[llvm-commits] [llvm] r75177 - in /llvm/trunk: include/llvm/Support/ConstantRange.h lib/Support/ConstantRange.cpp unittests/Support/ConstantRangeTest.cpp

Dan Gohman gohman at apple.com
Thu Jul 9 15:07:27 PDT 2009


Author: djg
Date: Thu Jul  9 17:07:27 2009
New Revision: 75177

URL: http://llvm.org/viewvc/llvm-project?rev=75177&view=rev
Log:
Add a ConstantSignedRange class, which does for signed integers
what ConstantRange does for unsigned integers. Factor out a
common base class for common functionality.

Add some new functions for performing arithmetic on constant
ranges. Some of these are currently just stubbed out with
conservative implementations.

Add unittests for ConstantRange and ConstantSignedRange.

Added:
    llvm/trunk/unittests/Support/ConstantRangeTest.cpp
Modified:
    llvm/trunk/include/llvm/Support/ConstantRange.h
    llvm/trunk/lib/Support/ConstantRange.cpp

Modified: llvm/trunk/include/llvm/Support/ConstantRange.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ConstantRange.h?rev=75177&r1=75176&r2=75177&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/ConstantRange.h (original)
+++ llvm/trunk/include/llvm/Support/ConstantRange.h Thu Jul  9 17:07:27 2009
@@ -24,7 +24,9 @@
 // [0, 0)     = {}       = Empty set
 // [255, 255) = {0..255} = Full Set
 //
-// Note that ConstantRange always keeps unsigned values.
+// Note that ConstantRange always keeps unsigned values, and
+// ConstantSignedRange always keeps signed values.
+//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_SUPPORT_CONSTANT_RANGE_H
@@ -35,24 +37,22 @@
 
 namespace llvm {
 
-class ConstantRange {
+/// ConstantRangeBase - A base class for ConstantRange and ConstantSignedRange.
+/// This class implements functionality common to both.
+class ConstantRangeBase {
+protected:
   APInt Lower, Upper;
-  static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
-                                         const ConstantRange &RHS);
- public:
-  /// Initialize a full (the default) or empty set for the specified bit width.
-  ///
-  explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
 
   /// Initialize a range to hold the single specified value.
   ///
-  ConstantRange(const APInt &Value);
+  ConstantRangeBase(const APInt &Value);
 
   /// @brief Initialize a range of values explicitly. This will assert out if
   /// Lower==Upper and Lower != Min or Max value for its type. It will also
   /// assert out if the two APInt's are not the same bit width.
-  ConstantRange(const APInt& Lower, const APInt& Upper);
+  ConstantRangeBase(const APInt& Lower, const APInt& Upper);
 
+public:
   /// getLower - Return the lower value for this range...
   ///
   const APInt &getLower() const { return Lower; }
@@ -65,6 +65,56 @@
   ///
   uint32_t getBitWidth() const { return Lower.getBitWidth(); }
 
+  /// getSingleElement - If this set contains a single element, return it,
+  /// otherwise return null.
+  ///
+  const APInt *getSingleElement() const {
+    if (Upper == Lower + 1)
+      return &Lower;
+    return 0;
+  }
+
+  /// isSingleElement - Return true if this set contains exactly one member.
+  ///
+  bool isSingleElement() const { return getSingleElement() != 0; }
+
+  /// operator== - Return true if this range is equal to another range.
+  ///
+  bool operator==(const ConstantRangeBase &CR) const {
+    return Lower == CR.Lower && Upper == CR.Upper;
+  }
+  bool operator!=(const ConstantRangeBase &CR) const {
+    return !operator==(CR);
+  }
+
+  /// print - Print out the bounds to a stream...
+  ///
+  void print(raw_ostream &OS) const;
+
+  /// dump - Allow printing from a debugger easily...
+  ///
+  void dump() const;
+};
+
+/// ConstantRange - This class represents an range of unsigned values.
+///
+class ConstantRange : public ConstantRangeBase {
+  static ConstantRange intersect1Wrapped(const ConstantRange &LHS,
+                                         const ConstantRange &RHS);
+public:
+  /// Initialize a full (the default) or empty set for the specified bit width.
+  ///
+  explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
+
+  /// Initialize a range to hold the single specified value.
+  ///
+  ConstantRange(const APInt &Value);
+
+  /// @brief Initialize a range of values explicitly. This will assert out if
+  /// Lower==Upper and Lower != Min or Max value for its type. It will also
+  /// assert out if the two APInt's are not the same bit width.
+  ConstantRange(const APInt& Lower, const APInt& Upper);
+
   /// isFullSet - Return true if this set contains all of the elements possible
   /// for this data-type
   ///
@@ -83,19 +133,6 @@
   ///
   bool contains(const APInt &Val) const;
 
-  /// getSingleElement - If this set contains a single element, return it,
-  /// otherwise return null.
-  ///
-  const APInt *getSingleElement() const {
-    if (Upper == Lower + 1)
-      return &Lower;
-    return 0;
-  }
-
-  /// isSingleElement - Return true if this set contains exactly one member.
-  ///
-  bool isSingleElement() const { return getSingleElement() != 0; }
-
   /// getSetSize - Return the number of elements in this set.
   ///
   APInt getSetSize() const;
@@ -120,15 +157,6 @@
   ///
   APInt getSignedMin() const;
 
-  /// operator== - Return true if this range is equal to another range.
-  ///
-  bool operator==(const ConstantRange &CR) const {
-    return Lower == CR.Lower && Upper == CR.Upper;
-  }
-  bool operator!=(const ConstantRange &CR) const {
-    return !operator==(CR);
-  }
-
   /// subtract - Subtract the specified constant from the endpoints of this
   /// constant range.
   ConstantRange subtract(const APInt &CI) const;
@@ -176,20 +204,170 @@
   /// truncated to the specified type.
   ConstantRange truncate(uint32_t BitWidth) const;
 
-  /// print - Print out the bounds to a stream...
+  /// add - Return a new range representing the possible values resulting
+  /// from an addition of a value in this range and a value in Other.
+  ConstantRange add(const ConstantRange &Other) const;
+
+  /// multiply - Return a new range representing the possible values resulting
+  /// from a multiplication of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantRange multiply(const ConstantRange &Other) const;
+
+  /// smax - Return a new range representing the possible values resulting
+  /// from a signed maximum of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantRange smax(const ConstantRange &Other) const;
+
+  /// umax - Return a new range representing the possible values resulting
+  /// from an unsigned maximum of a value in this range and a value in Other.
+  ConstantRange umax(const ConstantRange &Other) const;
+
+  /// udiv - Return a new range representing the possible values resulting
+  /// from an unsigned division of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantRange udiv(const ConstantRange &Other) const;
+};
+
+/// ConstantRange - This class represents an range of signed values.
+///
+class ConstantSignedRange : public ConstantRangeBase {
+  static ConstantSignedRange intersect1Wrapped(const ConstantSignedRange &LHS,
+                                               const ConstantSignedRange &RHS);
+public:
+  /// Initialize a full (the default) or empty set for the specified bit width.
   ///
-  void print(raw_ostream &OS) const;
+  explicit ConstantSignedRange(uint32_t BitWidth, bool isFullSet = true);
 
-  /// dump - Allow printing from a debugger easily...
+  /// Initialize a range to hold the single specified value.
   ///
-  void dump() const;
+  ConstantSignedRange(const APInt &Value);
+
+  /// @brief Initialize a range of values explicitly. This will assert out if
+  /// Lower==Upper and Lower != Min or Max value for its type. It will also
+  /// assert out if the two APInt's are not the same bit width.
+  ConstantSignedRange(const APInt& Lower, const APInt& Upper);
+
+  /// isFullSet - Return true if this set contains all of the elements possible
+  /// for this data-type
+  ///
+  bool isFullSet() const;
+
+  /// isEmptySet - Return true if this set contains no members.
+  ///
+  bool isEmptySet() const;
+
+  /// isWrappedSet - Return true if this set wraps around the top of the range,
+  /// for example: [100, 8)
+  ///
+  bool isWrappedSet() const;
+
+  /// contains - Return true if the specified value is in the set.
+  ///
+  bool contains(const APInt &Val) const;
+
+  /// getSetSize - Return the number of elements in this set.
+  ///
+  APInt getSetSize() const;
+
+  /// getUnsignedMax - Return the largest unsigned value contained in the
+  /// ConstantSignedRange.
+  ///
+  APInt getUnsignedMax() const;
+
+  /// getUnsignedMin - Return the smallest unsigned value contained in the
+  /// ConstantSignedRange.
+  ///
+  APInt getUnsignedMin() const;
+
+  /// getSignedMax - Return the largest signed value contained in the
+  /// ConstantSignedRange.
+  ///
+  APInt getSignedMax() const;
+
+  /// getSignedMin - Return the smallest signed value contained in the
+  /// ConstantSignedRange.
+  ///
+  APInt getSignedMin() const;
+
+  /// subtract - Subtract the specified constant from the endpoints of this
+  /// constant range.
+  ConstantSignedRange subtract(const APInt &CI) const;
+
+  /// intersectWith - Return the range that results from the intersection of
+  /// this range with another range.  The resultant range is pruned as much as
+  /// possible, but there may be cases where elements are included that are in
+  /// one of the sets but not the other.  For example: [100, 8) intersect [3,
+  /// 120) yields [3, 120)
+  ///
+  ConstantSignedRange intersectWith(const ConstantSignedRange &CR) const;
+
+  /// maximalIntersectWith - Return the range that results from the intersection
+  /// of this range with another range.  The resultant range is guaranteed to
+  /// include all elements contained in both input ranges, and to have the
+  /// smallest possible set size that does so.  Because there may be two
+  /// intersections with the same set size, A.maximalIntersectWith(B) might not
+  /// be equal to B.maximalIntersectWith(A).
+  ///
+  ConstantSignedRange maximalIntersectWith(const ConstantSignedRange &CR) const;
+
+  /// unionWith - Return the range that results from the union of this range
+  /// with another range.  The resultant range is guaranteed to include the
+  /// elements of both sets, but may contain more.  For example, [3, 9) union
+  /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
+  /// in either set before.
+  ///
+  ConstantSignedRange unionWith(const ConstantSignedRange &CR) const;
+
+  /// zeroExtend - Return a new range in the specified integer type, which must
+  /// be strictly larger than the current type.  The returned range will
+  /// correspond to the possible range of values if the source range had been
+  /// zero extended to BitWidth.
+  ConstantSignedRange zeroExtend(uint32_t BitWidth) const;
+
+  /// signExtend - Return a new range in the specified integer type, which must
+  /// be strictly larger than the current type.  The returned range will
+  /// correspond to the possible range of values if the source range had been
+  /// sign extended to BitWidth.
+  ConstantSignedRange signExtend(uint32_t BitWidth) const;
+
+  /// truncate - Return a new range in the specified integer type, which must be
+  /// strictly smaller than the current type.  The returned range will
+  /// correspond to the possible range of values if the source range had been
+  /// truncated to the specified type.
+  ConstantSignedRange truncate(uint32_t BitWidth) const;
+
+  /// add - Return a new range representing the possible values resulting
+  /// from an addition of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantSignedRange add(const ConstantSignedRange &Other) const;
+
+  /// multiply - Return a new range representing the possible values resulting
+  /// from a multiplication of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantSignedRange multiply(const ConstantSignedRange &Other) const;
+
+  /// smax - Return a new range representing the possible values resulting
+  /// from a signed maximum of a value in this range and a value in Other.
+  ConstantSignedRange smax(const ConstantSignedRange &Other) const;
+
+  /// umax - Return a new range representing the possible values resulting
+  /// from an unsigned maximum of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantSignedRange umax(const ConstantSignedRange &Other) const;
+
+  /// udiv - Return a new range representing the possible values resulting
+  /// from an unsigned division of a value in this range and a value in Other.
+  /// TODO: This isn't fully implemented yet.
+  ConstantSignedRange udiv(const ConstantSignedRange &Other) const;
 };
 
-inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) {
+inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRangeBase &CR) {
   CR.print(OS);
   return OS;
 }
 
