Fix bogus overflow checks by replacing them with actual
authorDan Gohman <gohman@apple.com>
Fri, 8 May 2009 23:11:16 +0000 (23:11 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 8 May 2009 23:11:16 +0000 (23:11 +0000)
overflow checks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71284 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/div-overflow.ll [new file with mode: 0644]

index 3ad542cd97ce1b4e07a9dd9897b54072ffa3b876..c53d1f5aaeabf21e7e782baea9a361a365463126 100644 (file)
@@ -1381,29 +1381,39 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
             dyn_cast<SCEVConstant>(AR->getStepRecurrence(*this)))
         if (!Step->getValue()->getValue()
               .urem(RHSC->getValue()->getValue()) &&
-            getTruncateExpr(getZeroExtendExpr(AR, ExtTy), Ty) == AR) {
+            getZeroExtendExpr(AR, ExtTy) ==
+            getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
+                          getZeroExtendExpr(Step, ExtTy),
+                          AR->getLoop())) {
           std::vector<SCEVHandle> Operands;
           for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i)
             Operands.push_back(getUDivExpr(AR->getOperand(i), RHS));
           return getAddRecExpr(Operands, AR->getLoop());
         }
     // (A*B)/C --> A*(B/C) if safe and B/C can be folded.
-    if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS))
-      if (getTruncateExpr(getZeroExtendExpr(M, ExtTy), Ty) == M)
+    if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS)) {
+      std::vector<SCEVHandle> Operands;
+      for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i)
+        Operands.push_back(getZeroExtendExpr(M->getOperand(i), ExtTy));
+      if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands))
         // Find an operand that's safely divisible.
         for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) {
           SCEVHandle Op = M->getOperand(i);
           SCEVHandle Div = getUDivExpr(Op, RHSC);
           if (!isa<SCEVUDivExpr>(Div) && getMulExpr(Div, RHSC) == Op) {
-            std::vector<SCEVHandle> Operands = M->getOperands();
+            Operands = M->getOperands();
             Operands[i] = Div;
             return getMulExpr(Operands);
           }
         }
+    }
     // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded.
-    if (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(LHS))
-      if (getTruncateExpr(getZeroExtendExpr(A, ExtTy), Ty) == A) {
-        std::vector<SCEVHandle> Operands;
+    if (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(LHS)) {
+      std::vector<SCEVHandle> Operands;
+      for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i)
+        Operands.push_back(getZeroExtendExpr(A->getOperand(i), ExtTy));
+      if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) {
+        Operands.clear();
         for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) {
           SCEVHandle Op = getUDivExpr(A->getOperand(i), RHS);
           if (isa<SCEVUDivExpr>(Op) || getMulExpr(Op, RHS) != A->getOperand(i))
@@ -1413,6 +1423,7 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
         if (Operands.size() == A->getNumOperands())
           return getAddExpr(Operands);
       }
+    }
 
     // Fold if both operands are constant.
     if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(LHS)) {
diff --git a/test/Analysis/ScalarEvolution/div-overflow.ll b/test/Analysis/ScalarEvolution/div-overflow.ll
new file mode 100644 (file)
index 0000000..cb64b85
--- /dev/null
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | opt -scalar-evolution -analyze -disable-output \
+; RUN:  | grep {\\-->  ((-128 \\* %a) /u -128)}
+
+; Don't let ScalarEvolution fold this div away.
+
+define i8 @foo(i8 %a) {
+        %t0 = shl i8 %a, 7
+        %t1 = lshr i8 %t0, 7
+        ret i8 %t1
+}