[llvm] r319806 - [ConstantRange] Support subtraction in makeGuaranteedNoWrapRegion.
Joel Galenson via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 5 10:14:23 PST 2017
Author: jgalenson
Date: Tue Dec 5 10:14:23 2017
New Revision: 319806
URL: http://llvm.org/viewvc/llvm-project?rev=319806&view=rev
Log:
[ConstantRange] Support subtraction in makeGuaranteedNoWrapRegion.
Previously ConstantRange::makeGuaranteedNoWrapRegion only handled addition. This adds support for subtraction.
Differential Revision: https://reviews.llvm.org/D40036
Modified:
llvm/trunk/include/llvm/IR/ConstantRange.h
llvm/trunk/lib/IR/ConstantRange.cpp
llvm/trunk/unittests/IR/ConstantRangeTest.cpp
Modified: llvm/trunk/include/llvm/IR/ConstantRange.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/ConstantRange.h?rev=319806&r1=319805&r2=319806&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ConstantRange.h (original)
+++ llvm/trunk/include/llvm/IR/ConstantRange.h Tue Dec 5 10:14:23 2017
@@ -96,9 +96,9 @@ public:
///
/// NB! The returned set does *not* contain **all** possible values of X for
/// which "X BinOpC Y" does not wrap -- some viable values of X may be
- /// missing, so you cannot use this to constrain 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.
+ /// missing, so you cannot use this to constrain X's range. E.g. in the
+ /// fourth example, "(-2) + 1" is both nsw and nuw (so the "X" could be -2),
+ /// but (-2) is not in the set returned.
///
/// Examples:
/// typedef OverflowingBinaryOperator OBO;
@@ -109,6 +109,10 @@ public:
/// 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)
+ /// MGNR(Sub, [i8 1, 2), OBO::NoSignedWrap) == [-127, 128)
+ /// MGNR(Sub, [i8 1, 2), OBO::NoUnsignedWrap) == [1, 0)
+ /// MGNR(Sub, [i8 1, 2), OBO::NoUnsignedWrap | OBO::NoSignedWrap)
+ /// == [1,INT_MAX)
static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
const ConstantRange &Other,
unsigned NoWrapKind);
Modified: llvm/trunk/lib/IR/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantRange.cpp?rev=319806&r1=319805&r2=319806&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantRange.cpp (original)
+++ llvm/trunk/lib/IR/ConstantRange.cpp Tue Dec 5 10:14:23 2017
@@ -199,39 +199,63 @@ ConstantRange::makeGuaranteedNoWrapRegio
"NoWrapKind invalid!");
unsigned BitWidth = Other.getBitWidth();
- if (BinOp != Instruction::Add)
- // Conservative answer: empty set
- return ConstantRange(BitWidth, false);
-
- if (auto *C = Other.getSingleElement())
- if (C->isNullValue())
- // 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),
- -Other.getUnsignedMax()));
-
- if (NoWrapKind & OBO::NoSignedWrap) {
- const APInt &SignedMin = Other.getSignedMin();
- const APInt &SignedMax = Other.getSignedMax();
-
- if (SignedMax.isStrictlyPositive())
- Result = SubsetIntersect(
- Result,
- ConstantRange(APInt::getSignedMinValue(BitWidth),
- APInt::getSignedMinValue(BitWidth) - SignedMax));
+ switch (BinOp) {
+ default:
+ // Conservative answer: empty set
+ return ConstantRange(BitWidth, false);
- if (SignedMin.isNegative())
- Result = SubsetIntersect(
- Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin,
- APInt::getSignedMinValue(BitWidth)));
+ case Instruction::Add:
+ if (auto *C = Other.getSingleElement())
+ if (C->isNullValue())
+ // Full set: nothing signed / unsigned wraps when added to 0.
+ return ConstantRange(BitWidth);
+ if (NoWrapKind & OBO::NoUnsignedWrap)
+ Result =
+ SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
+ -Other.getUnsignedMax()));
+ if (NoWrapKind & OBO::NoSignedWrap) {
+ const APInt &SignedMin = Other.getSignedMin();
+ const APInt &SignedMax = Other.getSignedMax();
+ if (SignedMax.isStrictlyPositive())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth),
+ APInt::getSignedMinValue(BitWidth) - SignedMax));
+ if (SignedMin.isNegative())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin,
+ APInt::getSignedMinValue(BitWidth)));
+ }
+ return Result;
+
+ case Instruction::Sub:
+ if (auto *C = Other.getSingleElement())
+ if (C->isNullValue())
+ // Full set: nothing signed / unsigned wraps when subtracting 0.
+ return ConstantRange(BitWidth);
+ if (NoWrapKind & OBO::NoUnsignedWrap)
+ Result =
+ SubsetIntersect(Result, ConstantRange(Other.getUnsignedMax(),
+ APInt::getMinValue(BitWidth)));
+ if (NoWrapKind & OBO::NoSignedWrap) {
+ const APInt &SignedMin = Other.getSignedMin();
+ const APInt &SignedMax = Other.getSignedMax();
+ if (SignedMax.isStrictlyPositive())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth) + SignedMax,
+ APInt::getSignedMinValue(BitWidth)));
+ if (SignedMin.isNegative())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth),
+ APInt::getSignedMinValue(BitWidth) + SignedMin));
+ }
+ return Result;
}
-
- return Result;
}
bool ConstantRange::isFullSet() const {
Modified: llvm/trunk/unittests/IR/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantRangeTest.cpp?rev=319806&r1=319805&r2=319806&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantRangeTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp Tue Dec 5 10:14:23 2017
@@ -715,24 +715,102 @@ TEST(ConstantRange, MakeGuaranteedNoWrap
}
}
+ for (int Const : {0, -1, -2, 1, 2, IntMin4Bits, IntMax4Bits}) {
+ APInt C(4, Const, true /* = isSigned */);
+
+ auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, C, OBO::NoUnsignedWrap);
+
+ EXPECT_FALSE(NUWRegion.isEmptySet());
+
+ auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, C, OBO::NoSignedWrap);
+
+ EXPECT_FALSE(NSWRegion.isEmptySet());
+
+ auto NoWrapRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, C, OBO::NoSignedWrap | OBO::NoUnsignedWrap);
+
+ EXPECT_FALSE(NoWrapRegion.isEmptySet());
+ EXPECT_TRUE(NUWRegion.intersectWith(NSWRegion).contains(NoWrapRegion));
+
+ for (APInt I = NUWRegion.getLower(), E = NUWRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+ (void)I.usub_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+
+ for (APInt I = NSWRegion.getLower(), E = NSWRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+ (void)I.ssub_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+
+ for (APInt I = NoWrapRegion.getLower(), E = NoWrapRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+
+ (void)I.ssub_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+
+ (void)I.usub_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+ }
+
auto NSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
OBO::NoSignedWrap);
EXPECT_TRUE(NSWForAllValues.isSingleElement() &&
NSWForAllValues.getSingleElement()->isMinValue());
+ NSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, ConstantRange(32, /* isFullSet = */ true),
+ OBO::NoSignedWrap);
+ EXPECT_TRUE(NSWForAllValues.isSingleElement() &&
+ NSWForAllValues.getSingleElement()->isMaxValue());
+
auto NUWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
OBO::NoUnsignedWrap);
EXPECT_TRUE(NUWForAllValues.isSingleElement() &&
NUWForAllValues.getSingleElement()->isMinValue());
+ NUWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, ConstantRange(32, /* isFullSet = */ true),
+ OBO::NoUnsignedWrap);
+ EXPECT_TRUE(NUWForAllValues.isSingleElement() &&
+ NUWForAllValues.getSingleElement()->isMaxValue());
+
auto NUWAndNSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
Instruction::Add, ConstantRange(32, /* isFullSet = */ true),
OBO::NoUnsignedWrap | OBO::NoSignedWrap);
EXPECT_TRUE(NUWAndNSWForAllValues.isSingleElement() &&
NUWAndNSWForAllValues.getSingleElement()->isMinValue());
+ NUWAndNSWForAllValues = ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, ConstantRange(32, /* isFullSet = */ true),
+ OBO::NoUnsignedWrap | OBO::NoSignedWrap);
+ EXPECT_TRUE(NUWAndNSWForAllValues.isSingleElement() &&
+ NUWAndNSWForAllValues.getSingleElement()->isMaxValue());
+
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, APInt(32, 0), OBO::NoUnsignedWrap).isFullSet());
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, APInt(32, 0), OBO::NoSignedWrap).isFullSet());
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, APInt(32, 0),
+ OBO::NoUnsignedWrap | OBO::NoSignedWrap).isFullSet());
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, APInt(32, 0), OBO::NoUnsignedWrap).isFullSet());
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, APInt(32, 0), OBO::NoSignedWrap).isFullSet());
+ EXPECT_TRUE(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, APInt(32, 0),
+ OBO::NoUnsignedWrap | OBO::NoSignedWrap).isFullSet());
+
ConstantRange OneToFive(APInt(32, 1), APInt(32, 6));
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
Instruction::Add, OneToFive, OBO::NoSignedWrap),
@@ -745,6 +823,17 @@ TEST(ConstantRange, MakeGuaranteedNoWrap
ConstantRange::makeGuaranteedNoWrapRegion(
Instruction::Add, OneToFive, OBO::NoUnsignedWrap | OBO::NoSignedWrap),
ConstantRange(APInt::getMinValue(32), APInt::getSignedMaxValue(32) - 4));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, OneToFive, OBO::NoSignedWrap),
+ ConstantRange(APInt::getSignedMinValue(32) + 5,
+ APInt::getSignedMinValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, OneToFive, OBO::NoUnsignedWrap),
+ ConstantRange(APInt::getMinValue(32) + 5, APInt::getMinValue(32)));
+ EXPECT_EQ(
+ ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, OneToFive, OBO::NoUnsignedWrap | OBO::NoSignedWrap),
+ ConstantRange(APInt::getMinValue(32) + 5, APInt::getSignedMinValue(32)));
ConstantRange MinusFiveToMinusTwo(APInt(32, -5), APInt(32, -1));
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
@@ -758,6 +847,19 @@ TEST(ConstantRange, MakeGuaranteedNoWrap
Instruction::Add, MinusFiveToMinusTwo,
OBO::NoUnsignedWrap | OBO::NoSignedWrap),
ConstantRange(APInt(32, 0), APInt(32, 2)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusFiveToMinusTwo, OBO::NoSignedWrap),
+ ConstantRange(APInt::getSignedMinValue(32),
+ APInt::getSignedMaxValue(32) - 4));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusFiveToMinusTwo, OBO::NoUnsignedWrap),
+ ConstantRange(APInt::getMaxValue(32) - 1,
+ APInt::getMinValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusFiveToMinusTwo,
+ OBO::NoUnsignedWrap | OBO::NoSignedWrap),
+ ConstantRange(APInt::getMaxValue(32) - 1,
+ APInt::getMinValue(32)));
ConstantRange MinusOneToOne(APInt(32, -1), APInt(32, 2));
EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
@@ -771,6 +873,43 @@ TEST(ConstantRange, MakeGuaranteedNoWrap
Instruction::Add, MinusOneToOne,
OBO::NoUnsignedWrap | OBO::NoSignedWrap),
ConstantRange(APInt(32, 0), APInt(32, 1)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusOneToOne, OBO::NoSignedWrap),
+ ConstantRange(APInt::getSignedMinValue(32) + 1,
+ APInt::getSignedMinValue(32) - 1));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusOneToOne, OBO::NoUnsignedWrap),
+ ConstantRange(APInt::getMaxValue(32),
+ APInt::getMinValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, MinusOneToOne,
+ OBO::NoUnsignedWrap | OBO::NoSignedWrap),
+ ConstantRange(APInt::getMaxValue(32),
+ APInt::getMinValue(32)));
+
+ ConstantRange One(APInt(32, 1), APInt(32, 2));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, One, OBO::NoSignedWrap),
+ ConstantRange(APInt::getSignedMinValue(32),
+ APInt::getSignedMaxValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, One, OBO::NoUnsignedWrap),
+ ConstantRange(APInt::getMinValue(32), APInt::getMaxValue(32)));
+ EXPECT_EQ(
+ ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Add, One, OBO::NoUnsignedWrap | OBO::NoSignedWrap),
+ ConstantRange(APInt(32, 0), APInt::getSignedMaxValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, One, OBO::NoSignedWrap),
+ ConstantRange(APInt::getSignedMinValue(32) + 1,
+ APInt::getSignedMinValue(32)));
+ EXPECT_EQ(ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, One, OBO::NoUnsignedWrap),
+ ConstantRange(APInt::getMinValue(32) + 1, APInt::getMinValue(32)));
+ EXPECT_EQ(
+ ConstantRange::makeGuaranteedNoWrapRegion(
+ Instruction::Sub, One, OBO::NoUnsignedWrap | OBO::NoSignedWrap),
+ ConstantRange(APInt::getMinValue(32) + 1, APInt::getSignedMinValue(32)));
}
TEST(ConstantRange, GetEquivalentICmp) {
More information about the llvm-commits
mailing list