From: Tim Shen Date: Mon, 11 Jun 2018 18:44:58 +0000 (+0000) Subject: [SCEV] Canonicalize "A /u C1 /u C2" to "A /u (C1*C2)". X-Git-Tag: android-x86-8.1-r1~2267 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=9299628cf440f16d3f4f78670ca5c465be3668fe;p=android-x86%2Fexternal-llvm.git [SCEV] Canonicalize "A /u C1 /u C2" to "A /u (C1*C2)". Summary: FWIW InstCombine already folds this. Also avoid the case where C1*C2 overflows. Reviewers: sunfish, sanjoy Subscribers: hiraditya, bixia, llvm-commits Differential Revision: https://reviews.llvm.org/D47965 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334425 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 840861653be..d6e64012126 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/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(LHS)) { + if (auto *DivisorConstant = + dyn_cast(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(LHS)) { SmallVector Operands; diff --git a/test/Analysis/ScalarEvolution/fold.ll b/test/Analysis/ScalarEvolution/fold.ll index 226a24ff9c8..ba8f2310ba4 100644 --- a/test/Analysis/ScalarEvolution/fold.ll +++ b/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 +}