diff options
author | Bill Wendling <isanbard@gmail.com> | 2008-11-30 03:42:12 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2008-11-30 03:42:12 +0000 |
commit | 70635adea36679b98bbc87f196548ed42a244a29 (patch) | |
tree | fe7af1cafc273d136789464171d779f9a5062fe3 /llvm/lib | |
parent | 441042796d90a9319804efa16586a84786801525 (diff) | |
download | bcm5719-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.cpp | 23 |
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 |