diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 15 | ||||
-rw-r--r-- | llvm/test/Analysis/ScalarEvolution/fold.ll | 28 |
2 files changed, 43 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 840861653be..d6e64012126 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -3066,6 +3066,21 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, } } } + + // (A/B)/C --> A/(B*C) if safe and B*C can be folded. + if (const SCEVUDivExpr *OtherDiv = dyn_cast<SCEVUDivExpr>(LHS)) { + if (auto *DivisorConstant = + dyn_cast<SCEVConstant>(OtherDiv->getRHS())) { + bool Overflow = false; + APInt NewRHS = + DivisorConstant->getAPInt().umul_ov(RHSC->getAPInt(), Overflow); + if (Overflow) { + return getConstant(RHSC->getType(), 0, false); + } + return getUDivExpr(OtherDiv->getLHS(), getConstant(NewRHS)); + } + } + // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded. if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(LHS)) { SmallVector<const SCEV *, 4> Operands; diff --git a/llvm/test/Analysis/ScalarEvolution/fold.ll b/llvm/test/Analysis/ScalarEvolution/fold.ll index 226a24ff9c8..ba8f2310ba4 100644 --- a/llvm/test/Analysis/ScalarEvolution/fold.ll +++ b/llvm/test/Analysis/ScalarEvolution/fold.ll @@ -98,3 +98,31 @@ define void @test7(i32 %A) { ; CHECK-NEXT: --> 0 ret void } + +define i64 @test8(i64 %a) { +; CHECK-LABEL: @test8 + %t0 = udiv i64 %a, 56 + %t1 = udiv i64 %t0, 56 +; CHECK: %t1 +; CHECK-NEXT: --> (%a /u 3136) + ret i64 %t1 +} + +define i64 @test9(i64 %a) { +; CHECK-LABEL: @test9 + %t0 = udiv i64 %a, 100000000000000 + %t1 = udiv i64 %t0, 100000000000000 +; CHECK: %t1 +; CHECK-NEXT: --> 0 + ret i64 %t1 +} + +define i64 @test10(i64 %a, i64 %b) { +; CHECK-LABEL: @test9 + %t0 = udiv i64 %a, 100000000000000 + %t1 = udiv i64 %t0, 100000000000000 + %t2 = mul i64 %b, %t1 +; CHECK: %t2 +; CHECK-NEXT: --> 0 + ret i64 %t2 +} |