llvm.org GIT mirror llvm / 9baffb2
[SimplifyIndvar] Replace the srem used by IV if we can prove both of its operands are non-negative Since now SCEV can handle 'urem', an 'urem' is a better canonical form than an 'srem' because it has well-defined behavior This is a follow up of D34598 Differential Revision: https://reviews.llvm.org/D38072 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@314125 91177308-0d34-0410-b5e6-96231b3b80d8 Hongbin Zheng 2 years ago
3 changed file(s) with 201 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
3838 STATISTIC(
3939 NumSimplifiedSDiv,
4040 "Number of IV signed division operations converted to unsigned division");
41 STATISTIC(
42 NumSimplifiedSRem,
43 "Number of IV signed remainder operations converted to unsigned remainder");
4144 STATISTIC(NumElimCmp , "Number of IV comparisons eliminated");
4245
4346 namespace {
7679 bool eliminateOverflowIntrinsic(CallInst *CI);
7780 bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
7881 void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
79 void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
80 bool IsSigned);
82 void simplifyIVRemainder(BinaryOperator *Rem, Value *IVOperand,
83 bool IsSigned);
84 void replaceRemWithNumerator(BinaryOperator *Rem);
85 void replaceRemWithNumeratorOrZero(BinaryOperator *Rem);
86 void replaceSRemWithURem(BinaryOperator *Rem);
8187 bool eliminateSDiv(BinaryOperator *SDiv);
8288 bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand);
8389 bool strengthenRightShift(BinaryOperator *BO, Value *IVOperand);
308314 return false;
309315 }
310316
311 /// SimplifyIVUsers helper for eliminating useless
312 /// remainder operations operating on an induction variable.
313 void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem,
314 Value *IVOperand,
315 bool IsSigned) {
316 // We're only interested in the case where we know something about
317 // the numerator.
318 if (IVOperand != Rem->getOperand(0))
319 return;
320
321 // Get the SCEVs for the ICmp operands.
322 const SCEV *S = SE->getSCEV(Rem->getOperand(0));
323 const SCEV *X = SE->getSCEV(Rem->getOperand(1));
324
325 // Simplify unnecessary loops away.
326 const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
327 S = SE->getSCEVAtScope(S, ICmpLoop);
328 X = SE->getSCEVAtScope(X, ICmpLoop);
329
330 // i % n --> i if i is in [0,n).
331 if ((!IsSigned || SE->isKnownNonNegative(S)) &&
332 SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
333 S, X))
334 Rem->replaceAllUsesWith(Rem->getOperand(0));
335 else {
336 // (i+1) % n --> (i+1)==n?0:(i+1) if i is in [0,n).
337 const SCEV *LessOne = SE->getMinusSCEV(S, SE->getOne(S->getType()));
338 if (IsSigned && !SE->isKnownNonNegative(LessOne))
339 return;
340
341 if (!SE->isKnownPredicate(IsSigned ?
342 ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
343 LessOne, X))
344 return;
345
346 ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
347 Rem->getOperand(0), Rem->getOperand(1));
348 SelectInst *Sel =
349 SelectInst::Create(ICmp,
350 ConstantInt::get(Rem->getType(), 0),
351 Rem->getOperand(0), "tmp", Rem);
352 Rem->replaceAllUsesWith(Sel);
353 }
354
317 // i %s n -> i %u n if i >= 0 and n >= 0
318 void SimplifyIndvar::replaceSRemWithURem(BinaryOperator *Rem) {
319 auto *N = Rem->getOperand(0), *D = Rem->getOperand(1);
320 auto *URem = BinaryOperator::Create(BinaryOperator::URem, N, D,
321 Rem->getName() + ".urem", Rem);
322 Rem->replaceAllUsesWith(URem);
323 DEBUG(dbgs() << "INDVARS: Simplified srem: " << *Rem << '\n');
324 ++NumSimplifiedSRem;
325 DeadInsts.emplace_back(Rem);
326 }
327
328 // i % n --> i if i is in [0,n).
329 void SimplifyIndvar::replaceRemWithNumerator(BinaryOperator *Rem) {
330 Rem->replaceAllUsesWith(Rem->getOperand(0));
355331 DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
356332 ++NumElimRem;
357333 Changed = true;
358334 DeadInsts.emplace_back(Rem);
335 }
336
337 // (i+1) % n --> (i+1)==n?0:(i+1) if i is in [0,n).
338 void SimplifyIndvar::replaceRemWithNumeratorOrZero(BinaryOperator *Rem) {
339 auto *T = Rem->getType();
340 auto *N = Rem->getOperand(0), *D = Rem->getOperand(1);
341 ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ, N, D);
342 SelectInst *Sel =
343 SelectInst::Create(ICmp, ConstantInt::get(T, 0), N, "iv.rem", Rem);
344 Rem->replaceAllUsesWith(Sel);
345 DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
346 ++NumElimRem;
347 Changed = true;
348 DeadInsts.emplace_back(Rem);
349 }
350
351 /// SimplifyIVUsers helper for eliminating useless remainder operations
352 /// operating on an induction variable or replacing srem by urem.
353 void SimplifyIndvar::simplifyIVRemainder(BinaryOperator *Rem, Value *IVOperand,
354 bool IsSigned) {
355 auto *NValue = Rem->getOperand(0);
356 auto *DValue = Rem->getOperand(1);
357 // We're only interested in the case where we know something about
358 // the numerator, unless it is a srem, because we want to replace srem by urem
359 // in general.
360 bool UsedAsNumerator = IVOperand == NValue;
361 if (!UsedAsNumerator && !IsSigned)
362 return;
363
364 const SCEV *N = SE->getSCEV(NValue);
365
366 // Simplify unnecessary loops away.
367 const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
368 N = SE->getSCEVAtScope(N, ICmpLoop);
369
370 bool IsNumeratorNonNegative = !IsSigned || SE->isKnownNonNegative(N);
371
372 // Do not proceed if the Numerator may be negative
373 if (!IsNumeratorNonNegative)
374 return;
375
376 const SCEV *D = SE->getSCEV(DValue);
377 D = SE->getSCEVAtScope(D, ICmpLoop);
378
379 if (UsedAsNumerator) {
380 auto LT = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
381 if (SE->isKnownPredicate(LT, N, D)) {
382 replaceRemWithNumerator(Rem);
383 return;
384 }
385
386 auto *T = Rem->getType();
387 const auto *NLessOne = SE->getMinusSCEV(N, SE->getOne(T));
388 if (SE->isKnownPredicate(LT, NLessOne, D)) {
389 replaceRemWithNumeratorOrZero(Rem);
390 return;
391 }
392 }
393
394 // Try to replace SRem with URem, if both N and D are known non-negative.
395 // Since we had already check N, we only need to check D now
396 if (!IsSigned || !SE->isKnownNonNegative(D))
397 return;
398
399 replaceSRemWithURem(Rem);
400 Changed = true;
359401 }
360402
361403 bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) {
473515 if (BinaryOperator *Bin = dyn_cast(UseInst)) {
474516 bool IsSRem = Bin->getOpcode() == Instruction::SRem;
475517 if (IsSRem || Bin->getOpcode() == Instruction::URem) {
476 eliminateIVRemainder(Bin, IVOperand, IsSRem);
518 simplifyIVRemainder(Bin, IVOperand, IsSRem);
477519 return true;
478520 }
479521
3232
3333 ; Indvars should be able to eliminate the (i+1)%n.
3434 ; CHECK-LABEL: @f(
35 ; CHECK-NOT: rem
36 ; CHECK: rem
37 ; CHECK-NOT: rem
35 ; CHECK-NOT: {{[us]}}rem
36 ; CHECK: {{[us]}}rem
37 ; CHECK-NOT: {{[us]}}rem
3838 ; CHECK: ret
3939
4040 define i32 @f(i64* %arg, i64 %arg1, i64 %arg2, i64 %arg3) nounwind {
0 ; RUN: opt < %s -indvars -S | FileCheck %s
1
2 define void @test0(i32* %a) {
3 ; CHECK-LABEL: @test0(
4 entry:
5 br label %for.body
6
7 for.body: ; preds = %entry, %for.body
8 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
9 %rem = srem i32 %i.01, 2
10 ; CHECK-NOT: srem
11 ; CHECK: urem
12 %idxprom = sext i32 %rem to i64
13 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
14 store i32 %i.01, i32* %arrayidx, align 4
15 %inc = add nsw i32 %i.01, 1
16 %cmp = icmp slt i32 %inc, 64
17 br i1 %cmp, label %for.body, label %for.end
18
19 for.end: ; preds = %for.body
20 ret void
21 }
22
23 define void @test2(i32* %a, i32 %d) {
24 ; CHECK-LABEL: @test2(
25 entry:
26 br label %for.body
27
28 for.body: ; preds = %entry, %for.body
29 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
30 %mul = mul nsw i32 %i.01, 64
31 %rem = srem i32 %mul, %d
32 ; CHECK-NOT: urem
33 %idxprom = sext i32 %rem to i64
34 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
35 store i32 %i.01, i32* %arrayidx, align 4
36 %inc = add nsw i32 %i.01, 1
37 %cmp = icmp slt i32 %inc, 64
38 br i1 %cmp, label %for.body, label %for.end
39
40 for.end: ; preds = %for.body
41 ret void
42 }
43
44 define void @test3(i32* %a) {
45 ; CHECK-LABEL: @test3(
46 entry:
47 br label %for.body
48
49 for.body: ; preds = %entry, %for.body
50 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
51 %rem = srem i32 2048, %i.01
52 ; CHECK: urem
53 ; CHECK-NOT: srem
54 %idxprom = sext i32 %rem to i64
55 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
56 store i32 %i.01, i32* %arrayidx, align 4
57 %inc = add nsw i32 %i.01, 1
58 %cmp = icmp slt i32 %inc, 64
59 br i1 %cmp, label %for.body, label %for.end
60
61 for.end: ; preds = %for.body
62 ret void
63 }
64
65 define void @test4(i32* %a) {
66 ; CHECK-LABEL: @test4(
67 entry:
68 br label %for.body
69
70 for.body: ; preds = %entry, %for.body
71 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
72 %mul = mul nsw i32 %i.01, 64
73 %rem = srem i32 %mul, 8
74 ; CHECK: urem
75 ; CHECK-NOT: srem
76 %idxprom = sext i32 %rem to i64
77 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
78 store i32 %i.01, i32* %arrayidx, align 4
79 %inc = add nsw i32 %i.01, 1
80 %cmp = icmp slt i32 %inc, 64
81 br i1 %cmp, label %for.body, label %for.end
82
83 for.end: ; preds = %for.body
84 ret void
85 }
86
87 define void @test5(i32* %a) {
88 ; CHECK-LABEL: @test5(
89 entry:
90 br label %for.body
91
92 for.body: ; preds = %entry, %for.body
93 %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
94 %mul = mul nsw i32 %i.01, 64
95 %rem = srem i32 %mul, 6
96 ; CHECK: urem
97 ; CHECK-NOT: srem
98 %idxprom = sext i32 %rem to i64
99 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
100 store i32 %i.01, i32* %arrayidx, align 4
101 %inc = add nsw i32 %i.01, 1
102 %cmp = icmp slt i32 %inc, 64
103 br i1 %cmp, label %for.body, label %for.end
104
105 for.end: ; preds = %for.body
106 ret void
107 }
108