Introduce ConstantRange.addWithNoSignedWrap

To be used by upcoming change to IndVarSimplify

Reviewed By: sanjoy

Differential Revision: https://reviews.llvm.org/D25732

llvm-svn: 284597
This commit is contained in:
Artur Pilipenko 2016-10-19 14:44:23 +00:00
parent 2cf1dc2add
commit ed84103a1a
3 changed files with 43 additions and 0 deletions

View File

@ -261,6 +261,10 @@ public:
/// from an addition of a value in this range and a value in \p Other.
ConstantRange add(const ConstantRange &Other) const;
/// Return a new range representing the possible values resulting from a
/// known NSW addition of a value in this range and \p Other constant.
ConstantRange addWithNoSignedWrap(const APInt &Other) const;
/// Return a new range representing the possible values resulting
/// from a subtraction of a value in this range and a value in \p Other.
ConstantRange sub(const ConstantRange &Other) const;

View File

@ -674,6 +674,19 @@ ConstantRange::add(const ConstantRange &Other) const {
return X;
}
ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const {
// Calculate the subset of this range such that "X + Other" is
// guaranteed not to wrap (overflow) for all X in this subset.
// makeGuaranteedNoWrapRegion will produce an exact NSW range since we are
// passing a single element range.
auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(BinaryOperator::Add,
ConstantRange(Other),
OverflowingBinaryOperator::NoSignedWrap);
auto NSWConstrainedRange = intersectWith(NSWRange);
return NSWConstrainedRange.add(ConstantRange(Other));
}
ConstantRange
ConstantRange::sub(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())

View File

@ -357,6 +357,32 @@ TEST_F(ConstantRangeTest, Add) {
ConstantRange(APInt(16, 0xe)));
}
TEST_F(ConstantRangeTest, AddWithNoSignedWrap) {
EXPECT_EQ(Empty.addWithNoSignedWrap(APInt(16, 1)), Empty);
EXPECT_EQ(Full.addWithNoSignedWrap(APInt(16, 1)),
ConstantRange(APInt(16, INT16_MIN+1), APInt(16, INT16_MIN)));
EXPECT_EQ(ConstantRange(APInt(8, -50), APInt(8, 50)).addWithNoSignedWrap(APInt(8, 10)),
ConstantRange(APInt(8, -40), APInt(8, 60)));
EXPECT_EQ(ConstantRange(APInt(8, -50), APInt(8, 120)).addWithNoSignedWrap(APInt(8, 10)),
ConstantRange(APInt(8, -40), APInt(8, INT8_MIN)));
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, -10)).addWithNoSignedWrap(APInt(8, 5)),
ConstantRange(APInt(8, 125), APInt(8, -5)));
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, -120)).addWithNoSignedWrap(APInt(8, 10)),
ConstantRange(APInt(8, INT8_MIN+10), APInt(8, -110)));
EXPECT_EQ(Empty.addWithNoSignedWrap(APInt(16, -1)), Empty);
EXPECT_EQ(Full.addWithNoSignedWrap(APInt(16, -1)),
ConstantRange(APInt(16, INT16_MIN), APInt(16, INT16_MAX)));
EXPECT_EQ(ConstantRange(APInt(8, -50), APInt(8, 50)).addWithNoSignedWrap(APInt(8, -10)),
ConstantRange(APInt(8, -60), APInt(8, 40)));
EXPECT_EQ(ConstantRange(APInt(8, -120), APInt(8, 50)).addWithNoSignedWrap(APInt(8, -10)),
ConstantRange(APInt(8, INT8_MIN), APInt(8, 40)));
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, -120)).addWithNoSignedWrap(APInt(8, -5)),
ConstantRange(APInt(8, 115), APInt(8, -125)));
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, -120)).addWithNoSignedWrap(APInt(8, -10)),
ConstantRange(APInt(8, 110), APInt(8, INT8_MIN-10)));
}
TEST_F(ConstantRangeTest, Sub) {
EXPECT_EQ(Full.sub(APInt(16, 4)), Full);
EXPECT_EQ(Full.sub(Full), Full);