Skip to content

Commit 0410720

Browse files
authored
[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).
1 parent 33bfbac commit 0410720

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class ConstantTerminatorFoldingImpl {
128128
// from any other block. So this variable set to true means that loop's latch
129129
// has become unreachable from loop header.
130130
bool DeleteCurrentLoop = false;
131+
// Whether or not we enter the loop through an indirectbr.
132+
bool HasIndirectEntry = false;
131133

132134
// The blocks of the original loop that will still be reachable from entry
133135
// after the constant folding.
@@ -216,6 +218,19 @@ class ConstantTerminatorFoldingImpl {
216218
return;
217219
}
218220

221+
// We need a loop preheader to split in handleDeadExits(). If LoopSimplify
222+
// wasn't able to form one because the loop can be entered through an
223+
// indirectbr we cannot continue.
224+
if (!L.getLoopPreheader()) {
225+
assert(any_of(predecessors(L.getHeader()),
226+
[&](BasicBlock *Pred) {
227+
return isa<IndirectBrInst>(Pred->getTerminator());
228+
}) &&
229+
"Loop should have preheader if it is not entered indirectly");
230+
HasIndirectEntry = true;
231+
return;
232+
}
233+
219234
// Collect live and dead loop blocks and exits.
220235
LiveLoopBlocks.insert(L.getHeader());
221236
for (auto I = DFS.beginRPO(), E = DFS.endRPO(); I != E; ++I) {
@@ -546,6 +561,12 @@ class ConstantTerminatorFoldingImpl {
546561
return false;
547562
}
548563

564+
if (HasIndirectEntry) {
565+
LLVM_DEBUG(dbgs() << "Loops which can be entered indirectly are not"
566+
" supported!\n");
567+
return false;
568+
}
569+
549570
// Nothing to constant-fold.
550571
if (FoldCandidates.empty()) {
551572
LLVM_DEBUG(
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; 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
3+
4+
define void @test(ptr %addr) {
5+
; CHECK-LABEL: define void @test(
6+
; CHECK-SAME: ptr [[ADDR:%.*]]) {
7+
; CHECK-NEXT: indirectbr ptr [[ADDR]], [label %[[A:.*]], label %C]
8+
; CHECK: [[A]]:
9+
; CHECK-NEXT: br i1 true, label %[[B:.*]], label %[[C_LOOPEXIT:.*]]
10+
; CHECK: [[B]]:
11+
; CHECK-NEXT: br i1 true, label %[[A]], label %[[C_LOOPEXIT]]
12+
; CHECK: [[C_LOOPEXIT]]:
13+
; CHECK-NEXT: br label %[[C:.*]]
14+
; CHECK: [[C]]:
15+
; CHECK-NEXT: unreachable
16+
;
17+
18+
indirectbr ptr %addr, [label %A, label %C]
19+
20+
A:
21+
br i1 true, label %B, label %C
22+
23+
B:
24+
br i1 true, label %A, label %C
25+
26+
C:
27+
unreachable
28+
}

0 commit comments

Comments
 (0)