//
//===----------------------------------------------------------------------===//
-#include "llvm/Constants.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Instructions.h"
using namespace llvm;
/// Initialize a full (the default) or empty set for the specified type.
/// Initialize a range to hold the single specified value.
///
-ConstantRange::ConstantRange(const APInt &V) : Lower(V), Upper(V + 1) {}
+ConstantRange::ConstantRange(APIntMoveTy V)
+ : Lower(std::move(V)), Upper(Lower + 1) {}
-ConstantRange::ConstantRange(const APInt &L, const APInt &U) :
- Lower(L), Upper(U) {
- assert(L.getBitWidth() == U.getBitWidth() &&
+ConstantRange::ConstantRange(APIntMoveTy L, APIntMoveTy U)
+ : Lower(std::move(L)), Upper(std::move(U)) {
+ assert(Lower.getBitWidth() == Upper.getBitWidth() &&
"ConstantRange with unequal bit widths");
- assert((L != U || (L.isMaxValue() || L.isMinValue())) &&
+ assert((Lower != Upper || (Lower.isMaxValue() || Lower.isMinValue())) &&
"Lower == Upper, but they aren't min or max value!");
}
ConstantRange ConstantRange::makeICmpRegion(unsigned Pred,
const ConstantRange &CR) {
+ if (CR.isEmptySet())
+ return CR;
+
uint32_t W = CR.getBitWidth();
switch (Pred) {
- default: assert(!"Invalid ICmp predicate to makeICmpRegion()");
- case ICmpInst::ICMP_EQ:
+ default: llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()");
+ case CmpInst::ICMP_EQ:
return CR;
- case ICmpInst::ICMP_NE:
+ case CmpInst::ICMP_NE:
if (CR.isSingleElement())
return ConstantRange(CR.getUpper(), CR.getLower());
return ConstantRange(W);
- case ICmpInst::ICMP_ULT:
- return ConstantRange(APInt::getMinValue(W), CR.getUnsignedMax());
- case ICmpInst::ICMP_SLT:
- return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax());
- case ICmpInst::ICMP_ULE: {
+ case CmpInst::ICMP_ULT: {
+ APInt UMax(CR.getUnsignedMax());
+ if (UMax.isMinValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(APInt::getMinValue(W), UMax);
+ }
+ case CmpInst::ICMP_SLT: {
+ APInt SMax(CR.getSignedMax());
+ if (SMax.isMinSignedValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(APInt::getSignedMinValue(W), SMax);
+ }
+ case CmpInst::ICMP_ULE: {
APInt UMax(CR.getUnsignedMax());
if (UMax.isMaxValue())
return ConstantRange(W);
return ConstantRange(APInt::getMinValue(W), UMax + 1);
}
- case ICmpInst::ICMP_SLE: {
+ case CmpInst::ICMP_SLE: {
APInt SMax(CR.getSignedMax());
- if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue())
+ if (SMax.isMaxSignedValue())
return ConstantRange(W);
return ConstantRange(APInt::getSignedMinValue(W), SMax + 1);
}
- case ICmpInst::ICMP_UGT:
- return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W));
- case ICmpInst::ICMP_SGT:
- return ConstantRange(CR.getSignedMin() + 1,
- APInt::getSignedMinValue(W));
- case ICmpInst::ICMP_UGE: {
+ case CmpInst::ICMP_UGT: {
+ APInt UMin(CR.getUnsignedMin());
+ if (UMin.isMaxValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(UMin + 1, APInt::getNullValue(W));
+ }
+ case CmpInst::ICMP_SGT: {
+ APInt SMin(CR.getSignedMin());
+ if (SMin.isMaxSignedValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(SMin + 1, APInt::getSignedMinValue(W));
+ }
+ case CmpInst::ICMP_UGE: {
APInt UMin(CR.getUnsignedMin());
if (UMin.isMinValue())
return ConstantRange(W);
return ConstantRange(UMin, APInt::getNullValue(W));
}
- case ICmpInst::ICMP_SGE: {
+ case CmpInst::ICMP_SGE: {
APInt SMin(CR.getSignedMin());
if (SMin.isMinSignedValue())
return ConstantRange(W);
/// getSetSize - Return the number of elements in this set.
///
APInt ConstantRange::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...
+ if (isFullSet()) {
+ APInt Size(getBitWidth()+1, 0);
+ Size.setBit(getBitWidth());
+ return Size;
}
- // Simply subtract the bounds...
- return Upper - Lower;
+ // This is also correct for wrapped sets.
+ return (Upper - Lower).zext(getBitWidth()+1);
}
/// getUnsignedMax - Return the largest unsigned value contained in the
APInt ConstantRange::getUnsignedMax() const {
if (isFullSet() || isWrappedSet())
return APInt::getMaxValue(getBitWidth());
- else
- return getUpper() - 1;
+ return getUpper() - 1;
}
/// getUnsignedMin - Return the smallest unsigned value contained in the
APInt ConstantRange::getUnsignedMin() const {
if (isFullSet() || (isWrappedSet() && getUpper() != 0))
return APInt::getMinValue(getBitWidth());
- else
- return getLower();
+ return getLower();
}
/// getSignedMax - Return the largest signed value contained in the
if (!isWrappedSet()) {
if (getLower().sle(getUpper() - 1))
return getUpper() - 1;
- else
- return SignedMax;
- } else {
- if (getLower().isNegative() == getUpper().isNegative())
- return SignedMax;
- else
- return getUpper() - 1;
+ return SignedMax;
}
+ if (getLower().isNegative() == getUpper().isNegative())
+ return SignedMax;
+ return getUpper() - 1;
}
/// getSignedMin - Return the smallest signed value contained in the
if (!isWrappedSet()) {
if (getLower().sle(getUpper() - 1))
return getLower();
- else
+ return SignedMin;
+ }
+ if ((getUpper() - 1).slt(getLower())) {
+ if (getUpper() != SignedMin)
return SignedMin;
- } else {
- if ((getUpper() - 1).slt(getLower())) {
- if (getUpper() != SignedMin)
- return SignedMin;
- else
- return getLower();
- } else {
- return getLower();
- }
}
+ return getLower();
}
/// contains - Return true if the specified value is in the set.
if (!isWrappedSet())
return Lower.ule(V) && V.ult(Upper);
- else
- return Lower.ule(V) || V.ult(Upper);
+ return Lower.ule(V) || V.ult(Upper);
}
/// contains - Return true if the argument is a subset of this range.
return ConstantRange(Lower - Val, Upper - Val);
}
+/// \brief Subtract the specified range from this range (aka relative complement
+/// of the sets).
+ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
+ return intersectWith(CR.inverse());
+}
+
/// intersectWith - 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
return ConstantRange(CR.Lower, Upper);
return CR;
- } else {
- if (Upper.ult(CR.Upper))
- return *this;
+ }
+ if (Upper.ult(CR.Upper))
+ return *this;
- if (Lower.ult(CR.Upper))
- return ConstantRange(Lower, CR.Upper);
+ if (Lower.ult(CR.Upper))
+ return ConstantRange(Lower, CR.Upper);
- return ConstantRange(getBitWidth(), false);
- }
+ return ConstantRange(getBitWidth(), false);
}
if (isWrappedSet() && !CR.isWrappedSet()) {
if (CR.Upper.ult(Upper))
return CR;
- if (CR.Upper.ult(Lower))
+ if (CR.Upper.ule(Lower))
return ConstantRange(CR.Lower, Upper);
if (getSetSize().ult(CR.getSetSize()))
return *this;
- else
- return CR;
- } else if (CR.Lower.ult(Lower)) {
+ return CR;
+ }
+ if (CR.Lower.ult(Lower)) {
if (CR.Upper.ule(Lower))
return ConstantRange(getBitWidth(), false);
if (CR.Lower.ult(Upper)) {
if (getSetSize().ult(CR.getSetSize()))
return *this;
- else
- return CR;
+ return CR;
}
if (CR.Lower.ult(Lower))
return ConstantRange(Lower, CR.Upper);
return CR;
- } else if (CR.Upper.ult(Lower)) {
+ }
+ if (CR.Upper.ule(Lower)) {
if (CR.Lower.ult(Lower))
return *this;
}
if (getSetSize().ult(CR.getSetSize()))
return *this;
- else
- return CR;
+ return CR;
}
APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
if (d1.ult(d2))
return ConstantRange(Lower, CR.Upper);
- else
- return ConstantRange(CR.Lower, Upper);
+ return ConstantRange(CR.Lower, Upper);
}
APInt L = Lower, U = Upper;
APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
if (d1.ult(d2))
return ConstantRange(Lower, CR.Upper);
- else
- return ConstantRange(CR.Lower, Upper);
+ return ConstantRange(CR.Lower, Upper);
}
// ----U L----- : this
// ------U L---- : this
// L-----U : CR
- if (CR.Lower.ult(Upper) && CR.Upper.ult(Lower))
- return ConstantRange(Lower, CR.Upper);
+ assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) &&
+ "ConstantRange::unionWith missed a case with one range wrapped");
+ return ConstantRange(Lower, CR.Upper);
}
- assert(isWrappedSet() && CR.isWrappedSet() &&
- "ConstantRange::unionWith missed wrapped union unwrapped case");
-
// ------U L---- and ------U L---- : this
// -U L----------- and ------------U L : CR
if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension");
- if (isFullSet() || isWrappedSet())
+ if (isFullSet() || isWrappedSet()) {
// Change into [0, 1 << src bit width)
- return ConstantRange(APInt(DstTySize,0), APInt(DstTySize,1).shl(SrcTySize));
+ APInt LowerExt(DstTySize, 0);
+ if (!Upper) // special case: [X, 0) -- not really wrapping around
+ LowerExt = Lower.zext(DstTySize);
+ return ConstantRange(LowerExt, APInt::getOneBitSet(DstTySize, SrcTySize));
+ }
- APInt L = Lower; L.zext(DstTySize);
- APInt U = Upper; U.zext(DstTySize);
- return ConstantRange(L, U);
+ return ConstantRange(Lower.zext(DstTySize), Upper.zext(DstTySize));
}
/// signExtend - Return a new range in the specified integer type, which must
unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension");
+
+ // special case: [X, INT_MIN) -- not really wrapping around
+ if (Upper.isMinSignedValue())
+ return ConstantRange(Lower.sext(DstTySize), Upper.zext(DstTySize));
+
if (isFullSet() || isSignWrappedSet()) {
return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1),
APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1);
}
- APInt L = Lower; L.sext(DstTySize);
- APInt U = Upper; U.sext(DstTySize);
- return ConstantRange(L, U);
+ return ConstantRange(Lower.sext(DstTySize), Upper.sext(DstTySize));
}
/// truncate - Return a new range in the specified integer type, which must be
/// correspond to the possible range of values as if the source range had been
/// truncated to the specified type.
ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
- unsigned SrcTySize = getBitWidth();
- assert(SrcTySize > DstTySize && "Not a value truncation");
- APInt Size(APInt::getLowBitsSet(SrcTySize, DstTySize));
- if (isFullSet() || getSetSize().ugt(Size))
+ assert(getBitWidth() > DstTySize && "Not a value truncation");
+ if (isEmptySet())
+ return ConstantRange(DstTySize, /*isFullSet=*/false);
+ if (isFullSet())
return ConstantRange(DstTySize, /*isFullSet=*/true);
- APInt L = Lower; L.trunc(DstTySize);
- APInt U = Upper; U.trunc(DstTySize);
- return ConstantRange(L, U);
+ APInt MaxValue = APInt::getMaxValue(DstTySize).zext(getBitWidth());
+ APInt MaxBitValue(getBitWidth(), 0);
+ MaxBitValue.setBit(DstTySize);
+
+ APInt LowerDiv(Lower), UpperDiv(Upper);
+ ConstantRange Union(DstTySize, /*isFullSet=*/false);
+
+ // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue]
+ // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and
+ // then we do the union with [MaxValue, Upper)
+ if (isWrappedSet()) {
+ // if Upper is greater than Max Value, it covers the whole truncated range.
+ if (Upper.uge(MaxValue))
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
+
+ Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
+ UpperDiv = APInt::getMaxValue(getBitWidth());
+
+ // Union covers the MaxValue case, so return if the remaining range is just
+ // MaxValue.
+ if (LowerDiv == UpperDiv)
+ return Union;
+ }
+
+ // Chop off the most significant bits that are past the destination bitwidth.
+ if (LowerDiv.uge(MaxValue)) {
+ APInt Div(getBitWidth(), 0);
+ APInt::udivrem(LowerDiv, MaxBitValue, Div, LowerDiv);
+ UpperDiv = UpperDiv - MaxBitValue * Div;
+ }
+
+ if (UpperDiv.ule(MaxValue))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperDiv.trunc(DstTySize)).unionWith(Union);
+
+ // The truncated value wrapps around. Check if we can do better than fullset.
+ APInt UpperModulo = UpperDiv - MaxBitValue;
+ if (UpperModulo.ult(LowerDiv))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperModulo.trunc(DstTySize)).unionWith(Union);
+
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
}
/// zextOrTrunc - make this range have the bit width given by \p DstTySize. The
unsigned SrcTySize = getBitWidth();
if (SrcTySize > DstTySize)
return truncate(DstTySize);
- else if (SrcTySize < DstTySize)
+ if (SrcTySize < DstTySize)
return zeroExtend(DstTySize);
- else
- return *this;
+ return *this;
}
/// sextOrTrunc - make this range have the bit width given by \p DstTySize. The
unsigned SrcTySize = getBitWidth();
if (SrcTySize > DstTySize)
return truncate(DstTySize);
- else if (SrcTySize < DstTySize)
+ if (SrcTySize < DstTySize)
return signExtend(DstTySize);
- else
- return *this;
+ return *this;
}
ConstantRange
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize();
- APInt NewLower = getLower() - Other.getLower();
- APInt NewUpper = getUpper() - Other.getUpper() + 1;
+ APInt NewLower = getLower() - Other.getUpper() + 1;
+ APInt NewUpper = getUpper() - Other.getLower();
if (NewLower == NewUpper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
- if (isFullSet() || Other.isFullSet())
- return ConstantRange(getBitWidth(), /*isFullSet=*/true);
APInt this_min = getUnsignedMin().zext(getBitWidth() * 2);
APInt this_max = getUnsignedMax().zext(getBitWidth() * 2);
return ConstantRange(Lower, Upper);
}
+ConstantRange
+ConstantRange::binaryAnd(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ // TODO: replace this with something less conservative
+
+ APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax());
+ if (umin.isAllOnesValue())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(APInt::getNullValue(getBitWidth()), umin + 1);
+}
+
+ConstantRange
+ConstantRange::binaryOr(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ // TODO: replace this with something less conservative
+
+ APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
+ if (umax.isMinValue())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(umax, APInt::getNullValue(getBitWidth()));
+}
+
ConstantRange
ConstantRange::shl(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
}
ConstantRange ConstantRange::inverse() const {
- if (isFullSet()) {
+ if (isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
- } else if (isEmptySet()) {
+ if (isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
- }
return ConstantRange(Upper, Lower);
}