diff options
author | Dan Gohman <gohman@apple.com> | 2008-05-02 21:30:02 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-05-02 21:30:02 +0000 |
commit | 1d9cd506774f2d51b7e7315b07fdbcc05efebe4a (patch) | |
tree | 5fb78373be257cfcaf5f1a6971329d0c0a8b1054 | |
parent | 48e8c80e1791adb7a07b8fd6e27edcdfbb756950 (diff) |
Fix a mistake in the computation of leading zeros for udiv.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50591 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 | ||||
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 8 | ||||
-rw-r--r-- | test/Transforms/InstCombine/udiv-simplify-bug-0.ll | 14 | ||||
-rw-r--r-- | test/Transforms/InstCombine/udiv-simplify-bug-1.ll | 25 |
4 files changed, 49 insertions, 6 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 18bb040008..6b2f54393d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1257,7 +1257,7 @@ void SelectionDAG::ComputeMaskedBits(SDOperand Op, const APInt &Mask, case ISD::UDIV: { // For the purposes of computing leading zeros we can conservatively // treat a udiv as a logical right shift by the power of 2 known to - // be greater than the denominator. + // be less than the denominator. APInt AllOnes = APInt::getAllOnesValue(BitWidth); ComputeMaskedBits(Op.getOperand(0), AllOnes, KnownZero2, KnownOne2, Depth+1); @@ -1267,8 +1267,10 @@ void SelectionDAG::ComputeMaskedBits(SDOperand Op, const APInt &Mask, KnownZero2.clear(); ComputeMaskedBits(Op.getOperand(1), AllOnes, KnownZero2, KnownOne2, Depth+1); - LeadZ = std::min(BitWidth, - LeadZ + BitWidth - KnownOne2.countLeadingZeros()); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; return; diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index ce052f724e..d7a5f7be5c 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -780,7 +780,7 @@ void InstCombiner::ComputeMaskedBits(Value *V, const APInt &Mask, case Instruction::UDiv: { // For the purposes of computing leading zeros we can conservatively // treat a udiv as a logical right shift by the power of 2 known to - // be greater than the denominator. + // be less than the denominator. APInt AllOnes = APInt::getAllOnesValue(BitWidth); ComputeMaskedBits(I->getOperand(0), AllOnes, KnownZero2, KnownOne2, Depth+1); @@ -790,8 +790,10 @@ void InstCombiner::ComputeMaskedBits(Value *V, const APInt &Mask, KnownZero2.clear(); ComputeMaskedBits(I->getOperand(1), AllOnes, KnownZero2, KnownOne2, Depth+1); - LeadZ = std::min(BitWidth, - LeadZ + BitWidth - KnownOne2.countLeadingZeros()); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; return; diff --git a/test/Transforms/InstCombine/udiv-simplify-bug-0.ll b/test/Transforms/InstCombine/udiv-simplify-bug-0.ll new file mode 100644 index 0000000000..5bcaa66366 --- /dev/null +++ b/test/Transforms/InstCombine/udiv-simplify-bug-0.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i64 0} | count 2 + +define i64 @foo(i32 %x) nounwind { + %y = lshr i32 %x, 1 + %r = udiv i32 %y, -1 + %z = sext i32 %r to i64 + ret i64 %z +} +define i64 @bar(i32 %x) nounwind { + %y = lshr i32 %x, 31 + %r = udiv i32 %y, 3 + %z = sext i32 %r to i64 + ret i64 %z +} diff --git a/test/Transforms/InstCombine/udiv-simplify-bug-1.ll b/test/Transforms/InstCombine/udiv-simplify-bug-1.ll new file mode 100644 index 0000000000..6e76bcfd75 --- /dev/null +++ b/test/Transforms/InstCombine/udiv-simplify-bug-1.ll @@ -0,0 +1,25 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis > %t1.ll +; RUN: grep udiv %t1.ll | count 3 +; RUN: grep zext %t1.ll | count 3 +; PR2274 + +; The udiv instructions shouldn't be optimized away, and the +; sext instructions should be optimized to zext. + +define i64 @foo(i32 %x) nounwind { + %r = udiv i32 %x, -1 + %z = sext i32 %r to i64 + ret i64 %z +} +define i64 @bar(i32 %x) nounwind { + %y = lshr i32 %x, 30 + %r = udiv i32 %y, 3 + %z = sext i32 %r to i64 + ret i64 %z +} +define i64 @qux(i32 %x, i32 %v) nounwind { + %y = lshr i32 %x, 31 + %r = udiv i32 %y, %v + %z = sext i32 %r to i64 + ret i64 %z +} |