Introduce ConstantRange.addWithNoSignedWrap
authorArtur Pilipenko <apilipenko@azulsystems.com>
Wed, 19 Oct 2016 14:44:23 +0000 (14:44 +0000)
committerArtur Pilipenko <apilipenko@azulsystems.com>
Wed, 19 Oct 2016 14:44:23 +0000 (14:44 +0000)
To be used by upcoming change to IndVarSimplify

Reviewed By: sanjoy

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

llvm-svn: 284597

llvm/include/llvm/IR/ConstantRange.h
llvm/lib/IR/ConstantRange.cpp
llvm/unittests/IR/ConstantRangeTest.cpp

index 2fb176f..4ac0a0f 100644 (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;
index b422eea..225eb5e 100644 (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())
index b890a4a..58fd044 100644 (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);