forked from OSchip/llvm-project
[ValueTracking] Use ConstantRange overflow check for signed add; NFC
This is the same change as rL356290, but for signed add. It replaces the existing ripple logic with the overflow logic in ConstantRange. This is NFC in that it should return NeverOverflow in exactly the same cases as the previous implementation. However, it does make computeOverflowForSignedAdd() more powerful by now also determining AlwaysOverflows conditions. As none of its consumers handle this yet, this has no impact on optimization. Making use of AlwaysOverflows in with.overflow folding will be handled as a followup. Differential Revision: https://reviews.llvm.org/D59450 llvm-svn: 356345
This commit is contained in:
parent
affead9ad0
commit
322e2dbee1
|
@ -4092,51 +4092,6 @@ OverflowResult llvm::computeOverflowForUnsignedAdd(
|
||||||
return mapOverflowResult(LHSRange.unsignedAddMayOverflow(RHSRange));
|
return mapOverflowResult(LHSRange.unsignedAddMayOverflow(RHSRange));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if we can prove that adding the two values of the
|
|
||||||
/// knownbits will not overflow.
|
|
||||||
/// Otherwise return false.
|
|
||||||
static bool checkRippleForSignedAdd(const KnownBits &LHSKnown,
|
|
||||||
const KnownBits &RHSKnown) {
|
|
||||||
// Addition of two 2's complement numbers having opposite signs will never
|
|
||||||
// overflow.
|
|
||||||
if ((LHSKnown.isNegative() && RHSKnown.isNonNegative()) ||
|
|
||||||
(LHSKnown.isNonNegative() && RHSKnown.isNegative()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// If either of the values is known to be non-negative, adding them can only
|
|
||||||
// overflow if the second is also non-negative, so we can assume that.
|
|
||||||
// Two non-negative numbers will only overflow if there is a carry to the
|
|
||||||
// sign bit, so we can check if even when the values are as big as possible
|
|
||||||
// there is no overflow to the sign bit.
|
|
||||||
if (LHSKnown.isNonNegative() || RHSKnown.isNonNegative()) {
|
|
||||||
APInt MaxLHS = ~LHSKnown.Zero;
|
|
||||||
MaxLHS.clearSignBit();
|
|
||||||
APInt MaxRHS = ~RHSKnown.Zero;
|
|
||||||
MaxRHS.clearSignBit();
|
|
||||||
APInt Result = std::move(MaxLHS) + std::move(MaxRHS);
|
|
||||||
return Result.isSignBitClear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If either of the values is known to be negative, adding them can only
|
|
||||||
// overflow if the second is also negative, so we can assume that.
|
|
||||||
// Two negative number will only overflow if there is no carry to the sign
|
|
||||||
// bit, so we can check if even when the values are as small as possible
|
|
||||||
// there is overflow to the sign bit.
|
|
||||||
if (LHSKnown.isNegative() || RHSKnown.isNegative()) {
|
|
||||||
APInt MinLHS = LHSKnown.One;
|
|
||||||
MinLHS.clearSignBit();
|
|
||||||
APInt MinRHS = RHSKnown.One;
|
|
||||||
MinRHS.clearSignBit();
|
|
||||||
APInt Result = std::move(MinLHS) + std::move(MinRHS);
|
|
||||||
return Result.isSignBitSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we reached here it means that we know nothing about the sign bits.
|
|
||||||
// In this case we can't know if there will be an overflow, since by
|
|
||||||
// changing the sign bits any two values can be made to overflow.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
|
static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
|
||||||
const Value *RHS,
|
const Value *RHS,
|
||||||
const AddOperator *Add,
|
const AddOperator *Add,
|
||||||
|
@ -4168,9 +4123,14 @@ static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
|
||||||
|
|
||||||
KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
|
KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
|
||||||
KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
|
KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
|
||||||
|
ConstantRange LHSRange =
|
||||||
if (checkRippleForSignedAdd(LHSKnown, RHSKnown))
|
ConstantRange::fromKnownBits(LHSKnown, /*signed*/ true);
|
||||||
return OverflowResult::NeverOverflows;
|
ConstantRange RHSRange =
|
||||||
|
ConstantRange::fromKnownBits(RHSKnown, /*signed*/ true);
|
||||||
|
OverflowResult OR =
|
||||||
|
mapOverflowResult(LHSRange.signedAddMayOverflow(RHSRange));
|
||||||
|
if (OR != OverflowResult::MayOverflow)
|
||||||
|
return OR;
|
||||||
|
|
||||||
// The remaining code needs Add to be available. Early returns if not so.
|
// The remaining code needs Add to be available. Early returns if not so.
|
||||||
if (!Add)
|
if (!Add)
|
||||||
|
|
Loading…
Reference in New Issue