diff options
author | Chris Lattner <sabre@nondot.org> | 2008-10-11 22:55:00 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-10-11 22:55:00 +0000 |
commit | a6321b40c22025b09c1bbff9df7f4b0470835b0b (patch) | |
tree | 23bd4ecb03c450667ab12192e6b753500d38e5e1 | |
parent | 1b8f4bb4a1a46e8a2295bdaf0454a5c302863703 (diff) | |
download | external_llvm-a6321b40c22025b09c1bbff9df7f4b0470835b0b.zip external_llvm-a6321b40c22025b09c1bbff9df7f4b0470835b0b.tar.gz external_llvm-a6321b40c22025b09c1bbff9df7f4b0470835b0b.tar.bz2 |
Fix PR2697 by rewriting the '(X / pos) op neg' logic. This also changes
a couple other cases for clarity, but shouldn't affect correctness.
Patch by Eli Friedman!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57387 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 25 | ||||
-rw-r--r-- | test/Transforms/InstCombine/2008-10-11-DivCompareFold.ll | 8 |
2 files changed, 23 insertions, 10 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 60da031..162e1bf 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -5784,6 +5784,11 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, return 0; if (DivRHS->isZero()) return 0; // The ProdOV computation fails on divide by zero. + if (DivIsSigned && DivRHS->isAllOnesValue()) + return 0; // The overflow computation also screws up here + if (DivRHS->isOne()) + return 0; // Not worth bothering, and eliminates some funny cases + // with INT_MIN. // Compute Prod = CI * DivRHS. We are essentially solving an equation // of form X/C1=C2. We solve for X by multiplying C1 (DivRHS) and @@ -5810,7 +5815,6 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, int LoOverflow = 0, HiOverflow = 0; ConstantInt *LoBound = 0, *HiBound = 0; - if (!DivIsSigned) { // udiv // e.g. X/5 op 3 --> [15, 20) LoBound = Prod; @@ -5829,11 +5833,13 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, HiOverflow = AddWithOverflow(HiBound, Prod, DivRHS, true); } else { // (X / pos) op neg // e.g. X/5 op -3 --> [-15-4, -15+1) --> [-19, -14) - Constant *DivRHSH = ConstantExpr::getNeg(SubOne(DivRHS)); - LoOverflow = AddWithOverflow(LoBound, Prod, - cast<ConstantInt>(DivRHSH), true) ? -1 : 0; HiBound = AddOne(Prod); - HiOverflow = ProdOV ? -1 : 0; + LoOverflow = HiOverflow = ProdOV ? -1 : 0; + if (!LoOverflow) { + ConstantInt* DivNeg = cast<ConstantInt>(ConstantExpr::getNeg(DivRHS)); + LoOverflow = AddWithOverflow(LoBound, HiBound, DivNeg, + true) ? -1 : 0; + } } } else if (DivRHS->getValue().isNegative()) { // Divisor is < 0. if (CmpRHSV == 0) { // (X / neg) op 0 @@ -5846,14 +5852,13 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, } } else if (CmpRHSV.isStrictlyPositive()) { // (X / neg) op pos // e.g. X/-5 op 3 --> [-19, -14) + HiBound = AddOne(Prod); HiOverflow = LoOverflow = ProdOV ? -1 : 0; if (!LoOverflow) - LoOverflow = AddWithOverflow(LoBound, Prod, AddOne(DivRHS), true) ?-1:0; - HiBound = AddOne(Prod); + LoOverflow = AddWithOverflow(LoBound, HiBound, DivRHS, true) ? -1 : 0; } else { // (X / neg) op neg - // e.g. X/-5 op -3 --> [15, 20) - LoBound = Prod; - LoOverflow = HiOverflow = ProdOV ? 1 : 0; + LoBound = Prod; // e.g. X/-5 op -3 --> [15, 20) + LoOverflow = HiOverflow = ProdOV; if (!HiOverflow) HiOverflow = SubWithOverflow(HiBound, Prod, DivRHS, true); } diff --git a/test/Transforms/InstCombine/2008-10-11-DivCompareFold.ll b/test/Transforms/InstCombine/2008-10-11-DivCompareFold.ll new file mode 100644 index 0000000..dfe9c4a --- /dev/null +++ b/test/Transforms/InstCombine/2008-10-11-DivCompareFold.ll @@ -0,0 +1,8 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i1 false} +; PR2697 + +define i1 @x(i32 %x) nounwind { + %div = sdiv i32 %x, 65536 ; <i32> [#uses=1] + %cmp = icmp slt i32 %div, -65536 + ret i1 %cmp +} |