+std::ostream &operator<<(std::ostream &OS, const ConstantRangeBase &CR);
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/lib/Support/ConstantRange.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ConstantRange.cpp?rev=75177&r1=75176&r2=75177&view=diff

==============================================================================
--- llvm/trunk/lib/Support/ConstantRange.cpp (original)
+++ llvm/trunk/lib/Support/ConstantRange.cpp Thu Jul  9 17:07:27 2009
@@ -25,10 +25,40 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
+/// Initialize a range to hold the single specified value.
+///
+ConstantRangeBase::ConstantRangeBase(const APInt & V)
+  : Lower(V), Upper(V + 1) {}
+
+ConstantRangeBase::ConstantRangeBase(const APInt &L, const APInt &U)
+  : Lower(L), Upper(U) {
+  assert(L.getBitWidth() == U.getBitWidth() &&
+         "ConstantRange with unequal bit widths");
+}
+
+/// print - Print out the bounds to a stream...
+///
+void ConstantRangeBase::print(raw_ostream &OS) const {
+  OS << "[" << Lower << "," << Upper << ")";
+}
+
+/// dump - Allow printing from a debugger easily...
+///
+void ConstantRangeBase::dump() const {
+  print(errs());
+}
+
+std::ostream &llvm::operator<<(std::ostream &o,
+                               const ConstantRangeBase &CR) {
+  raw_os_ostream OS(o);
+  OS << CR;
+  return o;
+}
+
 /// Initialize a full (the default) or empty set for the specified type.
 ///
 ConstantRange::ConstantRange(uint32_t BitWidth, bool Full) :
