From 381326d77198f0b707f8a6d6beca649554d406b0 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 7 Jul 2015 09:15:29 +0000 Subject: [PATCH] [IR] Make getFirstNonPHI return null if the BB is empty getFirstNonPHI's documentation states that it returns null if there is no non-PHI instruction. However, it instead returns a pointer to the end iterator. The implementation of getFirstNonPHI claims that dereferencing the iterator will result in an assertion failure but this doesn't occur. Instead, machinery like getFirstInsertionPt will attempt to isa<> this invalid memory which results in unpredictable behavior. Instead, make getFirst* return null if no such instruction exists. llvm-svn: 241570 --- llvm/lib/IR/BasicBlock.cpp | 51 ++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 77cb10d5b6ba..0a0449434a7b 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -163,47 +163,40 @@ CallInst *BasicBlock::getTerminatingMustTailCall() { } Instruction* BasicBlock::getFirstNonPHI() { - BasicBlock::iterator i = begin(); - // All valid basic blocks should have a terminator, - // which is not a PHINode. If we have an invalid basic - // block we'll get an assertion failure when dereferencing - // a past-the-end iterator. - while (isa(i)) ++i; - return &*i; + for (Instruction &I : *this) + if (!isa(I)) + return &I; + return nullptr; } Instruction* BasicBlock::getFirstNonPHIOrDbg() { - BasicBlock::iterator i = begin(); - // All valid basic blocks should have a terminator, - // which is not a PHINode. If we have an invalid basic - // block we'll get an assertion failure when dereferencing - // a past-the-end iterator. - while (isa(i) || isa(i)) ++i; - return &*i; + for (Instruction &I : *this) + if (!isa(I) && !isa(I)) + return &I; + return nullptr; } Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() { - // All valid basic blocks should have a terminator, - // which is not a PHINode. If we have an invalid basic - // block we'll get an assertion failure when dereferencing - // a past-the-end iterator. - BasicBlock::iterator i = begin(); - for (;; ++i) { - if (isa(i) || isa(i)) + for (Instruction &I : *this) { + if (isa(I) || isa(I)) continue; - const IntrinsicInst *II = dyn_cast(i); - if (!II) - break; - if (II->getIntrinsicID() != Intrinsic::lifetime_start && - II->getIntrinsicID() != Intrinsic::lifetime_end) - break; + if (auto *II = dyn_cast(&I)) + if (II->getIntrinsicID() == Intrinsic::lifetime_start || + II->getIntrinsicID() == Intrinsic::lifetime_end) + continue; + + return &I; } - return &*i; + return nullptr; } BasicBlock::iterator BasicBlock::getFirstInsertionPt() { - iterator InsertPt = getFirstNonPHI(); + Instruction *FirstNonPHI = getFirstNonPHI(); + if (!FirstNonPHI) + return end(); + + iterator InsertPt = FirstNonPHI; if (isa(InsertPt)) ++InsertPt; return InsertPt; }