summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2008-11-30 03:42:12 +0000
committerBill Wendling <isanbard@gmail.com>2008-11-30 03:42:12 +0000
commit70635adea36679b98bbc87f196548ed42a244a29 (patch)
treefe7af1cafc273d136789464171d779f9a5062fe3 /llvm/lib
parent441042796d90a9319804efa16586a84786801525 (diff)
downloadbcm5719-llvm-70635adea36679b98bbc87f196548ed42a244a29.tar.gz
bcm5719-llvm-70635adea36679b98bbc87f196548ed42a244a29.zip
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. llvm-svn: 60275
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp23
1 files changed, 20 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index 9214b6bbd11..8461aa75e02 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -2956,9 +2956,26 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
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
OpenPOWER on IntegriCloud