-  Lower(BitWidth, 0), Upper(BitWidth, 0) {
+  ConstantRangeBase(APInt(BitWidth, 0), APInt(BitWidth, 0)) {
   if (Full)
     Lower = Upper = APInt::getMaxValue(BitWidth);
   else
@@ -37,12 +67,10 @@
 
 /// Initialize a range to hold the single specified value.
 ///
-ConstantRange::ConstantRange(const APInt & V) : Lower(V), Upper(V + 1) { }
+ConstantRange::ConstantRange(const APInt & V) : ConstantRangeBase(V) {}
 
-ConstantRange::ConstantRange(const APInt &L, const APInt &U) :
-  Lower(L), Upper(U) {
-  assert(L.getBitWidth() == U.getBitWidth() && 
-         "ConstantRange with unequal bit widths");
+ConstantRange::ConstantRange(const APInt &L, const APInt &U)
+  : ConstantRangeBase(L, U) {
   assert((L != U || (L.isMaxValue() || L.isMinValue())) &&
          "Lower == Upper, but they aren't min or max value!");
 }
@@ -221,9 +249,8 @@
 
   if (!isWrappedSet()) {
     if (!CR.isWrappedSet()) {
-      using namespace APIntOps;
-      APInt L = umax(Lower, CR.Lower);
-      APInt U = umin(Upper, CR.Upper);
+      APInt L = APIntOps::umax(Lower, CR.Lower);
+      APInt U = APIntOps::umin(Upper, CR.Upper);
 
       if (L.ult(U)) // If range isn't empty...
         return ConstantRange(L, U);
@@ -236,9 +263,8 @@
       return intersect1Wrapped(*this, CR);
     else {
       // Both ranges are wrapped...
-      using namespace APIntOps;
-      APInt L = umax(Lower, CR.Lower);
-      APInt U = umin(Upper, CR.Upper);
+      APInt L = APIntOps::umax(Lower, CR.Lower);
+      APInt U = APIntOps::umin(Upper, CR.Upper);
       return ConstantRange(L, U);
     }
   }
@@ -251,7 +277,8 @@
 /// smallest possible set size that does so.  Because there may be two
 /// intersections with the same set size, A.maximalIntersectWith(B) might not
 /// be equal to B.maximalIntersect(A).
-ConstantRange ConstantRange::maximalIntersectWith(const ConstantRange &CR) const {
+ConstantRange
+ConstantRange::maximalIntersectWith(const ConstantRange &CR) const {
   assert(getBitWidth() == CR.getBitWidth() && 
          "ConstantRange types don't agree!");
 
@@ -459,14 +486,540 @@
   return ConstantRange(L, U);
 }
 
-/// print - Print out the bounds to a stream...
+ConstantRange
+ConstantRange::add(const ConstantRange &Other) const {
+  if (isEmptySet() || Other.isEmptySet())
+    return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+  APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize();
+  APInt NewLower = getLower() + Other.getLower();
+  APInt NewUpper = getUpper() + Other.getUpper() - 1;
+  if (NewLower == NewUpper)
+    return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+  ConstantRange X = ConstantRange(NewLower, NewUpper);
+  if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
+    // We've wrapped, therefore, full set.
+    return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+  return X;
+}
+
+ConstantRange
+ConstantRange::multiply(const ConstantRange &Other) const {
+  // TODO: Implement multiply.
+  return ConstantRange(getBitWidth(),
+                       !(isEmptySet() || Other.isEmptySet()));
+}
+
+ConstantRange
+ConstantRange::smax(const ConstantRange &Other) const {
+  // TODO: Implement smax.
+  return ConstantRange(getBitWidth(),
+                       !(isEmptySet() || Other.isEmptySet()));
+}
+
+ConstantRange
+ConstantRange::umax(const ConstantRange &Other) const {
+  // X umax Y is: range(umax(X_umin, Y_umin),
+  //                    umax(X_umax, Y_umax))
+  if (isEmptySet() || Other.isEmptySet())
+    return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+  if (isFullSet() || Other.isFullSet())
+    return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+  APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
+  APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
+  if (NewU == NewL)
+    return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+  return ConstantRange(NewL, NewU);
+}
+
+ConstantRange
+ConstantRange::udiv(const ConstantRange &Other) const {
+  // TODO: Implement udiv.
+  return ConstantRange(getBitWidth(),
+                       !(isEmptySet() || Other.isEmptySet()));
+}
+
+/// Initialize a full (the default) or empty set for the specified type.
 ///
-void ConstantRange::print(raw_ostream &OS) const {
-  OS << "[" << Lower << "," << Upper << ")";
+ConstantSignedRange::ConstantSignedRange(uint32_t BitWidth, bool Full) :
+  ConstantRangeBase(APInt(BitWidth, 0), APInt(BitWidth, 0)) {
+  if (Full)
+    Lower = Upper = APInt::getSignedMaxValue(BitWidth);
+  else
+    Lower = Upper = APInt::getSignedMinValue(BitWidth);
 }
 
-/// dump - Allow printing from a debugger easily...
+/// Initialize a range to hold the single specified value.
 ///
-void ConstantRange::dump() const {
-  print(errs());
+ConstantSignedRange::ConstantSignedRange(const APInt & V)
+  : ConstantRangeBase(V) {}
+
+ConstantSignedRange::ConstantSignedRange(const APInt &L, const APInt &U)
+  : ConstantRangeBase(L, U) {
+  assert((L != U || (L.isMaxSignedValue() || L.isMinSignedValue())) &&
+         "Lower == Upper, but they aren't min or max value!");
+}
+
+/// isFullSet - Return true if this set contains all of the elements possible
+/// for this data-type
+bool ConstantSignedRange::isFullSet() const {
+  return Lower == Upper && Lower.isMaxSignedValue();
+}
+
+/// isEmptySet - Return true if this set contains no members.
+///
+bool ConstantSignedRange::isEmptySet() const {
+  return Lower == Upper && Lower.isMinSignedValue();
+}
+
+/// isWrappedSet - Return true if this set wraps around the top of the range,
+/// for example: [100, 8)
+///
+bool ConstantSignedRange::isWrappedSet() const {
+  return Lower.sgt(Upper);
+}
+
+/// getSetSize - Return the number of elements in this set.
+///
+APInt ConstantSignedRange::getSetSize() const {
+  if (isEmptySet())
+    return APInt(getBitWidth(), 0);
+  if (getBitWidth() == 1) {
+    if (Lower != Upper)  // One of T or F in the set...
+      return APInt(2, 1);
+    return APInt(2, 2);      // Must be full set...
+  }
+
+  // Simply subtract the bounds...
+  return Upper - Lower;
+}
+
+/// getSignedMax - Return the largest signed value contained in the
+/// ConstantSignedRange.
+///
+APInt ConstantSignedRange::getSignedMax() const {
+  if (isFullSet() || isWrappedSet())
+    return APInt::getSignedMaxValue(getBitWidth());
+  else
+    return getUpper() - 1;
+}
+
+/// getSignedMin - Return the smallest signed value contained in the
+/// ConstantSignedRange.
+///
+APInt ConstantSignedRange::getSignedMin() const {
+  if (isFullSet() || (isWrappedSet() &&
+                      getUpper() != APInt::getSignedMinValue(getBitWidth())))
+    return APInt::getSignedMinValue(getBitWidth());
+  else
+    return getLower();
+}
+
+/// getUnsignedMax - Return the largest unsigned value contained in the
+/// ConstantSignedRange.
+///
+APInt ConstantSignedRange::getUnsignedMax() const {
+  APInt UnsignedMax(APInt::getMaxValue(getBitWidth()));
+  if (!isWrappedSet()) {
+    if (getLower().ule(getUpper() - 1))
+      return getUpper() - 1;
+    else
+      return UnsignedMax;
+  } else {
+    if ((getUpper() - 1).ult(getLower())) {
+      if (getLower() != UnsignedMax)
+        return UnsignedMax;
+      else
+        return getUpper() - 1;
+    } else {
+      return getUpper() - 1;
+    }
+  }
+}
+
+/// getUnsignedMin - Return the smallest unsigned value contained in the
+/// ConstantSignedRange.
+///
+APInt ConstantSignedRange::getUnsignedMin() const {
+  APInt UnsignedMin(APInt::getMinValue(getBitWidth()));
+  if (!isWrappedSet()) {
+    if (getLower().ule(getUpper() - 1))
+      return getLower();
+    else
+      return UnsignedMin;
+  } else {
+    if ((getUpper() - 1).ult(getLower())) {
+      if (getUpper() != UnsignedMin)
+        return UnsignedMin;
+      else
+        return getLower();
+    } else {
+      return getLower();
+    }
+  }
+}
+
+/// contains - Return true if the specified value is in the set.
+///
+bool ConstantSignedRange::contains(const APInt &V) const {
+  if (Lower == Upper)
+    return isFullSet();
+
+  if (!isWrappedSet())
+    return Lower.sle(V) && V.slt(Upper);
+  else
+    return Lower.sle(V) || V.slt(Upper);
+}
+
+/// subtract - Subtract the specified constant from the endpoints of this
+/// constant range.
+ConstantSignedRange ConstantSignedRange::subtract(const APInt &Val) const {
+  assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width");
+  // If the set is empty or full, don't modify the endpoints.
+  if (Lower == Upper)
+    return *this;
+  return ConstantSignedRange(Lower - Val, Upper - Val);
+}
+
+
+// intersect1Wrapped - This helper function is used to intersect two ranges when
+// it is known that LHS is wrapped and RHS isn't.
+//
+ConstantSignedRange
+ConstantSignedRange::intersect1Wrapped(const ConstantSignedRange &LHS,
+                                 const ConstantSignedRange &RHS) {
+  assert(LHS.isWrappedSet() && !RHS.isWrappedSet());
+
+  // Check to see if we overlap on the Left side of RHS...
+  //
+  if (RHS.Lower.slt(LHS.Upper)) {
+    // We do overlap on the left side of RHS, see if we overlap on the right of
+    // RHS...
+    if (RHS.Upper.sgt(LHS.Lower)) {
+      // Ok, the result overlaps on both the left and right sides.  See if the
+      // resultant interval will be smaller if we wrap or not...
+      //
+      if (LHS.getSetSize().ult(RHS.getSetSize()))
+        return LHS;
+      else
+        return RHS;
+
+    } else {
+      // No overlap on the right, just on the left.
+      return ConstantSignedRange(RHS.Lower, LHS.Upper);
+    }
+  } else {
+    // We don't overlap on the left side of RHS, see if we overlap on the right
+    // of RHS...
+    if (RHS.Upper.sgt(LHS.Lower)) {
+      // Simple overlap...
+      return ConstantSignedRange(LHS.Lower, RHS.Upper);
+    } else {
+      // No overlap...
+      return ConstantSignedRange(LHS.getBitWidth(), false);
+    }
+  }
+}
+
+/// intersectWith - Return the range that results from the intersection of this
+/// range with another range.
+///
+ConstantSignedRange
+ConstantSignedRange::intersectWith(const ConstantSignedRange &CR) const {
+  assert(getBitWidth() == CR.getBitWidth() &&
+         "ConstantSignedRange types don't agree!");
+  // Handle common special cases
+  if (isEmptySet() || CR.isFullSet())
+    return *this;
+  if (isFullSet()  || CR.isEmptySet())
+    return CR;
+
+  if (!isWrappedSet()) {
+    if (!CR.isWrappedSet()) {
+      APInt L = APIntOps::smax(Lower, CR.Lower);
+      APInt U = APIntOps::smin(Upper, CR.Upper);
+
+      if (L.slt(U)) // If range isn't empty...
+        return ConstantSignedRange(L, U);
+      else
+        return ConstantSignedRange(getBitWidth(), false);// Otherwise, empty set
+    } else
+      return intersect1Wrapped(CR, *this);
+  } else {   // We know "this" is wrapped...
+    if (!CR.isWrappedSet())
+      return intersect1Wrapped(*this, CR);
+    else {
+      // Both ranges are wrapped...
+      APInt L = APIntOps::smax(Lower, CR.Lower);
+      APInt U = APIntOps::smin(Upper, CR.Upper);
+      return ConstantSignedRange(L, U);
+    }
+  }
+  return *this;
+}
+
+/// maximalIntersectWith - Return the range that results from the intersection
+/// of this range with another range.  The resultant range is guaranteed to
+/// include all elements contained in both input ranges, and to have the
+/// smallest possible set size that does so.  Because there may be two
+/// intersections with the same set size, A.maximalIntersectWith(B) might not
+/// be equal to B.maximalIntersect(A).
+ConstantSignedRange
+ConstantSignedRange::maximalIntersectWith(const ConstantSignedRange &CR) const {
+  assert(getBitWidth() == CR.getBitWidth() &&
+         "ConstantSignedRange types don't agree!");
+
+  // Handle common cases.
+  if (   isEmptySet() || CR.isFullSet()) return *this;
+  if (CR.isEmptySet() ||    isFullSet()) return CR;
+
+  if (!isWrappedSet() && CR.isWrappedSet())
+    return CR.maximalIntersectWith(*this);
+
+  if (!isWrappedSet() && !CR.isWrappedSet()) {
+    if (Lower.slt(CR.Lower)) {
+      if (Upper.sle(CR.Lower))
+        return ConstantSignedRange(getBitWidth(), false);
+
+      if (Upper.slt(CR.Upper))
+        return ConstantSignedRange(CR.Lower, Upper);
+
+      return CR;
+    } else {
+      if (Upper.slt(CR.Upper))
+        return *this;
+
+      if (Lower.slt(CR.Upper))
+        return ConstantSignedRange(Lower, CR.Upper);
+
+      return ConstantSignedRange(getBitWidth(), false);
+    }
+  }
+
+  if (isWrappedSet() && !CR.isWrappedSet()) {
+    if (CR.Lower.slt(Upper)) {
+      if (CR.Upper.slt(Upper))
+        return CR;
+
+      if (CR.Upper.slt(Lower))
+        return ConstantSignedRange(CR.Lower, Upper);
+
+      if (getSetSize().ult(CR.getSetSize()))
+        return *this;
+      else
+        return CR;
+    } else if (CR.Lower.slt(Lower)) {
+      if (CR.Upper.sle(Lower))
+        return ConstantSignedRange(getBitWidth(), false);
+
+      return ConstantSignedRange(Lower, CR.Upper);
+    }
+    return CR;
+  }
+
+  if (CR.Upper.slt(Upper)) {
+    if (CR.Lower.slt(Upper)) {
+      if (getSetSize().ult(CR.getSetSize()))
+        return *this;
+      else
+        return CR;
+    }
+
+    if (CR.Lower.slt(Lower))
+      return ConstantSignedRange(Lower, CR.Upper);
+
+    return CR;
+  } else if (CR.Upper.slt(Lower)) {
+    if (CR.Lower.slt(Lower))
+      return *this;
+
+    return ConstantSignedRange(CR.Lower, Upper);
+  }
+  if (getSetSize().ult(CR.getSetSize()))
+    return *this;
+  else
+    return CR;
+}
+
+
+/// unionWith - Return the range that results from the union of this range with
+/// another range.  The resultant range is guaranteed to include the elements of
+/// both sets, but may contain more.  For example, [3, 9) union [12,15) is
+/// [3, 15), which includes 9, 10, and 11, which were not included in either
+/// set before.
+///
+ConstantSignedRange
+ConstantSignedRange::unionWith(const ConstantSignedRange &CR) const {
+  assert(getBitWidth() == CR.getBitWidth() &&
+         "ConstantSignedRange types don't agree!");
+
+  if (   isFullSet() || CR.isEmptySet()) return *this;
+  if (CR.isFullSet() ||    isEmptySet()) return CR;
+
+  if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this);
+
+  APInt L = Lower, U = Upper;
+
+  if (!isWrappedSet() && !CR.isWrappedSet()) {
+    if (CR.Lower.slt(L))
+      L = CR.Lower;
+
+    if (CR.Upper.sgt(U))
+      U = CR.Upper;
+  }
+
+  if (isWrappedSet() && !CR.isWrappedSet()) {
+    if ((CR.Lower.slt(Upper) && CR.Upper.slt(Upper)) ||
+        (CR.Lower.sgt(Lower) && CR.Upper.sgt(Lower))) {
+      return *this;
+    }
+
+    if (CR.Lower.sle(Upper) && Lower.sle(CR.Upper)) {
+      return ConstantSignedRange(getBitWidth());
+    }
+
+    if (CR.Lower.sle(Upper) && CR.Upper.sle(Lower)) {
+      APInt d1 = CR.Upper - Upper, d2 = Lower - CR.Upper;
+      if (d1.slt(d2)) {
+        U = CR.Upper;
+      } else {
+        L = CR.Upper;
+      }
+    }
+
+    if (Upper.slt(CR.Lower) && CR.Upper.slt(Lower)) {
+      APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
+      if (d1.slt(d2)) {
+        U = CR.Lower + 1;
+      } else {
+        L = CR.Upper - 1;
+      }
+    }
+
+    if (Upper.slt(CR.Lower) && Lower.slt(CR.Upper)) {
+      APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Lower;
+
+      if (d1.slt(d2)) {
+        U = CR.Lower + 1;
+      } else {
+        L = CR.Lower;
+      }
+    }
+  }
+
+  if (isWrappedSet() && CR.isWrappedSet()) {
+    if (Lower.slt(CR.Upper) || CR.Lower.slt(Upper))
+      return ConstantSignedRange(getBitWidth());
+
+    if (CR.Upper.sgt(U)) {
+      U = CR.Upper;
+    }
+
+    if (CR.Lower.slt(L)) {
+      L = CR.Lower;
+    }
+
+    if (L == U) return ConstantSignedRange(getBitWidth());
+  }
+
+  return ConstantSignedRange(L, U);
+}
+
+/// zeroExtend - Return a new range in the specified integer type, which must
+/// be strictly larger than the current type.  The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// zero extended.
+ConstantSignedRange ConstantSignedRange::zeroExtend(uint32_t DstTySize) const {
+  unsigned SrcTySize = getBitWidth();
+  assert(SrcTySize < DstTySize && "Not a value extension");
+  if (isEmptySet())
+    return ConstantSignedRange(SrcTySize, /*isFullSet=*/false);
+  if (isFullSet())
+    // Change a source full set into [0, 1 << 8*numbytes)
+    return ConstantSignedRange(APInt(DstTySize,0),
+                               APInt(DstTySize,1).shl(SrcTySize));
+
+  APInt L, U;
+  if (Lower.isNegative() && !Upper.isNegative()) {
+    L = APInt(SrcTySize, 0);
+    U = APInt::getSignedMinValue(SrcTySize);
+  } else {
+    L = Lower;
+    U = Upper;
+  }
+  L.zext(DstTySize);
+  U.zext(DstTySize);
+  return ConstantSignedRange(L, U);
+}
+
+/// signExtend - Return a new range in the specified integer type, which must
+/// be strictly larger than the current type.  The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// sign extended.
+ConstantSignedRange ConstantSignedRange::signExtend(uint32_t DstTySize) const {
+  unsigned SrcTySize = getBitWidth();
+  assert(SrcTySize < DstTySize && "Not a value extension");
+  if (isEmptySet())
+    return ConstantSignedRange(SrcTySize, /*isFullSet=*/false);
+  if (isFullSet())
+    return ConstantSignedRange(APInt(getSignedMin()).sext(DstTySize),
+                               APInt(getSignedMax()).sext(DstTySize)+1);
+
+  APInt L = Lower; L.sext(DstTySize);
+  APInt U = Upper; U.sext(DstTySize);
+  return ConstantSignedRange(L, U);
+}
+
+/// truncate - Return a new range in the specified integer type, which must be
+/// strictly smaller than the current type.  The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// truncated to the specified type.
+ConstantSignedRange ConstantSignedRange::truncate(uint32_t DstTySize) const {
+  // TODO: Implement truncate.
+  return ConstantSignedRange(DstTySize, !isEmptySet());
+}
+
+ConstantSignedRange
+ConstantSignedRange::add(const ConstantSignedRange &Other) const {
+  // TODO: Implement add.
+  return ConstantSignedRange(getBitWidth(),
+                             !(isEmptySet() || Other.isEmptySet()));
+}
+
+ConstantSignedRange
+ConstantSignedRange::multiply(const ConstantSignedRange &Other) const {
+  // TODO: Implement multiply.
+  return ConstantSignedRange(getBitWidth(),
+                             !(isEmptySet() || Other.isEmptySet()));
+}
+
+ConstantSignedRange
+ConstantSignedRange::smax(const ConstantSignedRange &Other) const {
+  // X smax Y is: range(smax(X_smin, Y_smin),
+  //                    smax(X_smax, Y_smax))
+  if (isEmptySet() || Other.isEmptySet())
+    return ConstantSignedRange(getBitWidth(), /*isFullSet=*/false);
+  if (isFullSet() || Other.isFullSet())
+    return ConstantSignedRange(getBitWidth(), /*isFullSet=*/true);
+  APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
+  APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
+  if (NewU == NewL)
+    return ConstantSignedRange(getBitWidth(), /*isFullSet=*/true);
+  return ConstantSignedRange(NewL, NewU);
+}
+
+ConstantSignedRange
+ConstantSignedRange::umax(const ConstantSignedRange &Other) const {
+  // TODO: Implement umax.
+  return ConstantSignedRange(getBitWidth(),
+                             !(isEmptySet() || Other.isEmptySet()));
+}
+
+ConstantSignedRange
+ConstantSignedRange::udiv(const ConstantSignedRange &Other) const {
+  // TODO: Implement udiv.
+  return ConstantSignedRange(getBitWidth(),
+                             !(isEmptySet() || Other.isEmptySet()));
 }

Added: llvm/trunk/unittests/Support/ConstantRangeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ConstantRangeTest.cpp?rev=75177&view=auto

==============================================================================
--- llvm/trunk/unittests/Support/ConstantRangeTest.cpp (added)
+++ llvm/trunk/unittests/Support/ConstantRangeTest.cpp Thu Jul  9 17:07:27 2009
@@ -0,0 +1,582 @@
+//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange tests --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ConstantRange.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(ConstantRangeTest, Unsigned) {
+  ConstantRange Full(16);
+  ConstantRange Empty(16, false);
+  ConstantRange One(APInt(16, 0xa));
+  ConstantRange Some(APInt(16, 0xa), APInt(16, 0xaaa));
+  ConstantRange Wrap(APInt(16, 0xaaa), APInt(16, 0xa));
+
+  EXPECT_TRUE(Full.isFullSet());
+  EXPECT_FALSE(Full.isEmptySet());
+  EXPECT_FALSE(Full.isWrappedSet());
+  EXPECT_TRUE(Full.contains(APInt(16, 0x0)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xa)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xaa9)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Empty.isFullSet());
+  EXPECT_TRUE(Empty.isEmptySet());
+  EXPECT_FALSE(Empty.isWrappedSet());
+  EXPECT_FALSE(Empty.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0x9)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(One.isFullSet());
+  EXPECT_FALSE(One.isEmptySet());
+  EXPECT_FALSE(One.isWrappedSet());
+  EXPECT_FALSE(One.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(One.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(One.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(One.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(One.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Some.isFullSet());
+  EXPECT_FALSE(Some.isEmptySet());
+  EXPECT_FALSE(Some.isWrappedSet());
+  EXPECT_FALSE(Some.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(Some.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(Some.contains(APInt(16, 0xa)));
+  EXPECT_TRUE(Some.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(Some.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Wrap.isFullSet());
+  EXPECT_FALSE(Wrap.isEmptySet());
+  EXPECT_TRUE(Wrap.isWrappedSet());
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0x0)));
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0x9)));
+  EXPECT_FALSE(Wrap.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9)));
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa)));
+
+  EXPECT_EQ(Full, Full);
+  EXPECT_EQ(Empty, Empty);
+  EXPECT_EQ(One, One);
+  EXPECT_EQ(Some, Some);
+  EXPECT_EQ(Wrap, Wrap);
+  EXPECT_NE(Full, Empty);
+  EXPECT_NE(Full, One);
+  EXPECT_NE(Full, Some);
+  EXPECT_NE(Full, Wrap);
+  EXPECT_NE(Empty, One);
+  EXPECT_NE(Empty, Some);
+  EXPECT_NE(Empty, Wrap);
+  EXPECT_NE(One, Some);
+  EXPECT_NE(One, Wrap);
+  EXPECT_NE(Some, Wrap);
+
+  EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL));
+
+  EXPECT_FALSE(Full.isSingleElement());
+  EXPECT_FALSE(Empty.isSingleElement());
+  EXPECT_TRUE(One.isSingleElement());
+  EXPECT_FALSE(Some.isSingleElement());
+  EXPECT_FALSE(Wrap.isSingleElement());
+
+  EXPECT_EQ(Full.getSetSize(), APInt(16, 0));
+  EXPECT_EQ(Empty.getSetSize(), APInt(16, 0));
+  EXPECT_EQ(One.getSetSize(), APInt(16, 1));
+  EXPECT_EQ(Some.getSetSize(), APInt(16, 0xaa0));
+  EXPECT_EQ(Wrap.getSetSize(), APInt(16, 0x10000 - 0xaa0));
+
+  EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX));
+  EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9));
+  EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX));
+
+  EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0));
+  EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0));
+
+  EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX));
+  EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9));
+  EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX));
+
+  EXPECT_EQ(Full.getSignedMin(), APInt(16, INT16_MIN));
+  EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Wrap.getSignedMin(), APInt(16, INT16_MIN));
+
+  ConstantRange TFull = Full.truncate(10);
+  ConstantRange TEmpty = Empty.truncate(10);
+  ConstantRange TOne = One.truncate(10);
+  ConstantRange TSome = Some.truncate(10);
+  ConstantRange TWrap = Wrap.truncate(10);
+  EXPECT_TRUE(TFull.isFullSet());
+  EXPECT_TRUE(TEmpty.isEmptySet());
+  EXPECT_EQ(TOne, ConstantRange(APInt(One.getLower()).trunc(10),
+                                APInt(One.getUpper()).trunc(10)));
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_TRUE(TSome.isFullSet());
+
+  ConstantRange ZFull = Full.zeroExtend(20);
+  ConstantRange ZEmpty = Empty.zeroExtend(20);
+  ConstantRange ZOne = One.zeroExtend(20);
+  ConstantRange ZSome = Some.zeroExtend(20);
+  ConstantRange ZWrap = Wrap.zeroExtend(20);
+  EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000)));
+  EXPECT_TRUE(ZEmpty.isEmptySet());
+  EXPECT_EQ(ZOne, ConstantRange(APInt(One.getLower()).zext(20),
+                                APInt(One.getUpper()).zext(20)));
+  EXPECT_EQ(ZSome, ConstantRange(APInt(Some.getLower()).zext(20),
+                                 APInt(Some.getUpper()).zext(20)));
+  EXPECT_EQ(ZWrap, ConstantRange(APInt(Wrap.getLower()).zext(20),
+                                 APInt(Wrap.getUpper()).zext(20)));
+
+  ConstantRange SFull = Full.signExtend(20);
+  ConstantRange SEmpty = Empty.signExtend(20);
+  ConstantRange SOne = One.signExtend(20);
+  ConstantRange SSome = Some.signExtend(20);
+  ConstantRange SWrap = Wrap.signExtend(20);
+  EXPECT_EQ(SFull, ConstantRange(APInt(20, INT16_MIN, true),
+                                 APInt(20, INT16_MAX, true)));
+  EXPECT_TRUE(SEmpty.isEmptySet());
+  EXPECT_EQ(SOne, ConstantRange(APInt(One.getLower()).sext(20),
+                                APInt(One.getUpper()).sext(20)));
+  EXPECT_EQ(SSome, ConstantRange(APInt(Some.getLower()).sext(20),
+                                 APInt(Some.getUpper()).sext(20)));
+  EXPECT_EQ(SWrap, ConstantRange(APInt(Wrap.getLower()).sext(20),
+                                 APInt(Wrap.getUpper()).sext(20)));
+
+  EXPECT_TRUE(Empty.intersectWith(Full).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Empty).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(One).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Some).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(Full.intersectWith(Full).isFullSet());
+  EXPECT_TRUE(Some.intersectWith(Some) == Some);
+  EXPECT_TRUE(Some.intersectWith(One) == One);
+  EXPECT_TRUE(Full.intersectWith(One) == One);
+  EXPECT_TRUE(Full.intersectWith(Some) == Some);
+  EXPECT_TRUE(Some.intersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(One.intersectWith(Wrap).isEmptySet());
+  EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One));
+
+  EXPECT_TRUE(Empty.maximalIntersectWith(Full).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Empty).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(One).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Some).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(Full.maximalIntersectWith(Full).isFullSet());
+  EXPECT_TRUE(Some.maximalIntersectWith(Some) == Some);
+  EXPECT_TRUE(Some.maximalIntersectWith(One) == One);
+  EXPECT_TRUE(Full.maximalIntersectWith(One) == One);
+  EXPECT_TRUE(Full.maximalIntersectWith(Some) == Some);
+  EXPECT_TRUE(Some.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(One.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_EQ(One.maximalIntersectWith(Wrap), Wrap.maximalIntersectWith(One));
+
+  EXPECT_EQ(Wrap.unionWith(One),
+            ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb)));
+  EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One));
+  EXPECT_TRUE(Empty.unionWith(Empty).isEmptySet());
+  EXPECT_TRUE(Full.unionWith(Full).isFullSet());
+  EXPECT_TRUE(Some.unionWith(Wrap).isFullSet());
+
+  EXPECT_TRUE(Full.subtract(APInt(16, 4)).isFullSet());
+  EXPECT_TRUE(Empty.subtract(APInt(16, 4)).isEmptySet());
+  EXPECT_EQ(Some.subtract(APInt(16, 4)),
+            ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6)));
+  EXPECT_EQ(Wrap.subtract(APInt(16, 4)),
+            ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6)));
+  EXPECT_EQ(One.subtract(APInt(16, 4)),
+            ConstantRange(APInt(16, 0x6)));
+
+  EXPECT_TRUE(Full.add(APInt(16, 4)).isFullSet());
+  EXPECT_TRUE(Empty.add(APInt(16, 4)).isEmptySet());
+  EXPECT_EQ(Some.add(APInt(16, 4)),
+            ConstantRange(APInt(16, 0xe), APInt(16, 0xaae)));
+  EXPECT_EQ(Wrap.add(APInt(16, 4)),
+            ConstantRange(APInt(16, 0xaae), APInt(16, 0xe)));
+  EXPECT_EQ(One.add(APInt(16, 4)),
+            ConstantRange(APInt(16, 0xe)));
+
+  EXPECT_TRUE(Full.umax(Full).isFullSet());
+  EXPECT_TRUE(Full.umax(Empty).isEmptySet());
+  EXPECT_TRUE(Full.umax(Some).isFullSet());
+  EXPECT_TRUE(Full.umax(Wrap).isFullSet());
+  EXPECT_TRUE(Full.umax(One).isFullSet());
+  EXPECT_EQ(Empty.umax(Empty), Empty);
+  EXPECT_EQ(Empty.umax(Some), Empty);
+  EXPECT_EQ(Empty.umax(Wrap), Empty);
+  EXPECT_EQ(Empty.umax(One), Empty);
+  EXPECT_EQ(Some.umax(Some), Some);
+  EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+  EXPECT_EQ(Some.umax(One), Some);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.umax(Wrap), Full);
+  EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+  EXPECT_EQ(One.umax(One), One);
+
+  EXPECT_EQ(Full.multiply(Full), Full);
+  EXPECT_EQ(Full.multiply(Empty), Empty);
+  EXPECT_EQ(Full.multiply(One), Full);
+  EXPECT_EQ(Full.multiply(Some), Full);
+  EXPECT_EQ(Full.multiply(Wrap), Full);
+  EXPECT_EQ(Empty.multiply(Empty), Empty);
+  EXPECT_EQ(Empty.multiply(One), Empty);
+  EXPECT_EQ(Empty.multiply(Some), Empty);
+  EXPECT_EQ(Empty.multiply(Wrap), Empty);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(One), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.multiply(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.multiply(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.multiply(Wrap), Full);
+
+  EXPECT_EQ(Full.smax(Full), Full);
+  EXPECT_EQ(Full.smax(Empty), Empty);
+  EXPECT_EQ(Full.smax(One), Full);
+  EXPECT_EQ(Full.smax(Some), Full);
+  EXPECT_EQ(Full.smax(Wrap), Full);
+  EXPECT_EQ(Empty.smax(Empty), Empty);
+  EXPECT_EQ(Empty.smax(One), Empty);
+  EXPECT_EQ(Empty.smax(Some), Empty);
+  EXPECT_EQ(Empty.smax(Wrap), Empty);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.smax(One), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.smax(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.smax(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.smax(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.smax(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.smax(Wrap), Full);
+
+  EXPECT_EQ(Full.udiv(Full), Full);
+  EXPECT_EQ(Full.udiv(Empty), Empty);
+  EXPECT_EQ(Full.udiv(One), Full);
+  EXPECT_EQ(Full.udiv(Some), Full);
+  EXPECT_EQ(Full.udiv(Wrap), Full);
+  EXPECT_EQ(Empty.udiv(Empty), Empty);
+  EXPECT_EQ(Empty.udiv(One), Empty);
+  EXPECT_EQ(Empty.udiv(Some), Empty);
+  EXPECT_EQ(Empty.udiv(Wrap), Empty);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.udiv(One), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.udiv(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(One.udiv(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.udiv(Some), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Some.udiv(Wrap), Full);
+  // TODO: ConstantRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.udiv(Wrap), Full);
+
+}
+
+TEST(ConstantRangeTest, Signed) {
+  ConstantSignedRange Full(16);
+  ConstantSignedRange Empty(16, false);
+  ConstantSignedRange One(APInt(16, 0xa));
+  ConstantSignedRange Some(APInt(16, 0xa), APInt(16, 0xaaa));
+  ConstantSignedRange Wrap(APInt(16, 0xaaa), APInt(16, 0xa));
+
+  EXPECT_TRUE(Full.isFullSet());
+  EXPECT_FALSE(Full.isEmptySet());
+  EXPECT_FALSE(Full.isWrappedSet());
+  EXPECT_TRUE(Full.contains(APInt(16, 0x0)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xa)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xaa9)));
+  EXPECT_TRUE(Full.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Empty.isFullSet());
+  EXPECT_TRUE(Empty.isEmptySet());
+  EXPECT_FALSE(Empty.isWrappedSet());
+  EXPECT_FALSE(Empty.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0x9)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(One.isFullSet());
+  EXPECT_FALSE(One.isEmptySet());
+  EXPECT_FALSE(One.isWrappedSet());
+  EXPECT_FALSE(One.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(One.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(One.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(One.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(One.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Some.isFullSet());
+  EXPECT_FALSE(Some.isEmptySet());
+  EXPECT_FALSE(Some.isWrappedSet());
+  EXPECT_FALSE(Some.contains(APInt(16, 0x0)));
+  EXPECT_FALSE(Some.contains(APInt(16, 0x9)));
+  EXPECT_TRUE(Some.contains(APInt(16, 0xa)));
+  EXPECT_TRUE(Some.contains(APInt(16, 0xaa9)));
+  EXPECT_FALSE(Some.contains(APInt(16, 0xaaa)));
+
+  EXPECT_FALSE(Wrap.isFullSet());
+  EXPECT_FALSE(Wrap.isEmptySet());
+  EXPECT_TRUE(Wrap.isWrappedSet());
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0x0)));
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0x9)));
+  EXPECT_FALSE(Wrap.contains(APInt(16, 0xa)));
+  EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9)));
+  EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa)));
+
+  EXPECT_EQ(Full, Full);
+  EXPECT_EQ(Empty, Empty);
+  EXPECT_EQ(One, One);
+  EXPECT_EQ(Some, Some);
+  EXPECT_EQ(Wrap, Wrap);
+  EXPECT_NE(Full, Empty);
+  EXPECT_NE(Full, One);
+  EXPECT_NE(Full, Some);
+  EXPECT_NE(Full, Wrap);
+  EXPECT_NE(Empty, One);
+  EXPECT_NE(Empty, Some);
+  EXPECT_NE(Empty, Wrap);
+  EXPECT_NE(One, Some);
+  EXPECT_NE(One, Wrap);
+  EXPECT_NE(Some, Wrap);
+
+  EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(NULL));
+  EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(NULL));
+
+  EXPECT_FALSE(Full.isSingleElement());
+  EXPECT_FALSE(Empty.isSingleElement());
+  EXPECT_TRUE(One.isSingleElement());
+  EXPECT_FALSE(Some.isSingleElement());
+  EXPECT_FALSE(Wrap.isSingleElement());
+
+  EXPECT_EQ(Full.getSetSize(), APInt(16, 0));
+  EXPECT_EQ(Empty.getSetSize(), APInt(16, 0));
+  EXPECT_EQ(One.getSetSize(), APInt(16, 1));
+  EXPECT_EQ(Some.getSetSize(), APInt(16, 0xaa0));
+  EXPECT_EQ(Wrap.getSetSize(), APInt(16, 0x10000 - 0xaa0));
+
+  EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX, true));
+  EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9));
+  EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX));
+
+  EXPECT_EQ(Full.getSignedMin(), APInt(16, INT16_MIN));
+  EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Wrap.getSignedMin(), APInt(16, INT16_MIN));
+
+  EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX, true));
+  EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9));
+  EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX));
+
+  EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0));
+  EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa));
+  EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0));
+
+  ConstantSignedRange TFull = Full.truncate(10);
+  ConstantSignedRange TEmpty = Empty.truncate(10);
+  ConstantSignedRange TOne = One.truncate(10);
+  ConstantSignedRange TSome = Some.truncate(10);
+  ConstantSignedRange TWrap = Wrap.truncate(10);
+  EXPECT_TRUE(TFull.isFullSet());
+  EXPECT_TRUE(TEmpty.isEmptySet());
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_TRUE(TOne.isFullSet());
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_TRUE(TSome.isFullSet());
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_TRUE(TWrap.isFullSet());
+
+  ConstantSignedRange ZFull = Full.zeroExtend(20);
+  ConstantSignedRange ZEmpty = Empty.zeroExtend(20);
+  ConstantSignedRange ZOne = One.zeroExtend(20);
+  ConstantSignedRange ZSome = Some.zeroExtend(20);
+  ConstantSignedRange ZWrap = Wrap.zeroExtend(20);
+  EXPECT_EQ(ZFull, ConstantSignedRange(APInt(20, 0), APInt(20, 0x10000)));
+  EXPECT_TRUE(ZEmpty.isEmptySet());
+  EXPECT_EQ(ZOne, ConstantSignedRange(APInt(One.getLower()).zext(20),
+                                      APInt(One.getUpper()).zext(20)));
+  EXPECT_EQ(ZSome, ConstantSignedRange(APInt(Some.getLower()).zext(20),
+                                       APInt(Some.getUpper()).zext(20)));
+  EXPECT_EQ(ZWrap, ConstantSignedRange(APInt(Wrap.getLower()).zext(20),
+                                       APInt(Wrap.getUpper()).zext(20)));
+
+  ConstantSignedRange SFull = Full.signExtend(20);
+  ConstantSignedRange SEmpty = Empty.signExtend(20);
+  ConstantSignedRange SOne = One.signExtend(20);
+  ConstantSignedRange SSome = Some.signExtend(20);
+  ConstantSignedRange SWrap = Wrap.signExtend(20);
+  EXPECT_EQ(SFull, ConstantSignedRange(APInt(20, INT16_MIN),
+                                       APInt(20, INT16_MAX+1)));
+  EXPECT_TRUE(SEmpty.isEmptySet());
+  EXPECT_EQ(SOne, ConstantSignedRange(APInt(One.getLower()).sext(20),
+                                      APInt(One.getUpper()).sext(20)));
+  EXPECT_EQ(SSome, ConstantSignedRange(APInt(Some.getLower()).sext(20),
+                                       APInt(Some.getUpper()).sext(20)));
+  EXPECT_EQ(SWrap, ConstantSignedRange(APInt(Wrap.getLower()).sext(20),
+                                       APInt(Wrap.getUpper()).sext(20)));
+
+  EXPECT_TRUE(Empty.intersectWith(Full).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Empty).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(One).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Some).isEmptySet());
+  EXPECT_TRUE(Empty.intersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(Full.intersectWith(Full).isFullSet());
+  EXPECT_TRUE(Some.intersectWith(Some) == Some);
+  EXPECT_TRUE(Some.intersectWith(One) == One);
+  EXPECT_TRUE(Full.intersectWith(One) == One);
+  EXPECT_TRUE(Full.intersectWith(Some) == Some);
+  EXPECT_TRUE(Some.intersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(One.intersectWith(Wrap).isEmptySet());
+  EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One));
+
+  EXPECT_TRUE(Empty.maximalIntersectWith(Full).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Empty).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(One).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Some).isEmptySet());
+  EXPECT_TRUE(Empty.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(Full.maximalIntersectWith(Full).isFullSet());
+  EXPECT_TRUE(Some.maximalIntersectWith(Some) == Some);
+  EXPECT_TRUE(Some.maximalIntersectWith(One) == One);
+  EXPECT_TRUE(Full.maximalIntersectWith(One) == One);
+  EXPECT_TRUE(Full.maximalIntersectWith(Some) == Some);
+  EXPECT_TRUE(Some.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_TRUE(One.maximalIntersectWith(Wrap).isEmptySet());
+  EXPECT_EQ(One.maximalIntersectWith(Wrap), Wrap.maximalIntersectWith(One));
+
+  EXPECT_EQ(Wrap.unionWith(One),
+            ConstantSignedRange(APInt(16, 0xaaa), APInt(16, 0xb)));
+  EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One));
+  EXPECT_TRUE(Empty.unionWith(Empty).isEmptySet());
+  EXPECT_TRUE(Full.unionWith(Full).isFullSet());
+  EXPECT_TRUE(Some.unionWith(Wrap).isFullSet());
+
+  EXPECT_TRUE(Full.subtract(APInt(16, 4)).isFullSet());
+  EXPECT_TRUE(Empty.subtract(APInt(16, 4)).isEmptySet());
+  EXPECT_EQ(Some.subtract(APInt(16, 4)),
+            ConstantSignedRange(APInt(16, 0x6), APInt(16, 0xaa6)));
+  EXPECT_EQ(Wrap.subtract(APInt(16, 4)),
+            ConstantSignedRange(APInt(16, 0xaa6), APInt(16, 0x6)));
+  EXPECT_EQ(One.subtract(APInt(16, 4)),
+            ConstantSignedRange(APInt(16, 0x6)));
+
+  EXPECT_TRUE(Full.smax(Full).isFullSet());
+  EXPECT_TRUE(Full.smax(Empty).isEmptySet());
+  EXPECT_TRUE(Full.smax(Some).isFullSet());
+  EXPECT_TRUE(Full.smax(Wrap).isFullSet());
+  EXPECT_TRUE(Full.smax(One).isFullSet());
+  EXPECT_EQ(Empty.smax(Empty), Empty);
+  EXPECT_EQ(Empty.smax(Some), Empty);
+  EXPECT_EQ(Empty.smax(Wrap), Empty);
+  EXPECT_EQ(Empty.smax(One), Empty);
+  EXPECT_EQ(Some.smax(Some), Some);
+  EXPECT_EQ(Some.smax(Wrap), ConstantSignedRange(APInt(16, 0xa),
+                                                 APInt(16, INT16_MIN)));
+  EXPECT_EQ(Some.smax(One), Some);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.smax(Wrap), Full);
+  EXPECT_EQ(Wrap.smax(One), ConstantSignedRange(APInt(16, 0xa),
+                                                APInt(16, INT16_MIN)));
+  EXPECT_EQ(One.smax(One), One);
+
+  EXPECT_EQ(Full.add(Full), Full);
+  EXPECT_EQ(Full.add(Empty), Empty);
+  EXPECT_EQ(Full.add(One), Full);
+  EXPECT_EQ(Full.add(Some), Full);
+  EXPECT_EQ(Full.add(Wrap), Full);
+  EXPECT_EQ(Empty.add(Empty), Empty);
+  EXPECT_EQ(Empty.add(One), Empty);
+  EXPECT_EQ(Empty.add(Some), Empty);
+  EXPECT_EQ(Empty.add(Wrap), Empty);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.add(One), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.add(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.add(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.add(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.add(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.add(Wrap), Full);
+
+  EXPECT_EQ(Full.multiply(Full), Full);
+  EXPECT_EQ(Full.multiply(Empty), Empty);
+  EXPECT_EQ(Full.multiply(One), Full);
+  EXPECT_EQ(Full.multiply(Some), Full);
+  EXPECT_EQ(Full.multiply(Wrap), Full);
+  EXPECT_EQ(Empty.multiply(Empty), Empty);
+  EXPECT_EQ(Empty.multiply(One), Empty);
+  EXPECT_EQ(Empty.multiply(Some), Empty);
+  EXPECT_EQ(Empty.multiply(Wrap), Empty);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(One), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.multiply(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.multiply(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.multiply(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.multiply(Wrap), Full);
+
+  EXPECT_EQ(Full.umax(Full), Full);
+  EXPECT_EQ(Full.umax(Empty), Empty);
+  EXPECT_EQ(Full.umax(One), Full);
+  EXPECT_EQ(Full.umax(Some), Full);
+  EXPECT_EQ(Full.umax(Wrap), Full);
+  EXPECT_EQ(Empty.umax(Empty), Empty);
+  EXPECT_EQ(Empty.umax(One), Empty);
+  EXPECT_EQ(Empty.umax(Some), Empty);
+  EXPECT_EQ(Empty.umax(Wrap), Empty);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.umax(One), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.umax(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(One.umax(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.umax(Some), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Some.umax(Wrap), Full);
+  // TODO: ConstantSignedRange is currently over-conservative here.
+  EXPECT_EQ(Wrap.umax(Wrap), Full);
+}
+
+}  // anonymous namespace





More information about the llvm-commits mailing list