Index: llvm/include/llvm/Analysis/LoopInfo.h =================================================================== --- llvm/include/llvm/Analysis/LoopInfo.h +++ llvm/include/llvm/Analysis/LoopInfo.h @@ -58,6 +58,7 @@ class MDNode; class MemorySSAUpdater; class PHINode; +class PostDominatorTree; class ScalarEvolution; class raw_ostream; template class DominatorTreeBase; @@ -574,9 +575,9 @@ bool getIncomingAndBackEdge(BasicBlock *&Incoming, BasicBlock *&Backedge) const; - /// Below are some utilities to get loop bounds and induction variable, and - /// check if a given phinode is an auxiliary induction variable, as well as - /// checking if the loop is canonical. + /// Below are some utilities to get the loop guard, loop bounds and induction + /// variable, and to check if a given phinode is an auxiliary induction + /// variable, if the loop is guarded, and if the loop is canonical. /// /// Here is an example: /// \code @@ -608,6 +609,9 @@ /// /// - getInductionVariable --> i_1 /// - isAuxiliaryInductionVariable(x) --> true if x == i_1 + /// - getLoopGuardBranch() + /// --> `if (guardcmp) goto preheader; else goto afterloop` + /// - isGuarded() --> true /// - isCanonical --> false struct LoopBounds { /// Return the LoopBounds object if @@ -729,6 +733,19 @@ bool isAuxiliaryInductionVariable(PHINode &AuxIndVar, ScalarEvolution &SE) const; + /// Return the closest loop guard before the loop, by traversing up the + /// unique predecessor. + /// A conditional branch is considered as a loop guard iff + /// 1. one successor of the given branch instruction \p BI dominates the loop + /// header, + /// 2. the other successor postdominates the loop header, and + /// 3. there doesn't exist unsafe instructions guarded by the branch + /// instruction and not inside the loop, + BranchInst *getLoopGuardBranch(const PostDominatorTree *PDT = nullptr) const; + + /// Return true iff the loop is guarded by at least one loop guard branch. + bool isGuarded(const PostDominatorTree *PDT = nullptr) const; + /// Return true if the loop induction variable starts at zero and increments /// by one each time through the loop. bool isCanonical(ScalarEvolution &SE) const; Index: llvm/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/lib/Analysis/LoopInfo.cpp +++ llvm/lib/Analysis/LoopInfo.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" +#include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Config/llvm-config.h" @@ -359,6 +360,92 @@ return SE.isLoopInvariant(IndDesc.getStep(), this); } +BranchInst *Loop::getLoopGuardBranch(const PostDominatorTree *PDT) const { + BasicBlock *Header = getHeader(); + assert(Header && "Expecting a valid loop header"); + + // Get the first conditional branch from iterating up the unique predecessor + // of \p BeginBB. + auto GetClosestConditionalBranch = [](BasicBlock &BeginBB) -> BranchInst * { + BasicBlock *BB = &BeginBB; + SmallPtrSet Visited; + while (BB && BB->getUniqueSuccessor() && Visited.insert(BB).second) + BB = BB->getUniquePredecessor(); + if (!BB) + return nullptr; + + BranchInst *BI = dyn_cast_or_null(BB->getTerminator()); + if (BI && BI->isConditional()) + return BI; + + return nullptr; + }; + + /// Return true if there exists instructions which are unsafe, e.g. + /// instructions that may throw. + auto ContainsUnsafeInstructions = [&](const BasicBlock &BeginBB, + const BasicBlock &EndBB) { + assert(!PDT || PDT->dominates(&EndBB, Header) && + "Expecting EndBB to postdominate Header"); + + SmallVector WorkList; + WorkList.push_back(&BeginBB); + + while (!WorkList.empty()) { + const BasicBlock *Succ = WorkList.pop_back_val(); + if (Succ == &EndBB) + continue; + + if (Succ == Header) { + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + WorkList.append(ExitBlocks.begin(), ExitBlocks.end()); + continue; + } + + if (!isGuaranteedToTransferExecutionToSuccessor(Succ)) + return true; + + WorkList.append(successors(Succ).begin(), successors(Succ).end()); + } + + return false; + }; + + BranchInst *GuardBI = nullptr; + for (BasicBlock *Pred : predecessors(Header)) { + if (contains(Pred)) + continue; + + // There should only be one loop guard branch. + if (GuardBI) + return nullptr; + + // We are being conservative here, in case there are dynamically endless + // loops. + BranchInst *BI = GetClosestConditionalBranch(*Pred); + if (!BI) + return nullptr; + + BasicBlock *Succ0 = BI->getSuccessor(0); + BasicBlock *Succ1 = BI->getSuccessor(1); + BasicBlock *ExitBlock = getExitBlock(); + BasicBlock *ExitSucc = + ExitBlock ? ExitBlock->getUniqueSuccessor() : nullptr; + if ((((ExitSucc == Succ1) || (PDT && PDT->dominates(Succ1, Header))) && + !ContainsUnsafeInstructions(*Succ0, *Succ1)) || + (((ExitSucc == Succ0) || (PDT && PDT->dominates(Succ0, Header))) && + !ContainsUnsafeInstructions(*Succ1, *Succ0))) + GuardBI = BI; + } + + return GuardBI; +} + +bool Loop::isGuarded(const PostDominatorTree *PDT) const { + return (getLoopGuardBranch(PDT) != nullptr); +} + bool Loop::isCanonical(ScalarEvolution &SE) const { InductionDescriptor IndDesc; if (!getInductionDescriptor(SE, IndDesc)) Index: llvm/unittests/Analysis/LoopInfoTest.cpp =================================================================== --- llvm/unittests/Analysis/LoopInfoTest.cpp +++ llvm/unittests/Analysis/LoopInfoTest.cpp @@ -266,6 +266,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -287,6 +289,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -321,6 +327,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -342,6 +350,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -376,6 +388,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -397,6 +411,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -431,6 +449,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -452,6 +472,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -486,6 +510,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -507,6 +533,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -542,6 +572,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -563,6 +595,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -597,6 +633,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -615,6 +653,10 @@ EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -649,6 +691,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -670,6 +714,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -704,6 +752,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -725,6 +775,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Decreasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -754,32 +808,38 @@ LLVMContext Context; std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - runWithLoopInfoPlus(*M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - // - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), - ICmpInst::BAD_ICMP_PREDICATE); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Unknown); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); + // First two basic block are entry and for.preheader + // - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), + ICmpInst::BAD_ICMP_PREDICATE); + EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); + }); } TEST(LoopInfoTest, ZextIndVar) { @@ -816,6 +876,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -837,6 +899,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -888,6 +954,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), nullptr); + EXPECT_FALSE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), nullptr); + EXPECT_FALSE(L->isGuarded()); }); } @@ -921,6 +991,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -942,6 +1014,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -987,10 +1063,13 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *OuterGuard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.outer.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); assert(Header->getName() == "for.outer"); + BranchInst *InnerGuard = dyn_cast(Header->getTerminator()); Loop *L = LI.getLoopFor(Header); EXPECT_NE(L, nullptr); @@ -1008,6 +1087,10 @@ EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), OuterGuard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), OuterGuard); + EXPECT_TRUE(L->isGuarded()); // Next two basic blocks are for.outer and for.inner.preheader - skip // them. @@ -1030,6 +1113,10 @@ EXPECT_EQ(InnerBounds->getDirection(), Loop::LoopBounds::Direction::Increasing); EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), InnerGuard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), InnerGuard); + EXPECT_TRUE(L->isGuarded()); }); } @@ -1073,6 +1160,8 @@ [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, PostDominatorTree &PDT) { Function::iterator FI = F.begin(); + BasicBlock *Entry = &*(FI); + BranchInst *Guard = dyn_cast(Entry->getTerminator()); // First two basic block are entry and for.preheader - skip them. ++FI; BasicBlock *Header = &*(++FI); @@ -1108,6 +1197,10 @@ PHINode &Instruction_mulopcode = cast(*(++II)); EXPECT_FALSE( L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); + EXPECT_EQ(L->getLoopGuardBranch(&PDT), Guard); + EXPECT_TRUE(L->isGuarded(&PDT)); + EXPECT_EQ(L->getLoopGuardBranch(), Guard); + EXPECT_TRUE(L->isGuarded()); }); }