[llvm] r225077 - InstCombine: Detect when llvm.umul.with.overflow always overflows
David Majnemer
david.majnemer at gmail.com
Thu Jan 1 23:29:48 PST 2015
Author: majnemer
Date: Fri Jan 2 01:29:47 2015
New Revision: 225077
URL: http://llvm.org/viewvc/llvm-project?rev=225077&view=rev
Log:
InstCombine: Detect when llvm.umul.with.overflow always overflows
We know overflow always occurs if both ~LHSKnownZero * ~RHSKnownZero
and LHSKnownOne * RHSKnownOne overflow.
Modified:
llvm/trunk/lib/Analysis/ValueTracking.cpp
llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/trunk/test/Transforms/InstCombine/intrinsics.ll
Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=225077&r1=225076&r2=225077&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Fri Jan 2 01:29:47 2015
@@ -2686,10 +2686,11 @@ OverflowResult llvm::computeOverflowForU
// 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::computeOverflowForU
// 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;
+
+ // 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 Overflow ? OverflowResult::MayOverflow
- : OverflowResult::NeverOverflows;
+ return OverflowResult::MayOverflow;
}
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=225077&r1=225076&r2=225077&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Fri Jan 2 01:29:47 2015
@@ -443,6 +443,8 @@ Instruction *InstCombiner::visitCallInst
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:
Modified: llvm/trunk/test/Transforms/InstCombine/intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/intrinsics.ll?rev=225077&r1=225076&r2=225077&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/intrinsics.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/intrinsics.ll Fri Jan 2 01:29:47 2015
@@ -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
More information about the llvm-commits
mailing list