From 5e9c6212a8e6bb300dbef6cfbe4dee24623e91d2 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 2 Jan 2015 07:29:47 +0000 Subject: [PATCH] InstCombine: Detect when llvm.umul.with.overflow always overflows We know overflow always occurs if both ~LHSKnownZero * ~RHSKnownZero and LHSKnownOne * RHSKnownOne overflow. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225077 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 23 +++++++++++++------ .../InstCombine/InstCombineCalls.cpp | 2 ++ test/Transforms/InstCombine/intrinsics.ll | 13 +++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index cb1e285e8f3..3a0efa76b2f 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -2686,10 +2686,11 @@ OverflowResult llvm::computeOverflowForUnsignedMul(Value *LHS, Value *RHS, // Ref: "Hacker's Delight" by Henry Warren unsigned BitWidth = LHS->getType()->getScalarSizeInBits(); APInt LHSKnownZero(BitWidth, 0); + APInt LHSKnownOne(BitWidth, 0); APInt RHSKnownZero(BitWidth, 0); - APInt TmpKnownOne(BitWidth, 0); - computeKnownBits(LHS, LHSKnownZero, TmpKnownOne, DL, /*Depth=*/0, AT, CxtI, DT); - computeKnownBits(RHS, RHSKnownZero, TmpKnownOne, DL, /*Depth=*/0, AT, CxtI, DT); + APInt RHSKnownOne(BitWidth, 0); + computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, DL, /*Depth=*/0, AT, CxtI, DT); + computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, DL, /*Depth=*/0, AT, CxtI, DT); // Note that underestimating the number of zero bits gives a more // conservative answer. unsigned ZeroBits = LHSKnownZero.countLeadingOnes() + @@ -2705,9 +2706,17 @@ OverflowResult llvm::computeOverflowForUnsignedMul(Value *LHS, Value *RHS, // We know the multiply operation doesn't overflow if the maximum values for // each operand will not overflow after we multiply them together. - bool Overflow; - LHSMax.umul_ov(RHSMax, Overflow); + bool MaxOverflow; + LHSMax.umul_ov(RHSMax, MaxOverflow); + if (!MaxOverflow) + return OverflowResult::NeverOverflows; - return Overflow ? OverflowResult::MayOverflow - : OverflowResult::NeverOverflows; + // We know it always overflows if multiplying the smallest possible values for + // the operands also results in overflow. + bool MinOverflow; + LHSKnownOne.umul_ov(RHSKnownOne, MinOverflow); + if (MinOverflow) + return OverflowResult::AlwaysOverflows; + + return OverflowResult::MayOverflow; } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 34caf1a5ab9..20310b41689 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -443,6 +443,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { OverflowResult OR = computeOverflowForUnsignedMul(LHS, RHS, II); if (OR == OverflowResult::NeverOverflows) { return CreateOverflowTuple(II, Builder->CreateNUWMul(LHS, RHS), false); + } else if (OR == OverflowResult::AlwaysOverflows) { + return CreateOverflowTuple(II, Builder->CreateMul(LHS, RHS), true); } } // FALL THROUGH case Intrinsic::smul_with_overflow: diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index eae14de6a31..8e7742f8c34 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -231,6 +231,19 @@ define i32 @umultest4(i32 %n) nounwind { ; CHECK: umul.with.overflow } +define %ov.result.32 @umultest5(i32 %x, i32 %y) nounwind { + %or_x = or i32 %x, 2147483648 + %or_y = or i32 %y, 2147483648 + %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %or_x, i32 %or_y) + ret %ov.result.32 %mul +; CHECK-LABEL: @umultest5( +; CHECK-NEXT: %[[or_x:.*]] = or i32 %x, -2147483648 +; CHECK-NEXT: %[[or_y:.*]] = or i32 %y, -2147483648 +; CHECK-NEXT: %[[mul:.*]] = mul i32 %[[or_x]], %[[or_y]] +; CHECK-NEXT: %[[ret:.*]] = insertvalue %ov.result.32 { i32 undef, i1 true }, i32 %[[mul]], 0 +; CHECK-NEXT: ret %ov.result.32 %[[ret]] +} + define void @powi(double %V, double *%P) { entry: %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind