[llvm-branch-commits] [llvm] f66e874 - [LoopSimplifyCFG] Add check for missing loop preheader (#149743)
Tobias Hieta via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jul 24 02:58:47 PDT 2025
Author: Justus Klausecker
Date: 2025-07-24T11:58:40+02:00
New Revision: f66e8745047ea04958e13bf02bae75ab15805e3c
URL: https://github.com/llvm/llvm-project/commit/f66e8745047ea04958e13bf02bae75ab15805e3c
DIFF: https://github.com/llvm/llvm-project/commit/f66e8745047ea04958e13bf02bae75ab15805e3c.diff
LOG: [LoopSimplifyCFG] Add check for missing loop preheader (#149743)
Closes #147869
Closes #149679
Adds a check for a missing loop preheader during analysis. This fixes a
nullptr dereference that happened whenever LoopSimplify was unable to
generate a preheader because the loop was entered by an indirectbr
instruction (as stated in the LoopSimplify.cpp doc comment).
(cherry picked from commit 04107209856bb39e041aa38cf40de0afa90a6b2d)
Added:
llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll
Modified:
llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
index 221094f170ac7..b9546c5fa236b 100644
--- a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
@@ -128,6 +128,8 @@ class ConstantTerminatorFoldingImpl {
// from any other block. So this variable set to true means that loop's latch
// has become unreachable from loop header.
bool DeleteCurrentLoop = false;
+ // Whether or not we enter the loop through an indirectbr.
+ bool HasIndirectEntry = false;
// The blocks of the original loop that will still be reachable from entry
// after the constant folding.
@@ -216,6 +218,19 @@ class ConstantTerminatorFoldingImpl {
return;
}
+ // We need a loop preheader to split in handleDeadExits(). If LoopSimplify
+ // wasn't able to form one because the loop can be entered through an
+ // indirectbr we cannot continue.
+ if (!L.getLoopPreheader()) {
+ assert(any_of(predecessors(L.getHeader()),
+ [&](BasicBlock *Pred) {
+ return isa<IndirectBrInst>(Pred->getTerminator());
+ }) &&
+ "Loop should have preheader if it is not entered indirectly");
+ HasIndirectEntry = true;
+ return;
+ }
+
// Collect live and dead loop blocks and exits.
LiveLoopBlocks.insert(L.getHeader());
for (auto I = DFS.beginRPO(), E = DFS.endRPO(); I != E; ++I) {
@@ -546,6 +561,12 @@ class ConstantTerminatorFoldingImpl {
return false;
}
+ if (HasIndirectEntry) {
+ LLVM_DEBUG(dbgs() << "Loops which can be entered indirectly are not"
+ " supported!\n");
+ return false;
+ }
+
// Nothing to constant-fold.
if (FoldCandidates.empty()) {
LLVM_DEBUG(
diff --git a/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll b/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll
new file mode 100644
index 0000000000000..dd524ab7d140d
--- /dev/null
+++ b/llvm/test/Transforms/LoopSimplifyCFG/enter-through-indirectbr.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require<domtree>,loop(loop-simplifycfg)' -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
+
+define void @test(ptr %addr) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: ptr [[ADDR:%.*]]) {
+; CHECK-NEXT: indirectbr ptr [[ADDR]], [label %[[A:.*]], label %C]
+; CHECK: [[A]]:
+; CHECK-NEXT: br i1 true, label %[[B:.*]], label %[[C_LOOPEXIT:.*]]
+; CHECK: [[B]]:
+; CHECK-NEXT: br i1 true, label %[[A]], label %[[C_LOOPEXIT]]
+; CHECK: [[C_LOOPEXIT]]:
+; CHECK-NEXT: br label %[[C:.*]]
+; CHECK: [[C]]:
+; CHECK-NEXT: unreachable
+;
+
+ indirectbr ptr %addr, [label %A, label %C]
+
+A:
+ br i1 true, label %B, label %C
+
+B:
+ br i1 true, label %A, label %C
+
+C:
+ unreachable
+}
More information about the llvm-branch-commits
mailing list