Oops, should be part of 41664; won't work very well without this piece.
[oota-llvm.git] / lib / Support / ConstantRange.cpp
index 71796493301bb53e048c45eafe17796e491f4481..fdfe28aaa95c88289d6cb830422f66f46f271e8a 100644 (file)
@@ -44,22 +44,20 @@ ConstantRange::ConstantRange(const APInt &L, const APInt &U) :
   Lower(L), Upper(U) {
   assert(L.getBitWidth() == U.getBitWidth() && 
          "ConstantRange with unequal bit widths");
-  uint32_t BitWidth = L.getBitWidth();
-  assert((L != U || (L == APInt::getMaxValue(BitWidth) ||
-                     L == APInt::getMinValue(BitWidth))) &&
+  assert((L != U || (L.isMaxValue() || L.isMinValue())) &&
          "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 ConstantRange::isFullSet() const {
-  return Lower == Upper && Lower == APInt::getMaxValue(getBitWidth());
+  return Lower == Upper && Lower.isMaxValue();
 }
 
 /// isEmptySet - Return true if this set contains no members.
 ///
 bool ConstantRange::isEmptySet() const {
-  return Lower == Upper && Lower == APInt::getMinValue(getBitWidth());
+  return Lower == Upper && Lower.isMinValue();
 }
 
 /// isWrappedSet - Return true if this set wraps around the top of the range,
@@ -110,7 +108,7 @@ APInt ConstantRange::getUnsignedMin() const {
 APInt ConstantRange::getSignedMax() const {
   APInt SignedMax(APInt::getSignedMaxValue(getBitWidth()));
   if (!isWrappedSet()) {
-    if (getLower().slt(getUpper() - 1))
+    if (getLower().sle(getUpper() - 1))
       return getUpper() - 1;
     else
       return SignedMax;
@@ -132,7 +130,7 @@ APInt ConstantRange::getSignedMax() const {
 APInt ConstantRange::getSignedMin() const {
   APInt SignedMin(APInt::getSignedMinValue(getBitWidth()));
   if (!isWrappedSet()) {
-    if (getLower().slt(getUpper() - 1))
+    if (getLower().sle(getUpper() - 1))
       return getLower();
     else
       return SignedMin;
@@ -248,6 +246,89 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
   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).
+ConstantRange ConstantRange::maximalIntersectWith(const ConstantRange &CR) const {
+  assert(getBitWidth() == CR.getBitWidth() && 
+         "ConstantRange 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.ult(CR.Lower)) {
+      if (Upper.ule(CR.Lower))
+        return ConstantRange(getBitWidth(), false);
+
+      if (Upper.ult(CR.Upper))
+        return ConstantRange(CR.Lower, Upper);
+
+      return CR;
+    } else {
+      if (Upper.ult(CR.Upper))
+        return *this;
+
+      if (Lower.ult(CR.Upper))
+        return ConstantRange(Lower, CR.Upper);
+
+      return ConstantRange(getBitWidth(), false);
+    }
+  }
+
+  if (isWrappedSet() && !CR.isWrappedSet()) {
+    if (CR.Lower.ult(Upper)) {
+      if (CR.Upper.ult(Upper))
+        return CR;
+
+      if (CR.Upper.ult(Lower))
+        return ConstantRange(CR.Lower, Upper);
+
+      if (getSetSize().ult(CR.getSetSize()))
+        return *this;
+      else
+        return CR;
+    } else if (CR.Lower.ult(Lower)) {
+      if (CR.Upper.ule(Lower))
+        return ConstantRange(getBitWidth(), false);
+
+      return ConstantRange(Lower, CR.Upper);
+    }
+    return CR;
+  }
+
+  if (CR.Upper.ult(Upper)) {
+    if (CR.Lower.ult(Upper)) {
+      if (getSetSize().ult(CR.getSetSize()))
+        return *this;
+      else
+        return CR;
+    }
+
+    if (CR.Lower.ult(Lower))
+      return ConstantRange(Lower, CR.Upper);
+
+    return CR;
+  } else if (CR.Upper.ult(Lower)) {
+    if (CR.Lower.ult(Lower))
+      return *this;
+
+    return ConstantRange(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