[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:
Nikita Popov 2019-03-17 21:25:26 +00:00
parent affead9ad0
commit 322e2dbee1
1 changed files with 8 additions and 48 deletions

View File

@ -4092,51 +4092,6 @@ OverflowResult llvm::computeOverflowForUnsignedAdd(
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,
const Value *RHS,
const AddOperator *Add,
@ -4168,9 +4123,14 @@ static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
if (checkRippleForSignedAdd(LHSKnown, RHSKnown))
return OverflowResult::NeverOverflows;
ConstantRange LHSRange =
ConstantRange::fromKnownBits(LHSKnown, /*signed*/ true);
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.
if (!Add)