[ConstantRange] Add getFull() + getEmpty() named constructors; NFC

This adds ConstantRange::getFull(BitWidth) and
ConstantRange::getEmpty(BitWidth) named constructors as more readable
alternatives to the current ConstantRange(BitWidth, /* full */ false)
and similar. Additionally private getFull() and getEmpty() member
functions are added which return a full/empty range with the same bit
width -- these are commonly needed inside ConstantRange.cpp.

The IsFullSet argument in the ConstantRange(BitWidth, IsFullSet)
constructor is now mandatory for the few usages that still make use of it.

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

llvm-svn: 356852
This commit is contained in:
Nikita Popov 2019-03-24 09:34:40 +00:00
parent 54ce1b18c5
commit 977934f00f
8 changed files with 105 additions and 85 deletions

View File

@ -47,9 +47,19 @@ struct KnownBits;
class LLVM_NODISCARD ConstantRange {
APInt Lower, Upper;
/// Create empty constant range with same bitwidth.
ConstantRange getEmpty() const {
return ConstantRange(getBitWidth(), false);
}
/// Create full constant range with same bitwidth.
ConstantRange getFull() const {
return ConstantRange(getBitWidth(), true);
}
public:
/// Initialize a full (the default) or empty set for the specified bit width.
explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true);
explicit ConstantRange(uint32_t BitWidth, bool isFullSet);
/// Initialize a range to hold the single specified value.
ConstantRange(APInt Value);
@ -59,6 +69,16 @@ public:
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APInt Lower, APInt Upper);
/// Create empty constant range with the given bit width.
static ConstantRange getEmpty(uint32_t BitWidth) {
return ConstantRange(BitWidth, false);
}
/// Create full constant range with the given bit width.
static ConstantRange getFull(uint32_t BitWidth) {
return ConstantRange(BitWidth, true);
}
/// Initialize a range based on a known bits constraint. The IsSigned flag
/// indicates whether the constant range should not wrap in the signed or
/// unsigned domain.

View File

@ -963,7 +963,7 @@ Optional<ConstantRange> LazyValueInfoImpl::getRangeForOperand(unsigned Op,
const unsigned OperandBitWidth =
DL.getTypeSizeInBits(I->getOperand(Op)->getType());
ConstantRange Range = ConstantRange(OperandBitWidth);
ConstantRange Range = ConstantRange::getFull(OperandBitWidth);
if (hasBlockValue(I->getOperand(Op), BB)) {
ValueLatticeElement Val = getBlockValue(I->getOperand(Op), BB);
intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I);
@ -1576,14 +1576,14 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB,
ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
if (Result.isUndefined())
return ConstantRange(Width, /*isFullSet=*/false);
return ConstantRange::getEmpty(Width);
if (Result.isConstantRange())
return Result.getConstantRange();
// We represent ConstantInt constants as constant ranges but other kinds
// of integer constants, i.e. ConstantExpr will be tagged as constants
assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) &&
"ConstantInt value must be represented as constantrange");
return ConstantRange(Width, /*isFullSet=*/true);
return ConstantRange::getFull(Width);
}
/// Determine whether the specified value is known to be a
@ -1615,14 +1615,14 @@ ConstantRange LazyValueInfo::getConstantRangeOnEdge(Value *V,
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
if (Result.isUndefined())
return ConstantRange(Width, /*isFullSet=*/false);
return ConstantRange::getEmpty(Width);
if (Result.isConstantRange())
return Result.getConstantRange();
// We represent ConstantInt constants as constant ranges but other kinds
// of integer constants, i.e. ConstantExpr will be tagged as constants
assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) &&
"ConstantInt value must be represented as constantrange");
return ConstantRange(Width, /*isFullSet=*/true);
return ConstantRange::getFull(Width);
}
static LazyValueInfo::Tristate

View File

