llvm.org GIT mirror llvm / 511c1a3
[SCEV] Re-enable "Cache results of computeExitLimit" The patch rL309080 was reverted because it did not clean up the cache on "forgetValue" method call. This patch re-enables this change, adds the missing check and introduces two new unit tests that make sure that the cache is cleaned properly. Differential Revision: https://reviews.llvm.org/D36087 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309925 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 2 years ago
4 changed file(s) with 487 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
408408 }
409409 };
410410
411 struct ExitLimitQuery {
412 ExitLimitQuery(const Loop *L, BasicBlock *ExitingBlock, bool AllowPredicates)
413 : L(L), ExitingBlock(ExitingBlock), AllowPredicates(AllowPredicates) {}
414
415 const Loop *L;
416 BasicBlock *ExitingBlock;
417 bool AllowPredicates;
418 };
419
420 template <> struct DenseMapInfo {
421 static inline ExitLimitQuery getEmptyKey() {
422 return ExitLimitQuery(nullptr, nullptr, true);
423 }
424 static inline ExitLimitQuery getTombstoneKey() {
425 return ExitLimitQuery(nullptr, nullptr, false);
426 }
427 static unsigned getHashValue(ExitLimitQuery Val) {
428 return hash_combine(hash_combine(Val.L, Val.ExitingBlock),
429 Val.AllowPredicates);
430 }
431 static bool isEqual(ExitLimitQuery LHS, ExitLimitQuery RHS) {
432 return LHS.L == RHS.L && LHS.ExitingBlock == RHS.ExitingBlock &&
433 LHS.AllowPredicates == RHS.AllowPredicates;
434 }
435 };
436
411437 /// The main scalar evolution driver. Because client code (intentionally)
412438 /// can't do much with the SCEV objects directly, they must ask this class
413439 /// for services.
582608 return !isa(ExactNotTaken) ||
583609 !isa(MaxNotTaken);
584610 }
611
612 bool hasOperand(const SCEV *S) const;
585613
586614 /// Test whether this ExitLimit contains all information.
587615 bool hasFullInfo() const {
703731 /// function as they are computed.
704732 DenseMap PredicatedBackedgeTakenCounts;
705733
734 // Cache the calculated exit limits for the loops.
735 DenseMap ExitLimits;
736
706737 /// This map contains entries for all of the PHI instructions that we
707738 /// attempt to compute constant evolutions for. This allows us to avoid
708739 /// potentially expensive recomputation of these properties. An instruction
854885 /// return an exact answer.
855886 ExitLimit computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
856887 bool AllowPredicates = false);
888
889 ExitLimit computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,
890 bool AllowPredicates = false);
857891
858892 /// Compute the number of times the backedge of the specified loop will
859893 /// execute if its exit condition were a conditional branch of ExitCond,
10941128 /// to be a constant.
10951129 Optional computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
10961130
1097 /// Drop memoized information computed for S.
1098 void forgetMemoizedResults(const SCEV *S);
1131 /// Drop memoized information computed for S. Only erase Exit Limits info if
1132 /// we expect that the operation we have made is going to change it.
1133 void forgetMemoizedResults(const SCEV *S, bool EraseExitLimit = true);
10991134
11001135 /// Return an existing SCEV for V if there is one, otherwise return nullptr.
11011136 const SCEV *getExistingSCEV(Value *V);
61996199 // own when it gets to that point.
62006200 if (!isa(I) || !isa(Old)) {
62016201 eraseValueFromMap(It->first);
6202 forgetMemoizedResults(Old);
6202 forgetMemoizedResults(Old, false);
62036203 }
62046204 if (PHINode *PN = dyn_cast(I))
62056205 ConstantEvolutionLoopExitValue.erase(PN);
62616261 }
62626262
62636263 PushDefUseChildren(I, Worklist);
6264 }
6265
6266 for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) {
6267 auto &Query = I->first;
6268 if (Query.L == L)
6269 ExitLimits.erase(I);
62646270 }
62656271
62666272 // Forget all contained loops too, to avoid dangling entries in the
65256531 ScalarEvolution::ExitLimit
65266532 ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock,
65276533 bool AllowPredicates) {
6534 ExitLimitQuery Query(L, ExitingBlock, AllowPredicates);
6535 auto MaybeEL = ExitLimits.find(Query);
6536 if (MaybeEL != ExitLimits.end())
6537 return MaybeEL->second;
6538 ExitLimit EL = computeExitLimitImpl(L, ExitingBlock, AllowPredicates);
6539 ExitLimits.insert({Query, EL});
6540 return EL;
6541 }
6542
6543 ScalarEvolution::ExitLimit
6544 ScalarEvolution::computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock,
6545 bool AllowPredicates) {
65286546
65296547 // Okay, we've chosen an exiting block. See what condition causes us to exit
65306548 // at this block and remember the exit block and whether all other targets
1040710425 BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)),
1040810426 PredicatedBackedgeTakenCounts(
1040910427 std::move(Arg.PredicatedBackedgeTakenCounts)),
10428 ExitLimits(std::move(Arg.ExitLimits)),
1041010429 ConstantEvolutionLoopExitValue(
1041110430 std::move(Arg.ConstantEvolutionLoopExitValue)),
1041210431 ValuesAtScopes(std::move(Arg.ValuesAtScopes)),
1080910828 return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; });
1081010829 }
1081110830
10812 void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {
10831 bool ScalarEvolution::ExitLimit::hasOperand(const SCEV *S) const {
10832 auto IsS = [&](const SCEV *X) { return S == X; };
10833 auto ContainsS = [&](const SCEV *X) {
10834 return !isa(X) && SCEVExprContains(X, IsS);
10835 };
10836 return ContainsS(ExactNotTaken) || ContainsS(MaxNotTaken);
10837 }
10838
10839 void
10840 ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) {
1081310841 ValuesAtScopes.erase(S);
1081410842 LoopDispositions.erase(S);
1081510843 BlockDispositions.erase(S);
1084210870
1084310871 RemoveSCEVFromBackedgeMap(BackedgeTakenCounts);
1084410872 RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts);
10873
10874 // TODO: There is a suspicion that we only need to do it when there is a
10875 // SCEVUnknown somewhere inside S. Need to check this.
10876 if (EraseExitLimit)
10877 for (auto I = ExitLimits.begin(), E = ExitLimits.end(); I != E; ++I)
10878 if (I->second.hasOperand(S))
10879 ExitLimits.erase(I);
1084510880 }
1084610881
1084710882 void ScalarEvolution::verify() const {
0 ; RUN: opt -scalar-evolution-max-arith-depth=4 -scalar-evolution-max-add-rec-size=4 -loop-reduce -S < %s | FileCheck %s
1
2 ; Check that the test does not hang.
3 define void @test_01(i32* nocapture %a) local_unnamed_addr {
4
5 ; CHECK-LABEL: @test_01(
6
7 while.body.outer:
8 %arrayidx2 = getelementptr inbounds i32, i32* %a, i64 96
9 %arrayidx2.promoted50 = load i32, i32* %arrayidx2, align 1
10 %a.promoted = load i32, i32* %a, align 1
11 %add347.peel = xor i32 %arrayidx2.promoted50, -1
12 %tobool48.peel = icmp eq i32 %a.promoted, %add347.peel
13 br i1 %tobool48.peel, label %while.body.preheader, label %while.body4.preheader
14
15 while.body.preheader: ; preds = %while.body.outer
16 %tobool48 = icmp eq i32 %a.promoted, 1
17 br label %while.body
18
19 while.body: ; preds = %while.body.preheader, %while.body
20 br i1 %tobool48, label %while.body, label %while.body4.preheader.loopexit
21
22 while.body4.preheader.loopexit: ; preds = %while.body
23 br label %while.body4.preheader
24
25 while.body4.preheader: ; preds = %while.body4.preheader.loopexit, %while.body.outer
26 br label %while.body4
27
28 while.body4: ; preds = %while.body4.preheader, %while.end.22
29 %0 = phi i32 [ %mul.22, %while.end.22 ], [ %arrayidx2.promoted50, %while.body4.preheader ]
30 %mul = mul nsw i32 %0, %0
31 br label %while.cond17
32
33 while.cond17: ; preds = %while.cond17, %while.body4
34 %add22.sink = phi i32 [ %add22, %while.cond17 ], [ %mul, %while.body4 ]
35 %cmp = icmp slt i32 %add22.sink, 0
36 %add22 = add nsw i32 %add22.sink, 1024
37 br i1 %cmp, label %while.cond17, label %while.end
38
39 while.end: ; preds = %while.cond17
40 %mul.1 = mul nsw i32 %add22.sink, %add22.sink
41 br label %while.cond17.1
42
43 while.cond17.1: ; preds = %while.cond17.1, %while.end
44 %add22.sink.1 = phi i32 [ %add22.1, %while.cond17.1 ], [ %mul.1, %while.end ]
45 %cmp.1 = icmp slt i32 %add22.sink.1, 0
46 %add22.1 = add nsw i32 %add22.sink.1, 2048
47 br i1 %cmp.1, label %while.cond17.1, label %while.end.1
48
49 while.end.1: ; preds = %while.cond17.1
50 %mul.2 = mul nsw i32 %add22.sink.1, %add22.sink.1
51 br label %while.cond17.2
52
53 while.cond17.2: ; preds = %while.cond17.2, %while.end.1
54 %add22.sink.2 = phi i32 [ %add22.2, %while.cond17.2 ], [ %mul.2, %while.end.1 ]
55 %cmp.2 = icmp slt i32 %add22.sink.2, 0
56 %add22.2 = add nsw i32 %add22.sink.2, 4096
57 br i1 %cmp.2, label %while.cond17.2, label %while.end.2
58
59 while.end.2: ; preds = %while.cond17.2
60 %mul.3 = mul nsw i32 %add22.sink.2, %add22.sink.2
61 br label %while.cond17.3
62
63 while.cond17.3: ; preds = %while.cond17.3, %while.end.2
64 %add22.sink.3 = phi i32 [ %add22.3, %while.cond17.3 ], [ %mul.3, %while.end.2 ]
65 %cmp.3 = icmp slt i32 %add22.sink.3, 0
66 %add22.3 = add nsw i32 %add22.sink.3, 8192
67 br i1 %cmp.3, label %while.cond17.3, label %while.end.3
68
69 while.end.3: ; preds = %while.cond17.3
70 %mul.4 = mul nsw i32 %add22.sink.3, %add22.sink.3
71 br label %while.cond17.4
72
73 while.cond17.4: ; preds = %while.cond17.4, %while.end.3
74 %add22.sink.4 = phi i32 [ %add22.4, %while.cond17.4 ], [ %mul.4, %while.end.3 ]
75 %cmp.4 = icmp slt i32 %add22.sink.4, 0
76 %add22.4 = add nsw i32 %add22.sink.4, 16384
77 br i1 %cmp.4, label %while.cond17.4, label %while.end.4
78
79 while.end.4: ; preds = %while.cond17.4
80 %mul.5 = mul nsw i32 %add22.sink.4, %add22.sink.4
81 br label %while.cond17.5
82
83 while.cond17.5: ; preds = %while.cond17.5, %while.end.4
84 %add22.sink.5 = phi i32 [ %add22.5, %while.cond17.5 ], [ %mul.5, %while.end.4 ]
85 %cmp.5 = icmp slt i32 %add22.sink.5, 0
86 %add22.5 = add nsw i32 %add22.sink.5, 32768
87 br i1 %cmp.5, label %while.cond17.5, label %while.end.5
88
89 while.end.5: ; preds = %while.cond17.5
90 %mul.6 = mul nsw i32 %add22.sink.5, %add22.sink.5
91 br label %while.cond17.6
92
93 while.cond17.6: ; preds = %while.cond17.6, %while.end.5
94 %add22.sink.6 = phi i32 [ %add22.6, %while.cond17.6 ], [ %mul.6, %while.end.5 ]
95 %cmp.6 = icmp slt i32 %add22.sink.6, 0
96 %add22.6 = add nsw i32 %add22.sink.6, 65536
97 br i1 %cmp.6, label %while.cond17.6, label %while.end.6
98
99 while.end.6: ; preds = %while.cond17.6
100 %mul.7 = mul nsw i32 %add22.sink.6, %add22.sink.6
101 br label %while.cond17.7
102
103 while.cond17.7: ; preds = %while.cond17.7, %while.end.6
104 %add22.sink.7 = phi i32 [ %add22.7, %while.cond17.7 ], [ %mul.7, %while.end.6 ]
105 %cmp.7 = icmp slt i32 %add22.sink.7, 0
106 %add22.7 = add nsw i32 %add22.sink.7, 131072
107 br i1 %cmp.7, label %while.cond17.7, label %while.end.7
108
109 while.end.7: ; preds = %while.cond17.7
110 %mul.8 = mul nsw i32 %add22.sink.7, %add22.sink.7
111 br label %while.cond17.8
112
113 while.cond17.8: ; preds = %while.cond17.8, %while.end.7
114 %add22.sink.8 = phi i32 [ %add22.8, %while.cond17.8 ], [ %mul.8, %while.end.7 ]
115 %cmp.8 = icmp slt i32 %add22.sink.8, 0
116 %add22.8 = add nsw i32 %add22.sink.8, 262144
117 br i1 %cmp.8, label %while.cond17.8, label %while.end.8
118
119 while.end.8: ; preds = %while.cond17.8
120 %mul.9 = mul nsw i32 %add22.sink.8, %add22.sink.8
121 br label %while.cond17.9
122
123 while.cond17.9: ; preds = %while.cond17.9, %while.end.8
124 %add22.sink.9 = phi i32 [ %add22.9, %while.cond17.9 ], [ %mul.9, %while.end.8 ]
125 %cmp.9 = icmp slt i32 %add22.sink.9, 0
126 %add22.9 = add nsw i32 %add22.sink.9, 524288
127 br i1 %cmp.9, label %while.cond17.9, label %while.end.9
128
129 while.end.9: ; preds = %while.cond17.9
130 %mul.10 = mul nsw i32 %add22.sink.9, %add22.sink.9
131 br label %while.cond17.10
132
133 while.cond17.10: ; preds = %while.cond17.10, %while.end.9
134 %add22.sink.10 = phi i32 [ %add22.10, %while.cond17.10 ], [ %mul.10, %while.end.9 ]
135 %cmp.10 = icmp slt i32 %add22.sink.10, 0
136 %add22.10 = add nsw i32 %add22.sink.10, 1048576
137 br i1 %cmp.10, label %while.cond17.10, label %while.end.10
138
139 while.end.10: ; preds = %while.cond17.10
140 %mul.11 = mul nsw i32 %add22.sink.10, %add22.sink.10
141 br label %while.cond17.11
142
143 while.cond17.11: ; preds = %while.cond17.11, %while.end.10
144 %add22.sink.11 = phi i32 [ %add22.11, %while.cond17.11 ], [ %mul.11, %while.end.10 ]
145 %cmp.11 = icmp slt i32 %add22.sink.11, 0
146 %add22.11 = add nsw i32 %add22.sink.11, 2097152
147 br i1 %cmp.11, label %while.cond17.11, label %while.end.11
148
149 while.end.11: ; preds = %while.cond17.11
150 %mul.12 = mul nsw i32 %add22.sink.11, %add22.sink.11
151 br label %while.cond17.12
152
153 while.cond17.12: ; preds = %while.cond17.12, %while.end.11
154 %add22.sink.12 = phi i32 [ %add22.12, %while.cond17.12 ], [ %mul.12, %while.end.11 ]
155 %cmp.12 = icmp slt i32 %add22.sink.12, 0
156 %add22.12 = add nsw i32 %add22.sink.12, 4194304
157 br i1 %cmp.12, label %while.cond17.12, label %while.end.12
158
159 while.end.12: ; preds = %while.cond17.12
160 %mul.13 = mul nsw i32 %add22.sink.12, %add22.sink.12
161 br label %while.cond17.13
162
163 while.cond17.13: ; preds = %while.cond17.13, %while.end.12
164 %add22.sink.13 = phi i32 [ %add22.13, %while.cond17.13 ], [ %mul.13, %while.end.12 ]
165 %cmp.13 = icmp slt i32 %add22.sink.13, 0
166 %add22.13 = add nsw i32 %add22.sink.13, 8388608
167 br i1 %cmp.13, label %while.cond17.13, label %while.end.13
168
169 while.end.13: ; preds = %while.cond17.13
170 %mul.14 = mul nsw i32 %add22.sink.13, %add22.sink.13
171 br label %while.cond17.14
172
173 while.cond17.14: ; preds = %while.cond17.14, %while.end.13
174 %add22.sink.14 = phi i32 [ %add22.14, %while.cond17.14 ], [ %mul.14, %while.end.13 ]
175 %cmp.14 = icmp slt i32 %add22.sink.14, 0
176 %add22.14 = add nsw i32 %add22.sink.14, 16777216
177 br i1 %cmp.14, label %while.cond17.14, label %while.end.14
178
179 while.end.14: ; preds = %while.cond17.14
180 %mul.15 = mul nsw i32 %add22.sink.14, %add22.sink.14
181 br label %while.cond17.15
182
183 while.cond17.15: ; preds = %while.cond17.15, %while.end.14
184 %add22.sink.15 = phi i32 [ %add22.15, %while.cond17.15 ], [ %mul.15, %while.end.14 ]
185 %cmp.15 = icmp slt i32 %add22.sink.15, 0
186 %add22.15 = add nsw i32 %add22.sink.15, 33554432
187 br i1 %cmp.15, label %while.cond17.15, label %while.end.15
188
189 while.end.15: ; preds = %while.cond17.15
190 %mul.16 = mul nsw i32 %add22.sink.15, %add22.sink.15
191 br label %while.cond17.16
192
193 while.cond17.16: ; preds = %while.cond17.16, %while.end.15
194 %add22.sink.16 = phi i32 [ %add22.16, %while.cond17.16 ], [ %mul.16, %while.end.15 ]
195 %cmp.16 = icmp slt i32 %add22.sink.16, 0
196 %add22.16 = add nsw i32 %add22.sink.16, 67108864
197 br i1 %cmp.16, label %while.cond17.16, label %while.end.16
198
199 while.end.16: ; preds = %while.cond17.16
200 %mul.17 = mul nsw i32 %add22.sink.16, %add22.sink.16
201 br label %while.cond17.17
202
203 while.cond17.17: ; preds = %while.cond17.17, %while.end.16
204 %add22.sink.17 = phi i32 [ %add22.17, %while.cond17.17 ], [ %mul.17, %while.end.16 ]
205 %cmp.17 = icmp slt i32 %add22.sink.17, 0
206 %add22.17 = add nsw i32 %add22.sink.17, 134217728
207 br i1 %cmp.17, label %while.cond17.17, label %while.end.17
208
209 while.end.17: ; preds = %while.cond17.17
210 %mul.18 = mul nsw i32 %add22.sink.17, %add22.sink.17
211 br label %while.cond17.18
212
213 while.cond17.18: ; preds = %while.cond17.18, %while.end.17
214 %add22.sink.18 = phi i32 [ %add22.18, %while.cond17.18 ], [ %mul.18, %while.end.17 ]
215 %cmp.18 = icmp slt i32 %add22.sink.18, 0
216 %add22.18 = add nsw i32 %add22.sink.18, 268435456
217 br i1 %cmp.18, label %while.cond17.18, label %while.end.18
218
219 while.end.18: ; preds = %while.cond17.18
220 %mul.19 = mul nsw i32 %add22.sink.18, %add22.sink.18
221 br label %while.cond17.19
222
223 while.cond17.19: ; preds = %while.cond17.19, %while.end.18
224 %add22.sink.19 = phi i32 [ %add22.19, %while.cond17.19 ], [ %mul.19, %while.end.18 ]
225 %cmp.19 = icmp slt i32 %add22.sink.19, 0
226 %add22.19 = add nsw i32 %add22.sink.19, 536870912
227 br i1 %cmp.19, label %while.cond17.19, label %while.end.19
228
229 while.end.19: ; preds = %while.cond17.19
230 %mul.20 = mul nsw i32 %add22.sink.19, %add22.sink.19
231 br label %while.cond17.20
232
233 while.cond17.20: ; preds = %while.cond17.20, %while.end.19
234 %add22.sink.20 = phi i32 [ %add22.20, %while.cond17.20 ], [ %mul.20, %while.end.19 ]
235 %cmp.20 = icmp slt i32 %add22.sink.20, 0
236 %add22.20 = add nsw i32 %add22.sink.20, 1073741824
237 br i1 %cmp.20, label %while.cond17.20, label %while.end.20
238
239 while.end.20: ; preds = %while.cond17.20
240 %mul.21 = mul nsw i32 %add22.sink.20, %add22.sink.20
241 br label %while.cond17.21
242
243 while.cond17.21: ; preds = %while.cond17.21, %while.end.20
244 %add22.sink.21 = phi i32 [ %add22.21, %while.cond17.21 ], [ %mul.21, %while.end.20 ]
245 %cmp.21 = icmp slt i32 %add22.sink.21, 0
246 %add22.21 = or i32 %add22.sink.21, -2147483648
247 br i1 %cmp.21, label %while.cond17.21, label %while.end.22
248
249 while.end.22: ; preds = %while.cond17.21
250 %mul.22 = mul nsw i32 %add22.sink.21, %add22.sink.21
251 br label %while.body4
252 }
929929 EXPECT_FALSE(verifyFunction(*F, &errs()));
930930 }
931931
932 // Make sure that SCEV invalidates exit limits after invalidating the values it
933 // depends on when we forget a loop.
934 TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetLoop) {
935 /*
936 * Create the following code:
937 * func(i64 addrspace(10)* %arg)
938 * top:
939 * br label %L.ph
940 * L.ph:
941 * br label %L
942 * L:
943 * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
944 * %add = add i64 %phi2, 1
945 * %cond = icmp slt i64 %add, 1000; then becomes 2000.
946 * br i1 %cond, label %post, label %L2
947 * post:
948 * ret void
949 *
950 */
951
952 // Create a module with non-integral pointers in it's datalayout
953 Module NIM("nonintegral", Context);
954 std::string DataLayout = M.getDataLayoutStr();
955 if (!DataLayout.empty())
956 DataLayout += "-";
957 DataLayout += "ni:10";
958 NIM.setDataLayout(DataLayout);
959
960 Type *T_int64 = Type::getInt64Ty(Context);
961 Type *T_pint64 = T_int64->getPointerTo(10);
962
963 FunctionType *FTy =
964 FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
965 Function *F = cast(NIM.getOrInsertFunction("foo", FTy));
966
967 Argument *Arg = &*F->arg_begin();
968
969 BasicBlock *Top = BasicBlock::Create(Context, "top", F);
970 BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
971 BasicBlock *L = BasicBlock::Create(Context, "L", F);
972 BasicBlock *Post = BasicBlock::Create(Context, "post", F);
973
974 IRBuilder<> Builder(Top);
975 Builder.CreateBr(LPh);
976
977 Builder.SetInsertPoint(LPh);
978 Builder.CreateBr(L);
979
980 Builder.SetInsertPoint(L);
981 PHINode *Phi = Builder.CreatePHI(T_int64, 2);
982 auto *Add = cast(
983 Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));
984 auto *Limit = ConstantInt::get(T_int64, 1000);
985 auto *Cond = cast(
986 Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Limit, "cond"));
987 auto *Br = cast(Builder.CreateCondBr(Cond, L, Post));
988 Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
989 Phi->addIncoming(Add, L);
990
991 Builder.SetInsertPoint(Post);
992 Builder.CreateRetVoid();
993
994 ScalarEvolution SE = buildSE(*F);
995 auto *Loop = LI->getLoopFor(L);
996 const SCEV *EC = SE.getBackedgeTakenCount(Loop);
997 EXPECT_FALSE(isa(EC));
998
999 SE.forgetLoop(Loop);
1000 Br->eraseFromParent();
1001 Cond->eraseFromParent();
1002
1003 Builder.SetInsertPoint(L);
1004 Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000),
1005 "new.cond");
1006 Builder.CreateCondBr(Cond, L, Post);
1007 const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);
1008 EXPECT_NE(EC, NewEC);
1009 }
1010
1011 // Make sure that SCEV invalidates exit limits after invalidating the values it
1012 // depends on when we forget a value.
1013 TEST_F(ScalarEvolutionsTest, SCEVExitLimitForgetValue) {
1014 /*
1015 * Create the following code:
1016 * func(i64 addrspace(10)* %arg)
1017 * top:
1018 * br label %L.ph
1019 * L.ph:
1020 * %load = load i64 addrspace(10)* %arg
1021 * br label %L
1022 * L:
1023 * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
1024 * %add = add i64 %phi2, 1
1025 * %cond = icmp slt i64 %add, %load ; then becomes 2000.
1026 * br i1 %cond, label %post, label %L2
1027 * post:
1028 * ret void
1029 *
1030 */
1031
1032 // Create a module with non-integral pointers in it's datalayout
1033 Module NIM("nonintegral", Context);
1034 std::string DataLayout = M.getDataLayoutStr();
1035 if (!DataLayout.empty())
1036 DataLayout += "-";
1037 DataLayout += "ni:10";
1038 NIM.setDataLayout(DataLayout);
1039
1040 Type *T_int64 = Type::getInt64Ty(Context);
1041 Type *T_pint64 = T_int64->getPointerTo(10);
1042
1043 FunctionType *FTy =
1044 FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
1045 Function *F = cast(NIM.getOrInsertFunction("foo", FTy));
1046
1047 Argument *Arg = &*F->arg_begin();
1048
1049 BasicBlock *Top = BasicBlock::Create(Context, "top", F);
1050 BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
1051 BasicBlock *L = BasicBlock::Create(Context, "L", F);
1052 BasicBlock *Post = BasicBlock::Create(Context, "post", F);
1053
1054 IRBuilder<> Builder(Top);
1055 Builder.CreateBr(LPh);
1056
1057 Builder.SetInsertPoint(LPh);
1058 auto *Load = cast(Builder.CreateLoad(T_int64, Arg, "load"));
1059 Builder.CreateBr(L);
1060
1061 Builder.SetInsertPoint(L);
1062 PHINode *Phi = Builder.CreatePHI(T_int64, 2);
1063 auto *Add = cast(
1064 Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add"));
1065 auto *Cond = cast(
1066 Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, Load, "cond"));
1067 auto *Br = cast(Builder.CreateCondBr(Cond, L, Post));
1068 Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
1069 Phi->addIncoming(Add, L);
1070
1071 Builder.SetInsertPoint(Post);
1072 Builder.CreateRetVoid();
1073
1074 ScalarEvolution SE = buildSE(*F);
1075 auto *Loop = LI->getLoopFor(L);
1076 const SCEV *EC = SE.getBackedgeTakenCount(Loop);
1077 EXPECT_FALSE(isa(EC));
1078
1079 SE.forgetValue(Load);
1080 Br->eraseFromParent();
1081 Cond->eraseFromParent();
1082 Load->eraseFromParent();
1083
1084 Builder.SetInsertPoint(L);
1085 Builder.CreateICmp(ICmpInst::ICMP_SLT, Add, ConstantInt::get(T_int64, 2000),
1086 "new.cond");
1087 Builder.CreateCondBr(Cond, L, Post);
1088 const SCEV *NewEC = SE.getBackedgeTakenCount(Loop);
1089 EXPECT_NE(EC, NewEC);
1090 }
1091
9321092 } // end anonymous namespace
9331093 } // end namespace llvm