diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 18bb0400080..6b2f54393d4 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 ce052f724e8..d7a5f7be5c5 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 00000000000..5bcaa66366c --- /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 00000000000..6e76bcfd753 --- /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 +}