@ -5774,7 +5774,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
// FullRange), then we don't know anything about the final range either.
// Return FullRange.
if (StartRange.isFullSet())
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
// If Step is signed and negative, then we use its absolute value, but we also
// note that we're moving in the opposite direction.
@ -5790,7 +5790,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
// Check if Offset is more than full span of BitWidth. If it is, the
// expression is guaranteed to overflow.
if (APInt::getMaxValue(StartRange.getBitWidth()).udiv(Step).ult(MaxBECount))
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
// Offset is by how much the expression can change. Checks above guarantee no
// overflow here.
@ -5809,7 +5809,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
// range (due to wrap around). This means that the expression can take any
// value in this bitwidth, and we have to return full range.
if (StartRange.contains(MovedBoundary))
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
APInt NewLower =
Descending ? std::move(MovedBoundary) : std::move(StartLower);
@ -5819,7 +5819,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
// If we end up with full range, return a proper full range.
if (NewLower == NewUpper)
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
// No overflow detected, return [StartLower, StartUpper + Offset + 1) range.
return ConstantRange(std::move(NewLower), std::move(NewUpper));
@ -5939,17 +5939,17 @@ ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
SelectPattern StartPattern(*this, BitWidth, Start);
if (!StartPattern.isRecognized())
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
SelectPattern StepPattern(*this, BitWidth, Step);
if (!StepPattern.isRecognized())
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
if (StartPattern.Condition != StepPattern.Condition) {
// We don't handle this case today; but we could, by considering four
// possibilities below instead of two. I'm not sure if there are cases where
// that will help over what getRange already does, though.
return ConstantRange(BitWidth, /* isFullSet = */ true);
return ConstantRange::getFull(BitWidth);
}
// NB! Calling ScalarEvolution::getConstant is fine, but we should not try to

View File

