mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
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
This commit is contained in:
parent
25e8e79fab
commit
5e9c6212a8
@ -2686,10 +2686,11 @@ OverflowResult llvm::computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
|
|||||||
// Ref: "Hacker's Delight" by Henry Warren
|
// Ref: "Hacker's Delight" by Henry Warren
|
||||||
unsigned BitWidth = LHS->getType()->getScalarSizeInBits();
|
unsigned BitWidth = LHS->getType()->getScalarSizeInBits();
|
||||||
APInt LHSKnownZero(BitWidth, 0);
|
APInt LHSKnownZero(BitWidth, 0);
|
||||||
|
APInt LHSKnownOne(BitWidth, 0);
|
||||||
APInt RHSKnownZero(BitWidth, 0);
|
APInt RHSKnownZero(BitWidth, 0);
|
||||||
APInt TmpKnownOne(BitWidth, 0);
|
APInt RHSKnownOne(BitWidth, 0);
|
||||||
computeKnownBits(LHS, LHSKnownZero, TmpKnownOne, DL, /*Depth=*/0, AT, CxtI, DT);
|
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, DL, /*Depth=*/0, AT, CxtI, DT);
|
||||||
computeKnownBits(RHS, RHSKnownZero, TmpKnownOne, 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
|
// Note that underestimating the number of zero bits gives a more
|
||||||
// conservative answer.
|
// conservative answer.
|
||||||
unsigned ZeroBits = LHSKnownZero.countLeadingOnes() +
|
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
|
// We know the multiply operation doesn't overflow if the maximum values for
|
||||||
// each operand will not overflow after we multiply them together.
|
// each operand will not overflow after we multiply them together.
|
||||||
bool Overflow;
|
bool MaxOverflow;
|
||||||
LHSMax.umul_ov(RHSMax, Overflow);
|
LHSMax.umul_ov(RHSMax, MaxOverflow);
|
||||||
|
if (!MaxOverflow)
|
||||||
|
return OverflowResult::NeverOverflows;
|
||||||
|
|
||||||
return Overflow ? OverflowResult::MayOverflow
|
// We know it always overflows if multiplying the smallest possible values for
|
||||||
: OverflowResult::NeverOverflows;
|
// the operands also results in overflow.
|
||||||
|
bool MinOverflow;
|
||||||
|
LHSKnownOne.umul_ov(RHSKnownOne, MinOverflow);
|
||||||
|
if (MinOverflow)
|
||||||
|
return OverflowResult::AlwaysOverflows;
|
||||||
|
|
||||||
|
return OverflowResult::MayOverflow;
|
||||||
}
|
}
|
||||||
|
@ -443,6 +443,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
|||||||
OverflowResult OR = computeOverflowForUnsignedMul(LHS, RHS, II);
|
OverflowResult OR = computeOverflowForUnsignedMul(LHS, RHS, II);
|
||||||
if (OR == OverflowResult::NeverOverflows) {
|
if (OR == OverflowResult::NeverOverflows) {
|
||||||
return CreateOverflowTuple(II, Builder->CreateNUWMul(LHS, RHS), false);
|
return CreateOverflowTuple(II, Builder->CreateNUWMul(LHS, RHS), false);
|
||||||
|
} else if (OR == OverflowResult::AlwaysOverflows) {
|
||||||
|
return CreateOverflowTuple(II, Builder->CreateMul(LHS, RHS), true);
|
||||||
}
|
}
|
||||||
} // FALL THROUGH
|
} // FALL THROUGH
|
||||||
case Intrinsic::smul_with_overflow:
|
case Intrinsic::smul_with_overflow:
|
||||||
|
@ -231,6 +231,19 @@ define i32 @umultest4(i32 %n) nounwind {
|
|||||||
; CHECK: umul.with.overflow
|
; 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) {
|
define void @powi(double %V, double *%P) {
|
||||||
entry:
|
entry:
|
||||||
%A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind
|
%A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind
|
||||||
|
Loading…
Reference in New Issue
Block a user