mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-19 02:42:58 +00:00
[ConstantRange] Generalize makeGuaranteedNoWrapRegion to work on ranges
This will be used in a later patch to ScalarEvolution. Right now only the unit tests exercise the newly added code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262637 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b76d92e4ad
commit
1d754782e0
@ -82,24 +82,26 @@ public:
|
||||
static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
|
||||
const ConstantRange &Other);
|
||||
|
||||
/// Return the largest range containing all X such that "X BinOpC C" is
|
||||
/// guaranteed not to wrap (overflow).
|
||||
/// Return the largest range containing all X such that "X BinOpC Y" is
|
||||
/// guaranteed not to wrap (overflow) for all Y in Other.
|
||||
///
|
||||
/// NB! The returned set does *not* contain **all** possible values of X for
|
||||
/// which "X BinOpC C" does not wrap -- some viable values of X may be
|
||||
/// which "X BinOpC Y" does not wrap -- some viable values of X may be
|
||||
/// missing, so you cannot use this to contrain X's range. E.g. in the last
|
||||
/// example, "(-2) + 1" is both nsw and nuw (so the "X" could be -2), but (-2)
|
||||
/// is not in the set returned.
|
||||
///
|
||||
/// Example:
|
||||
/// Examples:
|
||||
/// typedef OverflowingBinaryOperator OBO;
|
||||
/// makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127)
|
||||
/// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1)
|
||||
/// makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set
|
||||
/// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap | OBO::NoSignedWrap) ==
|
||||
/// [0,INT_MAX)
|
||||
/// #define MGNR makeGuaranteedNoWrapRegion
|
||||
/// MGNR(Add, [i8 1, 2), OBO::NoSignedWrap) == [-128, 127)
|
||||
/// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap) == [0, -1)
|
||||
/// MGNR(Add, [i8 0, 1), OBO::NoUnsignedWrap) == Full Set
|
||||
/// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap | OBO::NoSignedWrap)
|
||||
/// == [0,INT_MAX)
|
||||
/// MGNR(Add, [i8 -1, 6), OBO::NoSignedWrap) == [INT_MIN+1, INT_MAX-4)
|
||||
static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &C,
|
||||
const ConstantRange &Other,
|
||||
unsigned NoWrapKind);
|
||||
|
||||
/// Return the lower value for this range.
|
||||
|
@ -129,7 +129,8 @@ ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
|
||||
|
||||
ConstantRange
|
||||
ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
const APInt &C, unsigned NoWrapKind) {
|
||||
const ConstantRange &Other,
|
||||
unsigned NoWrapKind) {
|
||||
typedef OverflowingBinaryOperator OBO;
|
||||
|
||||
// Computes the intersection of CR0 and CR1. It is different from
|
||||
@ -149,29 +150,36 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
|
||||
NoWrapKind == (OBO::NoUnsignedWrap | OBO::NoSignedWrap)) &&
|
||||
"NoWrapKind invalid!");
|
||||
|
||||
unsigned BitWidth = C.getBitWidth();
|
||||
unsigned BitWidth = Other.getBitWidth();
|
||||
if (BinOp != Instruction::Add)
|
||||
// Conservative answer: empty set
|
||||
return ConstantRange(BitWidth, false);
|
||||
|
||||
if (C.isMinValue())
|
||||
// Full set: nothing signed / unsigned wraps when added to 0.
|
||||
return ConstantRange(BitWidth);
|
||||
if (auto *C = Other.getSingleElement())
|
||||
if (C->isMinValue())
|
||||
// Full set: nothing signed / unsigned wraps when added to 0.
|
||||
return ConstantRange(BitWidth);
|
||||
|
||||
ConstantRange Result(BitWidth);
|
||||
|
||||
if (NoWrapKind & OBO::NoUnsignedWrap)
|
||||
Result = SubsetIntersect(Result,
|
||||
ConstantRange(APInt::getNullValue(BitWidth), -C));
|
||||
Result =
|
||||
SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
|
||||
-Other.getUnsignedMax()));
|
||||
|
||||
if (NoWrapKind & OBO::NoSignedWrap) {
|
||||
if (C.isStrictlyPositive())
|
||||
APInt SignedMin = Other.getSignedMin();
|
||||
APInt SignedMax = Other.getSignedMax();
|
||||
|
||||
if (SignedMax.isStrictlyPositive())
|
||||
Result = SubsetIntersect(
|
||||
Result, ConstantRange(APInt::getSignedMinValue(BitWidth),
|
||||
APInt::getSignedMinValue(BitWidth) - C));
|
||||
else
|
||||
Result,
|
||||
ConstantRange(APInt::getSignedMinValue(BitWidth),
|
||||
APInt::getSignedMinValue(BitWidth) - SignedMax));
|
||||
|
||||
if (SignedMin.isNegative())
|
||||
Result = SubsetIntersect(
|
||||
Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - C,
|
||||
Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin,
|
||||
APInt::getSignedMinValue(BitWidth)));
|
||||
}
|
||||
|
||||
|
@ -657,6 +657,63 @@ TEST(ConstantRange, MakeOverflowingRegion) {
|
||||
EXPECT_FALSE(Overflow);
|
||||
}
|
||||
}
|
||||
|
||||
auto NSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
|
||||
OBO::NoSignedWrap);
|
||||
EXPECT_TRUE(NSWForAllValues.isSingleElement() &&
|
||||
NSWForAllValues.getSingleElement()->isMinValue());
|
||||
|
||||
auto NUWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
|
||||
OBO::NoUnsignedWrap);
|
||||
EXPECT_TRUE(NUWForAllValues.isSingleElement() &&
|
||||
NSWForAllValues.getSingleElement()->isMinValue());
|
||||
|
||||
auto NUWAndNSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
|
||||
OBO::NoUnsignedWrap | OBO::NoSignedWrap);
|
||||
EXPECT_TRUE(NUWAndNSWForAllValues.isSingleElement() &&
|
||||
NSWForAllValues.getSingleElement()->isMinValue());
|
||||
|
||||
ConstantRange OneToFive(APInt(32, 1), APInt(32, 6));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, OneToFive, OBO::NoSignedWrap),
|
||||
ConstantRange(APInt::getSignedMinValue(32),
|
||||
APInt::getSignedMaxValue(32) - 4));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, OneToFive, OBO::NoUnsignedWrap),
|
||||
ConstantRange(APInt::getMinValue(32), APInt::getMinValue(32) - 5));
|
||||
EXPECT_EQ(
|
||||
ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, OneToFive, OBO::NoUnsignedWrap | OBO::NoSignedWrap),
|
||||
ConstantRange(APInt::getMinValue(32), APInt::getSignedMaxValue(32) - 4));
|
||||
|
||||
ConstantRange MinusFiveToMinusTwo(APInt(32, -5), APInt(32, -1));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusFiveToMinusTwo, OBO::NoSignedWrap),
|
||||
ConstantRange(APInt::getSignedMinValue(32) + 5,
|
||||
APInt::getSignedMinValue(32)));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusFiveToMinusTwo, OBO::NoUnsignedWrap),
|
||||
ConstantRange(APInt(32, 0), APInt(32, 2)));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusFiveToMinusTwo,
|
||||
OBO::NoUnsignedWrap | OBO::NoSignedWrap),
|
||||
ConstantRange(APInt(32, 0), APInt(32, 2)));
|
||||
|
||||
ConstantRange MinusOneToOne(APInt(32, -1), APInt(32, 2));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusOneToOne, OBO::NoSignedWrap),
|
||||
ConstantRange(APInt::getSignedMinValue(32) + 1,
|
||||
APInt::getSignedMinValue(32) - 1));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusOneToOne, OBO::NoUnsignedWrap),
|
||||
ConstantRange(APInt(32, 0), APInt(32, 1)));
|
||||
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
|
||||
Instruction::Add, MinusOneToOne,
|
||||
OBO::NoUnsignedWrap | OBO::NoSignedWrap),
|
||||
ConstantRange(APInt(32, 0), APInt(32, 1)));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user