Instcombine was illegally transforming -X/C into X/-C when either X or C
overflowed on negation. This commit checks to make sure that neithe C nor X
overflows. This requires that the RHS of X (a subtract instruction) be a
constant integer.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60275 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 9214b6b..8461aa7 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2956,9 +2956,26 @@
     if (RHS->isAllOnesValue())
       return BinaryOperator::CreateNeg(Op0);
 
-    // -X/C -> X/-C
-    if (Value *LHSNeg = dyn_castNegVal(Op0))
-      return BinaryOperator::CreateSDiv(LHSNeg, ConstantExpr::getNeg(RHS));
+    ConstantInt *RHSNeg = cast<ConstantInt>(ConstantExpr::getNeg(RHS));
+
+    // -X/C -> X/-C, if and only if negation doesn't overflow.
+    if ((RHS->getSExtValue() < 0 &&
+         RHS->getSExtValue() < RHSNeg->getSExtValue()) ||
+        (RHS->getSExtValue() > 0 &&
+         RHS->getSExtValue() > RHSNeg->getSExtValue())) {
+      if (Value *LHSNeg = dyn_castNegVal(Op0)) {
+        if (ConstantInt *CI = dyn_cast<ConstantInt>(LHSNeg)) {
+          ConstantInt *CINeg = cast<ConstantInt>(ConstantExpr::getNeg(CI));
+
+          if ((CI->getSExtValue() < 0 &&
+               CI->getSExtValue() < CINeg->getSExtValue()) ||
+              (CI->getSExtValue() > 0 &&
+               CI->getSExtValue() > CINeg->getSExtValue()))
+            return BinaryOperator::CreateSDiv(LHSNeg,
+                                              ConstantExpr::getNeg(RHS));
+        }
+      }
+    }
   }
 
   // If the sign bits of both operands are zero (i.e. we can prove they are