@ -5711,7 +5711,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) {
setLimitsForSelectPattern(*SI, Lower, Upper);
ConstantRange CR = Lower != Upper ? ConstantRange(Lower, Upper)
: ConstantRange(BitWidth, true);
: ConstantRange::getFull(BitWidth);
if (auto *I = dyn_cast<Instruction>(V))
if (auto *Range = IIQ.getMetadata(I, LLVMContext::MD_range))

View File

@ -59,7 +59,7 @@ ConstantRange ConstantRange::fromKnownBits(const KnownBits &Known,
assert(!Known.hasConflict() && "Expected valid KnownBits");
if (Known.isUnknown())
return ConstantRange(Known.getBitWidth(), /* full */ true);
return getFull(Known.getBitWidth());
// For unsigned ranges, or signed ranges with known sign bit, create a simple
// range between the smallest and largest possible value.
@ -88,53 +88,53 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred,
case CmpInst::ICMP_NE:
if (CR.isSingleElement())
return ConstantRange(CR.getUpper(), CR.getLower());
return ConstantRange(W);
return getFull(W);
case CmpInst::ICMP_ULT: {
APInt UMax(CR.getUnsignedMax());
if (UMax.isMinValue())
return ConstantRange(W, /* empty */ false);
return getEmpty(W);
return ConstantRange(APInt::getMinValue(W), std::move(UMax));
}
case CmpInst::ICMP_SLT: {
APInt SMax(CR.getSignedMax());
if (SMax.isMinSignedValue())
return ConstantRange(W, /* empty */ false);
return getEmpty(W);
return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax));
}
case CmpInst::ICMP_ULE: {
APInt UMax(CR.getUnsignedMax());
if (UMax.isMaxValue())
return ConstantRange(W);
return getFull(W);
return ConstantRange(APInt::getMinValue(W), std::move(UMax) + 1);
}
case CmpInst::ICMP_SLE: {
APInt SMax(CR.getSignedMax());
if (SMax.isMaxSignedValue())
return ConstantRange(W);
return getFull(W);
return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax) + 1);
}
case CmpInst::ICMP_UGT: {
APInt UMin(CR.getUnsignedMin());
if (UMin.isMaxValue())
return ConstantRange(W, /* empty */ false);
return getEmpty(W);
return ConstantRange(std::move(UMin) + 1, APInt::getNullValue(W));
}
case CmpInst::ICMP_SGT: {
APInt SMin(CR.getSignedMin());
if (SMin.isMaxSignedValue())
return ConstantRange(W, /* empty */ false);
return getEmpty(W);
return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W));
}
case CmpInst::ICMP_UGE: {
APInt UMin(CR.getUnsignedMin());
if (UMin.isMinValue())
return ConstantRange(W);
return getFull(W);
return ConstantRange(std::move(UMin), APInt::getNullValue(W));
}
case CmpInst::ICMP_SGE: {
APInt SMin(CR.getSignedMin());
if (SMin.isMinSignedValue())
return ConstantRange(W);
return getFull(W);
return ConstantRange(std::move(SMin), APInt::getSignedMinValue(W));
}
}
@ -219,18 +219,18 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
"NoWrapKind invalid!");
unsigned BitWidth = Other.getBitWidth();
ConstantRange Result(BitWidth);
ConstantRange Result(BitWidth, /* full */ true);
switch (BinOp) {
default:
// Conservative answer: empty set
return ConstantRange(BitWidth, false);
return getEmpty(BitWidth);
case Instruction::Add:
if (auto *C = Other.getSingleElement())
if (C->isNullValue())
// Full set: nothing signed / unsigned wraps when added to 0.
return ConstantRange(BitWidth);
return getFull(BitWidth);
if (NoWrapKind & OBO::NoUnsignedWrap)
Result =
SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
@ -255,7 +255,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
if (auto *C = Other.getSingleElement())
if (C->isNullValue())
// Full set: nothing signed / unsigned wraps when subtracting 0.
return ConstantRange(BitWidth);
return getFull(BitWidth);
if (NoWrapKind & OBO::NoUnsignedWrap)
Result =
SubsetIntersect(Result, ConstantRange(Other.getUnsignedMax(),
@ -289,7 +289,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
// Handle special case for 0, -1 and 1. See the last for reason why we
// specialize -1 and 1.
if (V == 0 || V.isOneValue())
return ConstantRange(BitWidth, true);
return getFull(BitWidth);
APInt MinValue, MaxValue;
if (Unsigned) {
@ -459,7 +459,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
if (!isWrappedSet() && !CR.isWrappedSet()) {
if (Lower.ult(CR.Lower)) {
if (Upper.ule(CR.Lower))
return ConstantRange(getBitWidth(), false);
return getEmpty();
if (Upper.ult(CR.Upper))
return ConstantRange(CR.Lower, Upper);
@ -472,7 +472,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
if (Lower.ult(CR.Upper))
return ConstantRange(Lower, CR.Upper);
return ConstantRange(getBitWidth(), false);
return getEmpty();
}
if (isWrappedSet() && !CR.isWrappedSet()) {
@ -489,7 +489,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
}
if (CR.Lower.ult(Lower)) {
if (CR.Upper.ule(Lower))
return ConstantRange(getBitWidth(), false);
return getEmpty();
return ConstantRange(Lower, CR.Upper);
}
@ -541,7 +541,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper;
if (L.isNullValue() && U.isNullValue())
return ConstantRange(getBitWidth());
return getFull();
return ConstantRange(std::move(L), std::move(U));
}
@ -555,7 +555,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
// ------U L----- : this
// L---------U : CR
if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper))
return ConstantRange(getBitWidth());
return getFull();
// ----U L---- : this
// L---U : CR
@ -582,7 +582,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
// ------U L---- and ------U L---- : this
// -U L----------- and ------------U L : CR
if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
return ConstantRange(getBitWidth());
return getFull();
APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper;
@ -608,7 +608,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
if (getBitWidth() == ResultBitWidth)
return *this;
else
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
case Instruction::UIToFP: {
// TODO: use input range if available
auto BW = getBitWidth();
@ -628,13 +628,13 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
case Instruction::IntToPtr:
case Instruction::PtrToInt:
case Instruction::AddrSpaceCast:
// Conservatively return full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
// Conservatively return getFull set.
return getFull();
};
}
ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false);
if (isEmptySet()) return getEmpty(DstTySize);
unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension");
@ -651,7 +651,7 @@ ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
}
ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false);
if (isEmptySet()) return getEmpty(DstTySize);
unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension");
@ -671,9 +671,9 @@ ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
assert(getBitWidth() > DstTySize && "Not a value truncation");
if (isEmptySet())
return ConstantRange(DstTySize, /*isFullSet=*/false);
return getEmpty(DstTySize);
if (isFullSet())
return ConstantRange(DstTySize, /*isFullSet=*/true);
return getFull(DstTySize);
APInt LowerDiv(Lower), UpperDiv(Upper);
ConstantRange Union(DstTySize, /*isFullSet=*/false);
@ -686,7 +686,7 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
// truncated range.
if (Upper.getActiveBits() > DstTySize ||
Upper.countTrailingOnes() == DstTySize)
return ConstantRange(DstTySize, /*isFullSet=*/true);
return getFull(DstTySize);
Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
UpperDiv.setAllBits();
@ -719,7 +719,7 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
UpperDiv.trunc(DstTySize)).unionWith(Union);
}
return ConstantRange(DstTySize, /*isFullSet=*/true);
return getFull(DstTySize);
}
ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const {
@ -772,28 +772,28 @@ ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
case Instruction::FMul:
return multiply(Other);
default:
// Conservatively return full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
// Conservatively return getFull set.
return getFull();
}
}
ConstantRange
ConstantRange::add(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
if (isFullSet() || Other.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
APInt NewLower = getLower() + Other.getLower();
APInt NewUpper = getUpper() + Other.getUpper() - 1;
if (NewLower == NewUpper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
if (X.isSizeStrictlySmallerThan(*this) ||
X.isSizeStrictlySmallerThan(Other))
// We've wrapped, therefore, full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return X;
}
@ -813,20 +813,20 @@ ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const {
ConstantRange
ConstantRange::sub(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
if (isFullSet() || Other.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
APInt NewLower = getLower() - Other.getUpper() + 1;
APInt NewUpper = getUpper() - Other.getLower();
if (NewLower == NewUpper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
if (X.isSizeStrictlySmallerThan(*this) ||
X.isSizeStrictlySmallerThan(Other))
// We've wrapped, therefore, full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return X;
}
@ -838,7 +838,7 @@ ConstantRange::multiply(const ConstantRange &Other) const {
// range according to the greatest power-of-two factor of the single element.
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
// Multiplication is signedness-independent. However different ranges can be
// obtained depending on how the input ranges are treated. These different
@ -889,11 +889,11 @@ ConstantRange::smax(const ConstantRange &Other) const {
// X smax Y is: range(smax(X_smin, Y_smin),
// smax(X_smax, Y_smax))
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(NewL), std::move(NewU));
}
@ -902,11 +902,11 @@ 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);
return getEmpty();
APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(NewL), std::move(NewU));
}
@ -915,11 +915,11 @@ ConstantRange::smin(const ConstantRange &Other) const {
// X smin Y is: range(smin(X_smin, Y_smin),
// smin(X_smax, Y_smax))
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1;
if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(NewL), std::move(NewU));
}
@ -928,20 +928,20 @@ ConstantRange::umin(const ConstantRange &Other) const {
// X umin Y is: range(umin(X_umin, Y_umin),
// umin(X_umax, Y_umax))
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1;
if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(NewL), std::move(NewU));
}
ConstantRange
ConstantRange::udiv(const ConstantRange &RHS) const {
if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
if (RHS.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax());
@ -960,7 +960,7 @@ ConstantRange::udiv(const ConstantRange &RHS) const {
// If the LHS is Full and the RHS is a wrapped interval containing 1 then
// this could occur.
if (Lower == Upper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(Lower), std::move(Upper));
}
@ -968,40 +968,40 @@ ConstantRange::udiv(const ConstantRange &RHS) const {
ConstantRange
ConstantRange::binaryAnd(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
// TODO: replace this with something less conservative
APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax());
if (umin.isAllOnesValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(APInt::getNullValue(getBitWidth()), std::move(umin) + 1);
}
ConstantRange
ConstantRange::binaryOr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
// TODO: replace this with something less conservative
APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
if (umax.isNullValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth()));
}
ConstantRange
ConstantRange::shl(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
APInt max = getUnsignedMax();
APInt Other_umax = Other.getUnsignedMax();
// there's overflow!
if (Other_umax.uge(max.countLeadingZeros()))
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
// FIXME: implement the other tricky cases
@ -1015,12 +1015,12 @@ ConstantRange::shl(const ConstantRange &Other) const {
ConstantRange
ConstantRange::lshr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()) + 1;
APInt min = getUnsignedMin().lshr(Other.getUnsignedMax());
if (min == max)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(min), std::move(max));
}
@ -1028,7 +1028,7 @@ ConstantRange::lshr(const ConstantRange &Other) const {
ConstantRange
ConstantRange::ashr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
// May straddle zero, so handle both positive and negative cases.
// 'PosMax' is the upper bound of the result of the ashr
@ -1074,16 +1074,16 @@ ConstantRange::ashr(const ConstantRange &Other) const {
max = PosMax;
}
if (min == max)
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(std::move(min), std::move(max));
}
ConstantRange ConstantRange::inverse() const {
if (isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
return getEmpty();
if (isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true);
return getFull();
return ConstantRange(Upper, Lower);
}

View File

@ -3269,7 +3269,7 @@ void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) {
unsigned NumRanges = NumOperands / 2;
Assert(NumRanges >= 1, "It should have at least one range!", Range);
ConstantRange LastRange(1); // Dummy initial value
ConstantRange LastRange(1, true); // Dummy initial value
for (unsigned i = 0; i < NumRanges; ++i) {
ConstantInt *Low =
mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i));

