[llvm] 1f85e81 - [LoopInfo] Do not enqueue unreachable nodes; fix infinite loop (#214832)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 9 23:51:43 PDT 2026
Author: Pranav Kant
Date: 2026-08-10T06:51:38Z
New Revision: 1f85e810c9ae0e8f9f44a7373c5409d8e586ed06
URL: https://github.com/llvm/llvm-project/commit/1f85e810c9ae0e8f9f44a7373c5409d8e586ed06
DIFF: https://github.com/llvm/llvm-project/commit/1f85e810c9ae0e8f9f44a7373c5409d8e586ed06.diff
LOG: [LoopInfo] Do not enqueue unreachable nodes; fix infinite loop (#214832)
Before this patch, we were enqueing unreachable nodes reaching into the
latch nodes. Since unreachable nodes haven't been visited in the
original DFS algorithm, we end up in an infinite loop within enqueue
This patch restores isReachableFromEntry() check from now removed
discoverAndMapSubloop(). This should avoid infinite loop.
It's a regression from #212000
(5d582e4003b1cab59900d16fa3db9c3a9d16b462)
---------
Co-authored-by: Alexander Kornienko <alexfh at google.com>
Co-authored-by: Alexis Engelke <mail at aengelke.net>
Added:
Modified:
llvm/include/llvm/Support/GenericLoopInfoImpl.h
llvm/unittests/Analysis/LoopInfoTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/GenericLoopInfoImpl.h b/llvm/include/llvm/Support/GenericLoopInfoImpl.h
index c294583eb77fd..8cc0ce82c83ec 100644
--- a/llvm/include/llvm/Support/GenericLoopInfoImpl.h
+++ b/llvm/include/llvm/Support/GenericLoopInfoImpl.h
@@ -664,7 +664,9 @@ void LoopInfoBase<BlockT, LoopT>::analyze(
// Whatever reaches a latch without passing the header is in the loop.
for (unsigned I = 0; I != Worklist.size(); ++I)
for (BlockT *Pred : inverse_children<BlockT *>(Worklist[I]))
- enqueue(Pred);
+ // Do not enqueue any unreachable nodes.
+ if (Blocks[num(Pred)])
+ enqueue(Pred);
// Without a backedge the header forms no loop at all.
Info[H].Pos = HasBackedge ? IsHeader : OffPath;
// Partition the header's blocks: the loop keeps the ones the traversal
diff --git a/llvm/unittests/Analysis/LoopInfoTest.cpp b/llvm/unittests/Analysis/LoopInfoTest.cpp
index 5321f72aa1784..b909e434f7a5f 100644
--- a/llvm/unittests/Analysis/LoopInfoTest.cpp
+++ b/llvm/unittests/Analysis/LoopInfoTest.cpp
@@ -1646,3 +1646,46 @@ TEST(LoopInfoTest, TokenLCSSA) {
InnerLoop->isRecursivelyLCSSAForm(DT, LI, /*IgnoreTokens*/ false));
});
}
+
+TEST(LoopInfoTest, UnreachableBlock) {
+ const char *ModuleStr = "define void @irreducible_loop(i1 %c1, i1 %c2) {\n"
+ "dummy:\n"
+ " br label %entry\n"
+ "entry:\n"
+ " br i1 %c1, label %loop1, label %side_entry\n"
+ "dead_block:\n"
+ " br label %latch1\n"
+ "loop1:\n"
+ " br i1 %c2, label %body1, label %mid\n"
+ "body1:\n"
+ " br label %latch1\n"
+ "latch1:\n"
+ " br label %loop1\n"
+ "mid:\n"
+ " br label %latch2\n"
+ "latch2:\n"
+ " br label %loop1\n"
+ "side_entry:\n"
+ " br label %mid\n"
+ "}\n";
+
+ LLVMContext Context;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
+ ASSERT_TRUE(M);
+ Function *F = M->getFunction("irreducible_loop");
+ ASSERT_TRUE(F);
+
+ // Delete 'dummy' block so that block 0 is deleted and no block in the CFG has
+ // index 0.
+ BasicBlock *Dummy = &F->getEntryBlock();
+ Dummy->eraseFromParent();
+
+ DominatorTree DT(*F);
+ // This used to hang infinitely in analyze() due to an unvisited block
+ // reaching a latch.
+ LoopInfo LI(DT);
+
+ // Basic verification that a loop was found.
+ EXPECT_FALSE(LI.empty());
+}
More information about the llvm-commits
mailing list