Index: llvm/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/lib/Analysis/LoopInfo.cpp +++ llvm/lib/Analysis/LoopInfo.cpp @@ -364,17 +364,14 @@ } BranchInst *Loop::getLoopGuardBranch() const { - if (!isLoopSimplifyForm()) - return nullptr; - BasicBlock *Preheader = getLoopPreheader(); - assert(Preheader && getLoopLatch() && - "Expecting a loop with valid preheader and latch"); - + if (!Preheader) + return nullptr; + if (!getLoopLatch()) + return nullptr; // Loop should be in rotate form. if (!isRotatedForm()) return nullptr; - // Disallow loops with more than one unique exit block, as we do not verify // that GuardOtherSucc post dominates all exit blocks. BasicBlock *ExitFromLatch = getUniqueExitBlock(); @@ -384,7 +381,6 @@ BasicBlock *GuardBB = Preheader->getUniquePredecessor(); if (!GuardBB) return nullptr; - assert(GuardBB->getTerminator() && "Expecting valid guard terminator"); BranchInst *GuardBI = dyn_cast(GuardBB->getTerminator()); @@ -394,6 +390,12 @@ BasicBlock *GuardOtherSucc = (GuardBI->getSuccessor(0) == Preheader) ? GuardBI->getSuccessor(1) : GuardBI->getSuccessor(0); + if (!hasDedicatedExits()) { + if (ExitFromLatch->hasNPredecessors(2) && ExitFromLatch == GuardOtherSucc) { + return GuardBI; + } + return nullptr; + } // Check if ExitFromLatch (or any BasicBlock which is an empty unique // successor of ExitFromLatch) is equal to GuardOtherSucc. If Index: llvm/unittests/Analysis/LoopInfoTest.cpp =================================================================== --- llvm/unittests/Analysis/LoopInfoTest.cpp +++ llvm/unittests/Analysis/LoopInfoTest.cpp @@ -1547,3 +1547,43 @@ EXPECT_EQ(L->getLoopGuardBranch(), nullptr); }); } + +TEST(LoopInfoTest, NoDedicatedExitsButTheSameBBWithGuard) { + const char *ModuleStr = + "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" + "define void @foo(i32* %B, i64 signext %nx, i1 %cond) {\n" + "entry:\n" + " %cmp.guard = icmp slt i64 0, %nx\n" + " br i1 %cmp.guard, label %for.i.preheader, label %for.i.exit\n" + "for.i.preheader:\n" + " br label %for.i\n" + "for.i:\n" + " %i = phi i64 [ 0, %for.i.preheader ], [ %inc13, %for.i ]\n" + " %Bi = getelementptr inbounds i32, i32* %B, i64 %i\n" + " store i32 0, i32* %Bi, align 4\n" + " %inc13 = add nsw i64 %i, 1\n" + " %cmp = icmp slt i64 %inc13, %nx\n" + " br i1 %cmp, label %for.i, label %for.i.exit\n" + "for.i.exit:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { + Function::iterator FI = F.begin(); + assert(FI->getName() == "entry"); + + FI = ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.i"); + + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + EXPECT_EQ(L->isGuarded(), true); + EXPECT_NE(L->getLoopGuardBranch(), nullptr); + }); +}