Skip to content

Commit 60b8520

Browse files
committed
[LoopDeletion] Forget loop before setting values to undef
After D71539, we need to forget the loop before setting the incoming values of phi nodes in exit blocks, because we are looking through those phi nodes now and the SCEV expression could depend on the loop phi. If we update the phi nodes before forgetting the loop, we miss those users during invalidation. Reviewed By: reames Differential Revision: https://reviews.llvm.org/D88167
1 parent 9100bd7 commit 60b8520

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

llvm/lib/Transforms/Scalar/LoopDeletion.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
165165

166166
if (ExitBlock && isLoopNeverExecuted(L)) {
167167
LLVM_DEBUG(dbgs() << "Loop is proven to never execute, delete it!");
168+
// We need to forget the loop before setting the incoming values of the exit
169+
// phis to undef, so we properly invalidate the SCEV expressions for those
170+
// phis.
171+
SE.forgetLoop(L);
168172
// Set incoming value to undef for phi nodes in the exit block.
169173
for (PHINode &P : ExitBlock->phis()) {
170174
std::fill(P.incoming_values().begin(), P.incoming_values().end(),

llvm/lib/Transforms/Utils/LoopUtils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,9 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
724724
}
725725
LI->destroy(L);
726726
}
727+
728+
if (SE)
729+
SE->verify();
727730
}
728731

729732
/// Checks if \p L has single exit through latch block except possibly

llvm/test/Transforms/LoopDeletion/update-scev.ll

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt -S -analyze -scalar-evolution -loop-deletion -scalar-evolution < %s | FileCheck %s --check-prefix=SCEV-EXPRS
1+
; RUN: opt -S -analyze -scalar-evolution -loop-deletion -scalar-evolution -verify-scev < %s | FileCheck %s --check-prefix=SCEV-EXPRS
22
; RUN: opt -S -loop-deletion < %s | FileCheck %s --check-prefix=IR-AFTER-TRANSFORM
33
; RUN: opt -S -indvars -loop-deletion -indvars < %s | FileCheck %s --check-prefix=ORIGINAL-CRASH
44

