OSDN Git Service

[SCEV] Canonicalize "A /u C1 /u C2" to "A /u (C1*C2)".
authorTim Shen <timshen91@gmail.com>
Mon, 11 Jun 2018 18:44:58 +0000 (18:44 +0000)
committerTim Shen <timshen91@gmail.com>
Mon, 11 Jun 2018 18:44:58 +0000 (18:44 +0000)
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

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/fold.ll

index 8408616..d6e6401 100644 (file)
@@ -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;
index 226a24f..ba8f231 100644 (file)
@@ -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
+}