[llvm] r262637 - [ConstantRange] Generalize makeGuaranteedNoWrapRegion to work on ranges

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 3 10:31:17 PST 2016


Author: sanjoy
Date: Thu Mar  3 12:31:16 2016
New Revision: 262637

URL: http://llvm.org/viewvc/llvm-project?rev=262637&view=rev
Log:
[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.

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=262637&r1=262636&r2=262637&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/ConstantRange.h (original)
+++ llvm/trunk/include/llvm/IR/ConstantRange.h Thu Mar  3 12:31:16 2016
@@ -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.

Modified: llvm/trunk/lib/IR/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantRange.cpp?rev=262637&r1=262636&r2=262637&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantRange.cpp (original)
+++ llvm/trunk/lib/IR/ConstantRange.cpp Thu Mar  3 12:31:16 2016
@@ -129,7 +129,8 @@ ConstantRange ConstantRange::makeSatisfy
 
 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::makeGuaranteedNoWrapRegio
           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)));
   }
 

Modified: llvm/trunk/unittests/IR/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantRangeTest.cpp?rev=262637&r1=262636&r2=262637&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantRangeTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp Thu Mar  3 12:31:16 2016
@@ -657,6 +657,63 @@ TEST(ConstantRange, MakeOverflowingRegio
       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




More information about the llvm-commits mailing list