@@ -54,3 +54,115 @@ for.inc11: ; preds = %for.body6
5454
for.cond14: ; preds = %for.cond14, %for.inc11
5555
br i1 undef, label %for.cond, label %for.cond14
5656
}
57+
58+
; LoopDeletion removes the loop %for.body7.1. Make sure %inc.lcssa.1 in the loop
59+
; exit block is correctly invalidated.
60+
61+
define void @test2(double* %bx, i64 %by) local_unnamed_addr align 2 {
62+
; IR-AFTER-TRANSFORM-LABEL: @test2(
63+
; IR-AFTER-TRANSFORM-NOT: for.body7.1:
64+
65+
; SCEV-EXPRS-LABEL: test2
66+
; SCEV-EXPRS: %inc.lcssa.1 = phi i64 [ undef, %for.body7.preheader.1 ]
67+
; SCEV-EXPRS-NEXT: --> undef
68+
entry:
69+
%cmp = icmp sgt i64 %by, 0
70+
br label %for.cond.preheader
71+
72+
for.cond.preheader: ; preds = %entry
73+
br i1 %cmp, label %for.cond5.preheader.lr.ph, label %for.end14
74+
75+
for.cond5.preheader.lr.ph: ; preds = %for.cond.preheader
76+
br label %for.cond5.preheader
77+
78+
for.cond.loopexit.loopexit: ; preds = %for.body10
79+
%inc11.lcssa = phi i64 [ %inc11, %for.body10 ]
80+
br label %for.cond.loopexit
81+
82+
for.cond.loopexit: ; preds = %for.cond8.preheader, %for.cond.loopexit.loopexit
83+
%ca.3.lcssa = phi i64 [ %ca.2.lcssa, %for.cond8.preheader ], [ %inc11.lcssa, %for.cond.loopexit.loopexit ]
84+
br i1 %cmp, label %for.cond5.preheader, label %for.end14.loopexit
85+
86+
for.cond5.preheader: ; preds = %for.cond.loopexit, %for.cond5.preheader.lr.ph
87+
%ca.19 = phi i64 [ 0, %for.cond5.preheader.lr.ph ], [ %ca.3.lcssa, %for.cond.loopexit ]
88+
br i1 false, label %for.cond8.preheader, label %for.body7.preheader
89+
90+
for.body7.preheader: ; preds = %for.cond5.preheader
91+
br label %for.body7
92+
93+
for.cond8.preheader.loopexit: ; preds = %for.body7
94+
%inc.lcssa = phi i64 [ %inc, %for.body7 ]
95+
br label %for.cond8.preheader
96+
97+
for.cond8.preheader: ; preds = %for.cond8.preheader.loopexit, %for.cond5.preheader
98+
%ca.2.lcssa = phi i64 [ %ca.19, %for.cond5.preheader ], [ %inc.lcssa, %for.cond8.preheader.loopexit ]
99+
br i1 true, label %for.body10.preheader, label %for.cond.loopexit
100+
101+
for.body10.preheader: ; preds = %for.cond8.preheader
102+
br label %for.body10
103+
104+
for.body7: ; preds = %for.body7, %for.body7.preheader
105+
%ca.26 = phi i64 [ %inc, %for.body7 ], [ %ca.19, %for.body7.preheader ]
106+
%inc = add nsw i64 %ca.26, 1
107+
%arrayidx = getelementptr inbounds double, double* %bx, i64 %ca.26
108+
store double 0.000000e+00, double* %arrayidx, align 8
109+
br i1 false, label %for.cond8.preheader.loopexit, label %for.body7
110+
111+
for.body10: ; preds = %for.body10, %for.body10.preheader
112+
%ca.37 = phi i64 [ %inc11, %for.body10 ], [ %ca.2.lcssa, %for.body10.preheader ]
113+
%inc11 = add nsw i64 %ca.37, 1
114+
br i1 true, label %for.body10, label %for.cond.loopexit.loopexit
115+
116+
for.end14.loopexit: ; preds = %for.cond.loopexit
117+
br label %for.end14
118+
119+
for.end14: ; preds = %for.end14.loopexit, %for.cond.preheader
120+
br i1 %cmp, label %for.cond5.preheader.lr.ph.1, label %for.end14.1
121+
122+
for.cond5.preheader.lr.ph.1: ; preds = %for.end14
123+
br label %for.cond5.preheader.1
124+
125+
for.cond5.preheader.1: ; preds = %for.cond.loopexit.1, %for.cond5.preheader.lr.ph.1
126+
%ca.19.1 = phi i64 [ 0, %for.cond5.preheader.lr.ph.1 ], [ %ca.3.lcssa.1, %for.cond.loopexit.1 ]
127+
br i1 true, label %for.cond8.preheader.1, label %for.body7.preheader.1
128+
129+
for.body7.preheader.1: ; preds = %for.cond5.preheader.1
130+
br label %for.body7.1
131+
132+
for.body7.1: ; preds = %for.body7.1, %for.body7.preheader.1
133+
%ca.26.1 = phi i64 [ %inc.1, %for.body7.1 ], [ %ca.19.1, %for.body7.preheader.1 ]
134+
%inc.1 = add nsw i64 %ca.26.1, 1
135+
%arrayidx.1 = getelementptr inbounds double, double* %bx, i64 %ca.26.1
136+
store double 0.000000e+00, double* %arrayidx.1, align 8
137+
br i1 true, label %for.cond8.preheader.loopexit.1, label %for.body7.1
138+
139+
for.cond8.preheader.loopexit.1: ; preds = %for.body7.1
140+
%inc.lcssa.1 = phi i64 [ %inc.1, %for.body7.1 ]
141+
br label %for.cond8.preheader.1
142+
143+
for.cond8.preheader.1: ; preds = %for.cond8.preheader.loopexit.1, %for.cond5.preheader.1
144+
%ca.2.lcssa.1 = phi i64 [ %ca.19.1, %for.cond5.preheader.1 ], [ %inc.lcssa.1, %for.cond8.preheader.loopexit.1 ]
145+
br i1 false, label %for.body10.preheader.1, label %for.cond.loopexit.1
146+
147+
for.body10.preheader.1: ; preds = %for.cond8.preheader.1
148+
br label %for.body10.1
149+
150+
for.body10.1: ; preds = %for.body10.1, %for.body10.preheader.1
151+
%ca.37.1 = phi i64 [ %inc11.1, %for.body10.1 ], [ %ca.2.lcssa.1, %for.body10.preheader.1 ]
152+
%inc11.1 = add nsw i64 %ca.37.1, 1
153+
br i1 false, label %for.body10.1, label %for.cond.loopexit.loopexit.1
154+
155+
for.cond.loopexit.loopexit.1: ; preds = %for.body10.1
156+
%inc11.lcssa.1 = phi i64 [ %inc11.1, %for.body10.1 ]
157+
br label %for.cond.loopexit.1
158+
159+
for.cond.loopexit.1: ; preds = %for.cond.loopexit.loopexit.1, %for.cond8.preheader.1
160+
%ca.3.lcssa.1 = phi i64 [ %ca.2.lcssa.1, %for.cond8.preheader.1 ], [ %inc11.lcssa.1, %for.cond.loopexit.loopexit.1 ]
161+
br i1 %cmp, label %for.cond5.preheader.1, label %for.end14.loopexit.1
162+
163+
for.end14.loopexit.1: ; preds = %for.cond.loopexit.1
164+
br label %for.end14.1
165+
166+
for.end14.1: ; preds = %for.end14.loopexit.1, %for.end14
167+
ret void
168+
}

0 commit comments

Comments
 (0)