Skip to content

Commit 32ec6d9

Browse files
authored
[SCEV] Make invalidation in SCEVCallbackVH more thorough (#68316)
When a SCEVCallbackVH is RAUWed, we currently do a def-use walk and remove dependent instructions from the ValueExprMap. However, unlike SCEVs usual invalidation, this does not forget memoized values. The end result is that we might end up removing a SCEVUnknown from the map, while that expression still has users. Due to that, we may later fail to invalide those expressions. In particular, invalidation of loop dispositions only does something if there is an expression for the value, which would not be the case here. Fix this by using the standard forgetValue() API, instead of rolling a custom variant. Fixes #68285.
1 parent f26fb3e commit 32ec6d9

File tree

3 files changed

+101
-31
lines changed

3 files changed

+101
-31
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13266,26 +13266,7 @@ void ScalarEvolution::SCEVCallbackVH::allUsesReplacedWith(Value *V) {
1326613266
// Forget all the expressions associated with users of the old value,
1326713267
// so that future queries will recompute the expressions using the new
1326813268
// value.
13269-
Value *Old = getValPtr();
13270-
SmallVector<User *, 16> Worklist(Old->users());
13271-
SmallPtrSet<User *, 8> Visited;
13272-
while (!Worklist.empty()) {
13273-
User *U = Worklist.pop_back_val();
13274-
// Deleting the Old value will cause this to dangle. Postpone
13275-
// that until everything else is done.
13276-
if (U == Old)
13277-
continue;
13278-
if (!Visited.insert(U).second)
13279-
continue;
13280-
if (PHINode *PN = dyn_cast<PHINode>(U))
13281-
SE->ConstantEvolutionLoopExitValue.erase(PN);
13282-
SE->eraseValueFromMap(U);
13283-
llvm::append_range(Worklist, U->users());
13284-
}
13285-
// Delete the Old value.
13286-
if (PHINode *PN = dyn_cast<PHINode>(Old))
13287-
SE->ConstantEvolutionLoopExitValue.erase(PN);
13288-
SE->eraseValueFromMap(Old);
13269+
SE->forgetValue(getValPtr());
1328913270
// this now dangles!
1329013271
}
1329113272

llvm/test/Transforms/IndVarSimplify/elim-extend.ll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,46 +114,46 @@ define void @nestedIV(ptr %address, i32 %limit) nounwind {
114114
; CHECK-LABEL: @nestedIV(
115115
; CHECK-NEXT: entry:
116116
; CHECK-NEXT: [[LIMITDEC:%.*]] = add i32 [[LIMIT:%.*]], -1
117+
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[LIMITDEC]] to i64
117118
; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[LIMIT]], i32 1)
118-
; CHECK-NEXT: [[WIDE_TRIP_COUNT4:%.*]] = zext i32 [[SMAX]] to i64
119+
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64
119120
; CHECK-NEXT: br label [[OUTERLOOP:%.*]]
120121
; CHECK: outerloop:
121122
; CHECK-NEXT: [[INDVARS_IV1:%.*]] = phi i64 [ [[INDVARS_IV_NEXT2:%.*]], [[OUTERMERGE:%.*]] ], [ 0, [[ENTRY:%.*]] ]
122123
; CHECK-NEXT: [[INNERCOUNT:%.*]] = phi i32 [ [[INNERCOUNT_MERGE:%.*]], [[OUTERMERGE]] ], [ 0, [[ENTRY]] ]
123-
; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[INDVARS_IV1]], -1
124-
; CHECK-NEXT: [[ADR1:%.*]] = getelementptr i8, ptr [[ADDRESS:%.*]], i64 [[TMP0]]
124+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV1]], -1
125+
; CHECK-NEXT: [[ADR1:%.*]] = getelementptr i8, ptr [[ADDRESS:%.*]], i64 [[TMP1]]
125126
; CHECK-NEXT: store i8 0, ptr [[ADR1]], align 1
126127
; CHECK-NEXT: br label [[INNERPREHEADER:%.*]]
127128
; CHECK: innerpreheader:
128129
; CHECK-NEXT: [[INNERPRECMP:%.*]] = icmp sgt i32 [[LIMITDEC]], [[INNERCOUNT]]
129130
; CHECK-NEXT: br i1 [[INNERPRECMP]], label [[INNERLOOP_PREHEADER:%.*]], label [[OUTERMERGE]]
130131
; CHECK: innerloop.preheader:
131-
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[INNERCOUNT]] to i64
132-
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = sext i32 [[LIMITDEC]] to i64
132+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[INNERCOUNT]] to i64
133133
; CHECK-NEXT: br label [[INNERLOOP:%.*]]
134134
; CHECK: innerloop:
135-
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP1]], [[INNERLOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[INNERLOOP]] ]
135+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP2]], [[INNERLOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[INNERLOOP]] ]
136136
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
137137
; CHECK-NEXT: [[ADR2:%.*]] = getelementptr i8, ptr [[ADDRESS]], i64 [[INDVARS_IV]]
138138
; CHECK-NEXT: store i8 0, ptr [[ADR2]], align 1
139139
; CHECK-NEXT: [[ADR3:%.*]] = getelementptr i8, ptr [[ADDRESS]], i64 [[INDVARS_IV_NEXT]]
140140
; CHECK-NEXT: store i8 0, ptr [[ADR3]], align 1
141-
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
141+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[TMP0]]
142142
; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNERLOOP]], label [[INNEREXIT:%.*]]
143143
; CHECK: innerexit:
144144
; CHECK-NEXT: [[INNERCOUNT_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV_NEXT]], [[INNERLOOP]] ]
145-
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INNERCOUNT_LCSSA_WIDE]] to i32
145+
; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INNERCOUNT_LCSSA_WIDE]] to i32
146146
; CHECK-NEXT: br label [[OUTERMERGE]]
147147
; CHECK: outermerge:
148-
; CHECK-NEXT: [[INNERCOUNT_MERGE]] = phi i32 [ [[TMP2]], [[INNEREXIT]] ], [ [[INNERCOUNT]], [[INNERPREHEADER]] ]
148+
; CHECK-NEXT: [[INNERCOUNT_MERGE]] = phi i32 [ [[TMP3]], [[INNEREXIT]] ], [ [[INNERCOUNT]], [[INNERPREHEADER]] ]
149149
; CHECK-NEXT: [[ADR4:%.*]] = getelementptr i8, ptr [[ADDRESS]], i64 [[INDVARS_IV1]]
150150
; CHECK-NEXT: store i8 0, ptr [[ADR4]], align 1
151151
; CHECK-NEXT: [[OFS5:%.*]] = sext i32 [[INNERCOUNT_MERGE]] to i64
152152
; CHECK-NEXT: [[ADR5:%.*]] = getelementptr i8, ptr [[ADDRESS]], i64 [[OFS5]]
153153
; CHECK-NEXT: store i8 0, ptr [[ADR5]], align 1
154154
; CHECK-NEXT: [[INDVARS_IV_NEXT2]] = add nuw nsw i64 [[INDVARS_IV1]], 1
155-
; CHECK-NEXT: [[EXITCOND5:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT2]], [[WIDE_TRIP_COUNT4]]
156-
; CHECK-NEXT: br i1 [[EXITCOND5]], label [[OUTERLOOP]], label [[RETURN:%.*]]
155+
; CHECK-NEXT: [[EXITCOND4:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT2]], [[WIDE_TRIP_COUNT]]
156+
; CHECK-NEXT: br i1 [[EXITCOND4]], label [[OUTERLOOP]], label [[RETURN:%.*]]
157157
; CHECK: return:
158158
; CHECK-NEXT: ret void
159159
;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2+
; RUN: opt -S -passes="loop-mssa(simple-loop-unswitch<nontrivial>),loop(loop-unroll-full),loop-simplify,verify<scalar-evolution>" < %s | FileCheck %s
3+
4+
; Should not caused a SCEV verification failure due to incorrect
5+
; loop dispositions.
6+
7+
define void @g(ptr %b, i32 %arg, i1 %tobool.not) {
8+
; CHECK-LABEL: define void @g(
9+
; CHECK-SAME: ptr [[B:%.*]], i32 [[ARG:%.*]], i1 [[TOBOOL_NOT:%.*]]) {
10+
; CHECK-NEXT: entry:
11+
; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
12+
; CHECK: entry.split.us:
13+
; CHECK-NEXT: br label [[FOR_BODY_US:%.*]]
14+
; CHECK: for.body.us:
15+
; CHECK-NEXT: br label [[LAND_END_US:%.*]]
16+
; CHECK: land.end.us:
17+
; CHECK-NEXT: store i16 0, ptr [[B]], align 1
18+
; CHECK-NEXT: br label [[FOR_END:%.*]]
19+
; CHECK: entry.split:
20+
; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]]
21+
; CHECK: for.body.peel.begin:
22+
; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]]
23+
; CHECK: for.body.peel:
24+
; CHECK-NEXT: br label [[LAND_RHS_PEEL:%.*]]
25+
; CHECK: land.rhs.peel:
26+
; CHECK-NEXT: [[AND_PEEL:%.*]] = and i32 -1, [[ARG]]
27+
; CHECK-NEXT: [[TOBOOL2_PEEL:%.*]] = icmp ne i32 [[AND_PEEL]], 0
28+
; CHECK-NEXT: [[DOTPRE_PEEL:%.*]] = load i32, ptr [[B]], align 1
29+
; CHECK-NEXT: br label [[LAND_END_PEEL:%.*]]
30+
; CHECK: land.end.peel:
31+
; CHECK-NEXT: [[IV2_PEEL:%.*]] = phi i32 [ [[DOTPRE_PEEL]], [[LAND_RHS_PEEL]] ]
32+
; CHECK-NEXT: [[IV3_PEEL:%.*]] = phi i1 [ [[TOBOOL2_PEEL]], [[LAND_RHS_PEEL]] ]
33+
; CHECK-NEXT: [[LAND_EXT_PEEL:%.*]] = zext i1 [[IV3_PEEL]] to i16
34+
; CHECK-NEXT: [[CMP3_PEEL:%.*]] = icmp ne i16 0, [[LAND_EXT_PEEL]]
35+
; CHECK-NEXT: [[CONV4_PEEL:%.*]] = zext i1 [[CMP3_PEEL]] to i16
36+
; CHECK-NEXT: store i16 [[LAND_EXT_PEEL]], ptr [[B]], align 1
37+
; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[IV2_PEEL]], 0
38+
; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END_SPLIT:%.*]]
39+
; CHECK: for.body.peel.next:
40+
; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT1:%.*]]
41+
; CHECK: for.body.peel.next1:
42+
; CHECK-NEXT: br label [[ENTRY_SPLIT_PEEL_NEWPH:%.*]]
43+
; CHECK: entry.split.peel.newph:
44+
; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp ne i32 [[ARG]], 0
45+
; CHECK-NEXT: [[LAND_EXT:%.*]] = zext i1 [[TOBOOL2]] to i16
46+
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
47+
; CHECK: for.body:
48+
; CHECK-NEXT: br label [[LAND_RHS:%.*]]
49+
; CHECK: land.rhs:
50+
; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[B]], align 1
51+
; CHECK-NEXT: br label [[LAND_END:%.*]]
52+
; CHECK: land.end:
53+
; CHECK-NEXT: store i16 [[LAND_EXT]], ptr [[B]], align 1
54+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DOTPRE]], 0
55+
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_SPLIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
56+
; CHECK: for.end.split.loopexit:
57+
; CHECK-NEXT: br label [[FOR_END_SPLIT]]
58+
; CHECK: for.end.split:
59+
; CHECK-NEXT: br label [[FOR_END]]
60+
; CHECK: for.end:
61+
; CHECK-NEXT: ret void
62+
;
63+
entry:
64+
br label %for.body
65+
66+
for.body: ; preds = %land.end, %entry
67+
%iv1 = phi i16 [ 0, %entry ], [ %trunc, %land.end ]
68+
br i1 %tobool.not, label %land.end, label %land.rhs
69+
70+
land.rhs: ; preds = %for.body
71+
%and = and i32 -1, %arg
72+
%tobool2 = icmp ne i32 %and, 0
73+
%.pre = load i32, ptr %b, align 1
74+
br label %land.end
75+
76+
land.end: ; preds = %land.rhs, %for.body
77+
%iv2 = phi i32 [ 0, %for.body ], [ %.pre, %land.rhs ]
78+
%iv3 = phi i1 [ false, %for.body ], [ %tobool2, %land.rhs ]
79+
%land.ext = zext i1 %iv3 to i16
80+
%cmp3 = icmp ne i16 %iv1, %land.ext
81+
%conv4 = zext i1 %cmp3 to i16
82+
store i16 %land.ext, ptr %b, align 1
83+
%cmp = icmp slt i32 %iv2, 0
84+
%trunc = trunc i32 %arg to i16
85+
br i1 %cmp, label %for.body, label %for.end
86+
87+
for.end: ; preds = %land.end
88+
ret void
89+
}

0 commit comments

Comments
 (0)