llvm.org GIT mirror llvm / 86fff1f
[IndVarSimplify] Teach calculatePostIncRange to take guards into account Reviewed By: sanjoy Differential Revision: https://reviews.llvm.org/D25739 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284632 91177308-0d34-0410-b5e6-96231b3b80d8 Artur Pilipenko 3 years ago
2 changed file(s) with 140 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
891891 ScalarEvolution *SE;
892892 DominatorTree *DT;
893893
894 // Does the module have any calls to the llvm.experimental.guard intrinsic
895 // at all? If not we can avoid scanning instructions looking for guards.
896 bool HasGuards;
897
894898 // Result
895899 PHINode *WidePhi;
896900 Instruction *WideInc;
937941 public:
938942 WidenIV(const WideIVInfo &WI, LoopInfo *LInfo,
939943 ScalarEvolution *SEv, DominatorTree *DTree,
940 SmallVectorImpl &DI) :
944 SmallVectorImpl &DI, bool HasGuards) :
941945 OrigPhi(WI.NarrowIV),
942946 WideType(WI.WidestNativeType),
943947 LI(LInfo),
944948 L(LI->getLoopFor(OrigPhi->getParent())),
945949 SE(SEv),
946950 DT(DTree),
951 HasGuards(HasGuards),
947952 WidePhi(nullptr),
948953 WideInc(nullptr),
949954 WideIncExpr(nullptr),
16081613 updatePostIncRangeInfo(NarrowDef, NarrowUser, NarrowDefRange);
16091614 };
16101615
1616 auto UpdateRangeFromGuards = [&](Instruction *Ctx) {
1617 if (!HasGuards)
1618 return;
1619
1620 for (Instruction &I : make_range(Ctx->getIterator().getReverse(),
1621 Ctx->getParent()->rend())) {
1622 Value *C = nullptr;
1623 if (match(&I, m_Intrinsic(m_Value(C))))
1624 UpdateRangeFromCondition(C, /*TrueDest=*/true);
1625 }
1626 };
1627
1628 UpdateRangeFromGuards(NarrowUser);
1629
16111630 BasicBlock *NarrowUserBB = NarrowUser->getParent();
16121631 // If NarrowUserBB is statically unreachable asking dominator queries may
16131632 // yield suprising results. (e.g. the block may not have a dom tree node)
16191638 DTB = DTB->getIDom()) {
16201639 auto *BB = DTB->getBlock();
16211640 auto *TI = BB->getTerminator();
1641 UpdateRangeFromGuards(TI);
16221642
16231643 auto *BI = dyn_cast(TI);
16241644 if (!BI || !BI->isConditional())
17091729 SCEVExpander &Rewriter,
17101730 LoopInfo *LI) {
17111731 SmallVector WideIVs;
1732
1733 auto *GuardDecl = L->getBlocks()[0]->getModule()->getFunction(
1734 Intrinsic::getName(Intrinsic::experimental_guard));
1735 bool HasGuards = GuardDecl && !GuardDecl->use_empty();
17121736
17131737 SmallVector LoopPhis;
17141738 for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) {
17391763 } while(!LoopPhis.empty());
17401764
17411765 for (; !WideIVs.empty(); WideIVs.pop_back()) {
1742 WidenIV Widener(WideIVs.back(), LI, SE, DT, DeadInsts);
1766 WidenIV Widener(WideIVs.back(), LI, SE, DT, DeadInsts, HasGuards);
17431767 if (PHINode *WidePhi = Widener.createWideIV(Rewriter)) {
17441768 Changed = true;
17451769 LoopPhis.push_back(WidePhi);
172172 exit:
173173 ret void
174174 }
175
176 declare void @llvm.experimental.guard(i1, ...)
177
178 define void @test_guard_one_bb(i32* %base, i32 %limit, i32 %start) {
179 ; CHECK-LABEL: @test_guard_one_bb(
180 ; CHECK-NOT: trunc
181 ; CHECK-NOT: icmp slt i32
182
183 for.body.lr.ph:
184 br label %for.body
185
186 for.body:
187 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
188 %within_limits = icmp ult i32 %i, 64
189 %i.i64 = zext i32 %i to i64
190 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
191 %val = load i32, i32* %arrayidx, align 4
192 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
193 %i.inc = add nsw nuw i32 %i, 1
194 %cmp = icmp slt i32 %i.inc, %limit
195 br i1 %cmp, label %for.body, label %for.end
196
197 for.end:
198 br label %exit
199
200 exit:
201 ret void
202 }
203
204 define void @test_guard_in_the_same_bb(i32* %base, i32 %limit, i32 %start) {
205 ; CHECK-LABEL: @test_guard_in_the_same_bb(
206 ; CHECK-NOT: trunc
207 ; CHECK-NOT: icmp slt i32
208
209 for.body.lr.ph:
210 br label %for.body
211
212 for.body:
213 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
214 %within_limits = icmp ult i32 %i, 64
215 %i.i64 = zext i32 %i to i64
216 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
217 %val = load i32, i32* %arrayidx, align 4
218 br label %for.inc
219
220 for.inc:
221 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
222 %i.inc = add nsw nuw i32 %i, 1
223 %cmp = icmp slt i32 %i.inc, %limit
224 br i1 %cmp, label %for.body, label %for.end
225
226 for.end:
227 br label %exit
228
229 exit:
230 ret void
231 }
232
233 define void @test_guard_in_idom(i32* %base, i32 %limit, i32 %start) {
234 ; CHECK-LABEL: @test_guard_in_idom(
235 ; CHECK-NOT: trunc
236 ; CHECK-NOT: icmp slt i32
237
238 for.body.lr.ph:
239 br label %for.body
240
241 for.body:
242 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
243 %within_limits = icmp ult i32 %i, 64
244 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
245 %i.i64 = zext i32 %i to i64
246 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
247 %val = load i32, i32* %arrayidx, align 4
248 br label %for.inc
249
250 for.inc:
251 %i.inc = add nsw nuw i32 %i, 1
252 %cmp = icmp slt i32 %i.inc, %limit
253 br i1 %cmp, label %for.body, label %for.end
254
255 for.end:
256 br label %exit
257
258 exit:
259 ret void
260 }
261
262 define void @test_guard_merge_ranges(i32* %base, i32 %limit, i32 %start) {
263 ; CHECK-LABEL: @test_guard_merge_ranges(
264 ; CHECK-NOT: trunc
265 ; CHECK-NOT: icmp slt i32
266
267 for.body.lr.ph:
268 br label %for.body
269
270 for.body:
271 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
272 %within_limits.1 = icmp ult i32 %i, 64
273 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ]
274 %within_limits.2 = icmp ult i32 %i, 2147483647
275 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ]
276 %i.i64 = zext i32 %i to i64
277 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
278 %val = load i32, i32* %arrayidx, align 4
279 %i.inc = add nsw nuw i32 %i, 1
280 %cmp = icmp slt i32 %i.inc, %limit
281 br i1 %cmp, label %for.body, label %for.end
282
283 for.end:
284 br label %exit
285
286 exit:
287 ret void
288 }