View File

@ -147,10 +147,10 @@ void Float2IntPass::seen(Instruction *I, ConstantRange R) {
// Helper - get a range representing a poison value.
ConstantRange Float2IntPass::badRange() {
return ConstantRange(MaxIntegerBW + 1, true);
return ConstantRange::getFull(MaxIntegerBW + 1);
}
ConstantRange Float2IntPass::unknownRange() {
return ConstantRange(MaxIntegerBW + 1, false);
return ConstantRange::getEmpty(MaxIntegerBW + 1);
}
ConstantRange Float2IntPass::validateRange(ConstantRange R) {
if (R.getBitWidth() > MaxIntegerBW + 1)
@ -194,7 +194,7 @@ void Float2IntPass::walkBackwards(const SmallPtrSetImpl<Instruction*> &Roots) {
// Path terminated cleanly - use the type of the integer input to seed
// the analysis.
unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
auto Input = ConstantRange(BW, true);
auto Input = ConstantRange::getFull(BW);
auto CastOp = (Instruction::CastOps)I->getOpcode();
seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));
continue;

View File

@ -25,7 +25,7 @@ protected:
static ConstantRange Wrap;
};
ConstantRange ConstantRangeTest::Full(16);
ConstantRange ConstantRangeTest::Full(16, true);
ConstantRange ConstantRangeTest::Empty(16, false);
ConstantRange ConstantRangeTest::One(APInt(16, 0xa));
ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa));
@ -320,10 +320,10 @@ TEST_F(ConstantRangeTest, UnionWith) {
ConstantRange(APInt(16, 14), APInt(16, 8)));
EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith(
ConstantRange(APInt(16, 4), APInt(16, 0))),
ConstantRange(16));
ConstantRange::getFull(16));
EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith(
ConstantRange(APInt(16, 2), APInt(16, 1))),
ConstantRange(16));
ConstantRange::getFull(16));
}
TEST_F(ConstantRangeTest, SetDifference) {