[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 { class LLVM_NODISCARD ConstantRange {
APInt Lower, Upper; 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: public:
/// Initialize a full (the default) or empty set for the specified bit width. /// 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. /// Initialize a range to hold the single specified value.
ConstantRange(APInt Value); ConstantRange(APInt Value);
@ -59,6 +69,16 @@ public:
/// assert out if the two APInt's are not the same bit width. /// assert out if the two APInt's are not the same bit width.
ConstantRange(APInt Lower, APInt Upper); 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 /// Initialize a range based on a known bits constraint. The IsSigned flag
/// indicates whether the constant range should not wrap in the signed or /// indicates whether the constant range should not wrap in the signed or
/// unsigned domain. /// unsigned domain.

View File

@ -963,7 +963,7 @@ Optional<ConstantRange> LazyValueInfoImpl::getRangeForOperand(unsigned Op,
const unsigned OperandBitWidth = const unsigned OperandBitWidth =
DL.getTypeSizeInBits(I->getOperand(Op)->getType()); DL.getTypeSizeInBits(I->getOperand(Op)->getType());
ConstantRange Range = ConstantRange(OperandBitWidth); ConstantRange Range = ConstantRange::getFull(OperandBitWidth);
if (hasBlockValue(I->getOperand(Op), BB)) { if (hasBlockValue(I->getOperand(Op), BB)) {
ValueLatticeElement Val = getBlockValue(I->getOperand(Op), BB); ValueLatticeElement Val = getBlockValue(I->getOperand(Op), BB);
intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I); intersectAssumeOrGuardBlockValueConstantRange(I->getOperand(Op), Val, I);
@ -1576,14 +1576,14 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB,
ValueLatticeElement Result = ValueLatticeElement Result =
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI); getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
if (Result.isUndefined()) if (Result.isUndefined())
return ConstantRange(Width, /*isFullSet=*/false); return ConstantRange::getEmpty(Width);
if (Result.isConstantRange()) if (Result.isConstantRange())
return Result.getConstantRange(); return Result.getConstantRange();
// We represent ConstantInt constants as constant ranges but other kinds // We represent ConstantInt constants as constant ranges but other kinds
// of integer constants, i.e. ConstantExpr will be tagged as constants // of integer constants, i.e. ConstantExpr will be tagged as constants
assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) && assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) &&
"ConstantInt value must be represented as constantrange"); "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 /// 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); getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
if (Result.isUndefined()) if (Result.isUndefined())
return ConstantRange(Width, /*isFullSet=*/false); return ConstantRange::getEmpty(Width);
if (Result.isConstantRange()) if (Result.isConstantRange())
return Result.getConstantRange(); return Result.getConstantRange();
// We represent ConstantInt constants as constant ranges but other kinds // We represent ConstantInt constants as constant ranges but other kinds
// of integer constants, i.e. ConstantExpr will be tagged as constants // of integer constants, i.e. ConstantExpr will be tagged as constants
assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) && assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) &&
"ConstantInt value must be represented as constantrange"); "ConstantInt value must be represented as constantrange");
return ConstantRange(Width, /*isFullSet=*/true); return ConstantRange::getFull(Width);
} }
static LazyValueInfo::Tristate 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. // FullRange), then we don't know anything about the final range either.
// Return FullRange. // Return FullRange.
if (StartRange.isFullSet()) 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 // If Step is signed and negative, then we use its absolute value, but we also
// note that we're moving in the opposite direction. // 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 // Check if Offset is more than full span of BitWidth. If it is, the
// expression is guaranteed to overflow. // expression is guaranteed to overflow.
if (APInt::getMaxValue(StartRange.getBitWidth()).udiv(Step).ult(MaxBECount)) 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 // Offset is by how much the expression can change. Checks above guarantee no
// overflow here. // overflow here.
@ -5809,7 +5809,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
// range (due to wrap around). This means that the expression can take any // range (due to wrap around). This means that the expression can take any
// value in this bitwidth, and we have to return full range. // value in this bitwidth, and we have to return full range.
if (StartRange.contains(MovedBoundary)) if (StartRange.contains(MovedBoundary))
return ConstantRange(BitWidth, /* isFullSet = */ true); return ConstantRange::getFull(BitWidth);
APInt NewLower = APInt NewLower =
Descending ? std::move(MovedBoundary) : std::move(StartLower); 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 we end up with full range, return a proper full range.
if (NewLower == NewUpper) if (NewLower == NewUpper)
return ConstantRange(BitWidth, /* isFullSet = */ true); return ConstantRange::getFull(BitWidth);
// No overflow detected, return [StartLower, StartUpper + Offset + 1) range. // No overflow detected, return [StartLower, StartUpper + Offset + 1) range.
return ConstantRange(std::move(NewLower), std::move(NewUpper)); return ConstantRange(std::move(NewLower), std::move(NewUpper));
@ -5939,17 +5939,17 @@ ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
SelectPattern StartPattern(*this, BitWidth, Start); SelectPattern StartPattern(*this, BitWidth, Start);
if (!StartPattern.isRecognized()) if (!StartPattern.isRecognized())
return ConstantRange(BitWidth, /* isFullSet = */ true); return ConstantRange::getFull(BitWidth);
SelectPattern StepPattern(*this, BitWidth, Step); SelectPattern StepPattern(*this, BitWidth, Step);
if (!StepPattern.isRecognized()) if (!StepPattern.isRecognized())
return ConstantRange(BitWidth, /* isFullSet = */ true); return ConstantRange::getFull(BitWidth);
if (StartPattern.Condition != StepPattern.Condition) { if (StartPattern.Condition != StepPattern.Condition) {
// We don't handle this case today; but we could, by considering four // 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 // possibilities below instead of two. I'm not sure if there are cases where
// that will help over what getRange already does, though. // 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 // 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); setLimitsForSelectPattern(*SI, Lower, Upper);
ConstantRange CR = Lower != Upper ? ConstantRange(Lower, Upper) ConstantRange CR = Lower != Upper ? ConstantRange(Lower, Upper)
: ConstantRange(BitWidth, true); : ConstantRange::getFull(BitWidth);
if (auto *I = dyn_cast<Instruction>(V)) if (auto *I = dyn_cast<Instruction>(V))
if (auto *Range = IIQ.getMetadata(I, LLVMContext::MD_range)) 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"); assert(!Known.hasConflict() && "Expected valid KnownBits");
if (Known.isUnknown()) 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 // For unsigned ranges, or signed ranges with known sign bit, create a simple
// range between the smallest and largest possible value. // range between the smallest and largest possible value.
@ -88,53 +88,53 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred,
case CmpInst::ICMP_NE: case CmpInst::ICMP_NE:
if (CR.isSingleElement()) if (CR.isSingleElement())
return ConstantRange(CR.getUpper(), CR.getLower()); return ConstantRange(CR.getUpper(), CR.getLower());
return ConstantRange(W); return getFull(W);
case CmpInst::ICMP_ULT: { case CmpInst::ICMP_ULT: {
APInt UMax(CR.getUnsignedMax()); APInt UMax(CR.getUnsignedMax());
if (UMax.isMinValue()) if (UMax.isMinValue())
return ConstantRange(W, /* empty */ false); return getEmpty(W);
return ConstantRange(APInt::getMinValue(W), std::move(UMax)); return ConstantRange(APInt::getMinValue(W), std::move(UMax));
} }
case CmpInst::ICMP_SLT: { case CmpInst::ICMP_SLT: {
APInt SMax(CR.getSignedMax()); APInt SMax(CR.getSignedMax());
if (SMax.isMinSignedValue()) if (SMax.isMinSignedValue())
return ConstantRange(W, /* empty */ false); return getEmpty(W);
return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax)); return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax));
} }
case CmpInst::ICMP_ULE: { case CmpInst::ICMP_ULE: {
APInt UMax(CR.getUnsignedMax()); APInt UMax(CR.getUnsignedMax());
if (UMax.isMaxValue()) if (UMax.isMaxValue())
return ConstantRange(W); return getFull(W);
return ConstantRange(APInt::getMinValue(W), std::move(UMax) + 1); return ConstantRange(APInt::getMinValue(W), std::move(UMax) + 1);
} }
case CmpInst::ICMP_SLE: { case CmpInst::ICMP_SLE: {
APInt SMax(CR.getSignedMax()); APInt SMax(CR.getSignedMax());
if (SMax.isMaxSignedValue()) if (SMax.isMaxSignedValue())
return ConstantRange(W); return getFull(W);
return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax) + 1); return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax) + 1);
} }
case CmpInst::ICMP_UGT: { case CmpInst::ICMP_UGT: {
APInt UMin(CR.getUnsignedMin()); APInt UMin(CR.getUnsignedMin());
if (UMin.isMaxValue()) if (UMin.isMaxValue())
return ConstantRange(W, /* empty */ false); return getEmpty(W);
return ConstantRange(std::move(UMin) + 1, APInt::getNullValue(W)); return ConstantRange(std::move(UMin) + 1, APInt::getNullValue(W));
} }
case CmpInst::ICMP_SGT: { case CmpInst::ICMP_SGT: {
APInt SMin(CR.getSignedMin()); APInt SMin(CR.getSignedMin());
if (SMin.isMaxSignedValue()) if (SMin.isMaxSignedValue())
return ConstantRange(W, /* empty */ false); return getEmpty(W);
return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W)); return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W));
} }
case CmpInst::ICMP_UGE: { case CmpInst::ICMP_UGE: {
APInt UMin(CR.getUnsignedMin()); APInt UMin(CR.getUnsignedMin());
if (UMin.isMinValue()) if (UMin.isMinValue())
return ConstantRange(W); return getFull(W);
return ConstantRange(std::move(UMin), APInt::getNullValue(W)); return ConstantRange(std::move(UMin), APInt::getNullValue(W));
} }
case CmpInst::ICMP_SGE: { case CmpInst::ICMP_SGE: {
APInt SMin(CR.getSignedMin()); APInt SMin(CR.getSignedMin());
if (SMin.isMinSignedValue()) if (SMin.isMinSignedValue())
return ConstantRange(W); return getFull(W);
return ConstantRange(std::move(SMin), APInt::getSignedMinValue(W)); return ConstantRange(std::move(SMin), APInt::getSignedMinValue(W));
} }
} }
@ -219,18 +219,18 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
"NoWrapKind invalid!"); "NoWrapKind invalid!");
unsigned BitWidth = Other.getBitWidth(); unsigned BitWidth = Other.getBitWidth();
ConstantRange Result(BitWidth); ConstantRange Result(BitWidth, /* full */ true);
switch (BinOp) { switch (BinOp) {
default: default:
// Conservative answer: empty set // Conservative answer: empty set
return ConstantRange(BitWidth, false); return getEmpty(BitWidth);
case Instruction::Add: case Instruction::Add:
if (auto *C = Other.getSingleElement()) if (auto *C = Other.getSingleElement())
if (C->isNullValue()) if (C->isNullValue())
// Full set: nothing signed / unsigned wraps when added to 0. // Full set: nothing signed / unsigned wraps when added to 0.
return ConstantRange(BitWidth); return getFull(BitWidth);
if (NoWrapKind & OBO::NoUnsignedWrap) if (NoWrapKind & OBO::NoUnsignedWrap)
Result = Result =
SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth), SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
@ -255,7 +255,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
if (auto *C = Other.getSingleElement()) if (auto *C = Other.getSingleElement())
if (C->isNullValue()) if (C->isNullValue())
// Full set: nothing signed / unsigned wraps when subtracting 0. // Full set: nothing signed / unsigned wraps when subtracting 0.
return ConstantRange(BitWidth); return getFull(BitWidth);
if (NoWrapKind & OBO::NoUnsignedWrap) if (NoWrapKind & OBO::NoUnsignedWrap)
Result = Result =
SubsetIntersect(Result, ConstantRange(Other.getUnsignedMax(), 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 // Handle special case for 0, -1 and 1. See the last for reason why we
// specialize -1 and 1. // specialize -1 and 1.
if (V == 0 || V.isOneValue()) if (V == 0 || V.isOneValue())
return ConstantRange(BitWidth, true); return getFull(BitWidth);
APInt MinValue, MaxValue; APInt MinValue, MaxValue;
if (Unsigned) { if (Unsigned) {
@ -459,7 +459,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
if (!isWrappedSet() && !CR.isWrappedSet()) { if (!isWrappedSet() && !CR.isWrappedSet()) {
if (Lower.ult(CR.Lower)) { if (Lower.ult(CR.Lower)) {
if (Upper.ule(CR.Lower)) if (Upper.ule(CR.Lower))
return ConstantRange(getBitWidth(), false); return getEmpty();
if (Upper.ult(CR.Upper)) if (Upper.ult(CR.Upper))
return ConstantRange(CR.Lower, Upper); return ConstantRange(CR.Lower, Upper);
@ -472,7 +472,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
if (Lower.ult(CR.Upper)) if (Lower.ult(CR.Upper))
return ConstantRange(Lower, CR.Upper); return ConstantRange(Lower, CR.Upper);
return ConstantRange(getBitWidth(), false); return getEmpty();
} }
if (isWrappedSet() && !CR.isWrappedSet()) { if (isWrappedSet() && !CR.isWrappedSet()) {
@ -489,7 +489,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
} }
if (CR.Lower.ult(Lower)) { if (CR.Lower.ult(Lower)) {
if (CR.Upper.ule(Lower)) if (CR.Upper.ule(Lower))
return ConstantRange(getBitWidth(), false); return getEmpty();
return ConstantRange(Lower, CR.Upper); 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; APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper;
if (L.isNullValue() && U.isNullValue()) if (L.isNullValue() && U.isNullValue())
return ConstantRange(getBitWidth()); return getFull();
return ConstantRange(std::move(L), std::move(U)); return ConstantRange(std::move(L), std::move(U));
} }
@ -555,7 +555,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
// ------U L----- : this // ------U L----- : this
// L---------U : CR // L---------U : CR
if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper))
return ConstantRange(getBitWidth()); return getFull();
// ----U L---- : this // ----U L---- : this
// L---U : CR // 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---- : this
// -U L----------- and ------------U L : CR // -U L----------- and ------------U L : CR
if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
return ConstantRange(getBitWidth()); return getFull();
APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower; APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper; APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper;
@ -608,7 +608,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
if (getBitWidth() == ResultBitWidth) if (getBitWidth() == ResultBitWidth)
return *this; return *this;
else else
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
case Instruction::UIToFP: { case Instruction::UIToFP: {
// TODO: use input range if available // TODO: use input range if available
auto BW = getBitWidth(); auto BW = getBitWidth();
@ -628,13 +628,13 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
case Instruction::IntToPtr: case Instruction::IntToPtr:
case Instruction::PtrToInt: case Instruction::PtrToInt:
case Instruction::AddrSpaceCast: case Instruction::AddrSpaceCast:
// Conservatively return full set. // Conservatively return getFull set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
}; };
} }
ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const { ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false); if (isEmptySet()) return getEmpty(DstTySize);
unsigned SrcTySize = getBitWidth(); unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension"); 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 { ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false); if (isEmptySet()) return getEmpty(DstTySize);
unsigned SrcTySize = getBitWidth(); unsigned SrcTySize = getBitWidth();
assert(SrcTySize < DstTySize && "Not a value extension"); 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 { ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
assert(getBitWidth() > DstTySize && "Not a value truncation"); assert(getBitWidth() > DstTySize && "Not a value truncation");
if (isEmptySet()) if (isEmptySet())
return ConstantRange(DstTySize, /*isFullSet=*/false); return getEmpty(DstTySize);
if (isFullSet()) if (isFullSet())
return ConstantRange(DstTySize, /*isFullSet=*/true); return getFull(DstTySize);
APInt LowerDiv(Lower), UpperDiv(Upper); APInt LowerDiv(Lower), UpperDiv(Upper);
ConstantRange Union(DstTySize, /*isFullSet=*/false); ConstantRange Union(DstTySize, /*isFullSet=*/false);
@ -686,7 +686,7 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
// truncated range. // truncated range.
if (Upper.getActiveBits() > DstTySize || if (Upper.getActiveBits() > DstTySize ||
Upper.countTrailingOnes() == DstTySize) Upper.countTrailingOnes() == DstTySize)
return ConstantRange(DstTySize, /*isFullSet=*/true); return getFull(DstTySize);
Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize)); Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
UpperDiv.setAllBits(); UpperDiv.setAllBits();
@ -719,7 +719,7 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
UpperDiv.trunc(DstTySize)).unionWith(Union); UpperDiv.trunc(DstTySize)).unionWith(Union);
} }
return ConstantRange(DstTySize, /*isFullSet=*/true); return getFull(DstTySize);
} }
ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const { ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const {
@ -772,28 +772,28 @@ ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
case Instruction::FMul: case Instruction::FMul:
return multiply(Other); return multiply(Other);
default: default:
// Conservatively return full set. // Conservatively return getFull set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
} }
} }
ConstantRange ConstantRange
ConstantRange::add(const ConstantRange &Other) const { ConstantRange::add(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
if (isFullSet() || Other.isFullSet()) if (isFullSet() || Other.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
APInt NewLower = getLower() + Other.getLower(); APInt NewLower = getLower() + Other.getLower();
APInt NewUpper = getUpper() + Other.getUpper() - 1; APInt NewUpper = getUpper() + Other.getUpper() - 1;
if (NewLower == NewUpper) if (NewLower == NewUpper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper)); ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
if (X.isSizeStrictlySmallerThan(*this) || if (X.isSizeStrictlySmallerThan(*this) ||
X.isSizeStrictlySmallerThan(Other)) X.isSizeStrictlySmallerThan(Other))
// We've wrapped, therefore, full set. // We've wrapped, therefore, full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return X; return X;
} }
@ -813,20 +813,20 @@ ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const {
ConstantRange ConstantRange
ConstantRange::sub(const ConstantRange &Other) const { ConstantRange::sub(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
if (isFullSet() || Other.isFullSet()) if (isFullSet() || Other.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
APInt NewLower = getLower() - Other.getUpper() + 1; APInt NewLower = getLower() - Other.getUpper() + 1;
APInt NewUpper = getUpper() - Other.getLower(); APInt NewUpper = getUpper() - Other.getLower();
if (NewLower == NewUpper) if (NewLower == NewUpper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper)); ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
if (X.isSizeStrictlySmallerThan(*this) || if (X.isSizeStrictlySmallerThan(*this) ||
X.isSizeStrictlySmallerThan(Other)) X.isSizeStrictlySmallerThan(Other))
// We've wrapped, therefore, full set. // We've wrapped, therefore, full set.
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return X; 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. // range according to the greatest power-of-two factor of the single element.
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
// Multiplication is signedness-independent. However different ranges can be // Multiplication is signedness-independent. However different ranges can be
// obtained depending on how the input ranges are treated. These different // 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), // X smax Y is: range(smax(X_smin, Y_smin),
// smax(X_smax, Y_smax)) // smax(X_smax, Y_smax))
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin()); APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1; APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
if (NewU == NewL) if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(NewL), std::move(NewU)); 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), // X umax Y is: range(umax(X_umin, Y_umin),
// umax(X_umax, Y_umax)) // umax(X_umax, Y_umax))
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1; APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
if (NewU == NewL) if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(NewL), std::move(NewU)); 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), // X smin Y is: range(smin(X_smin, Y_smin),
// smin(X_smax, Y_smax)) // smin(X_smax, Y_smax))
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin()); APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1; APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1;
if (NewU == NewL) if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(NewL), std::move(NewU)); 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), // X umin Y is: range(umin(X_umin, Y_umin),
// umin(X_umax, Y_umax)) // umin(X_umax, Y_umax))
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin()); APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1; APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1;
if (NewU == NewL) if (NewU == NewL)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(NewL), std::move(NewU)); return ConstantRange(std::move(NewL), std::move(NewU));
} }
ConstantRange ConstantRange
ConstantRange::udiv(const ConstantRange &RHS) const { ConstantRange::udiv(const ConstantRange &RHS) const {
if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue()) if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
if (RHS.isFullSet()) if (RHS.isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax()); 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 // If the LHS is Full and the RHS is a wrapped interval containing 1 then
// this could occur. // this could occur.
if (Lower == Upper) if (Lower == Upper)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(Lower), std::move(Upper)); return ConstantRange(std::move(Lower), std::move(Upper));
} }
@ -968,40 +968,40 @@ ConstantRange::udiv(const ConstantRange &RHS) const {
ConstantRange ConstantRange
ConstantRange::binaryAnd(const ConstantRange &Other) const { ConstantRange::binaryAnd(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
// TODO: replace this with something less conservative // TODO: replace this with something less conservative
APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax());
if (umin.isAllOnesValue()) if (umin.isAllOnesValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(APInt::getNullValue(getBitWidth()), std::move(umin) + 1); return ConstantRange(APInt::getNullValue(getBitWidth()), std::move(umin) + 1);
} }
ConstantRange ConstantRange
ConstantRange::binaryOr(const ConstantRange &Other) const { ConstantRange::binaryOr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
// TODO: replace this with something less conservative // TODO: replace this with something less conservative
APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
if (umax.isNullValue()) if (umax.isNullValue())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth())); return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth()));
} }
ConstantRange ConstantRange
ConstantRange::shl(const ConstantRange &Other) const { ConstantRange::shl(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt max = getUnsignedMax(); APInt max = getUnsignedMax();
APInt Other_umax = Other.getUnsignedMax(); APInt Other_umax = Other.getUnsignedMax();
// there's overflow! // there's overflow!
if (Other_umax.uge(max.countLeadingZeros())) if (Other_umax.uge(max.countLeadingZeros()))
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
// FIXME: implement the other tricky cases // FIXME: implement the other tricky cases
@ -1015,12 +1015,12 @@ ConstantRange::shl(const ConstantRange &Other) const {
ConstantRange ConstantRange
ConstantRange::lshr(const ConstantRange &Other) const { ConstantRange::lshr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()) + 1; APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()) + 1;
APInt min = getUnsignedMin().lshr(Other.getUnsignedMax()); APInt min = getUnsignedMin().lshr(Other.getUnsignedMax());
if (min == max) if (min == max)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(min), std::move(max)); return ConstantRange(std::move(min), std::move(max));
} }
@ -1028,7 +1028,7 @@ ConstantRange::lshr(const ConstantRange &Other) const {
ConstantRange ConstantRange
ConstantRange::ashr(const ConstantRange &Other) const { ConstantRange::ashr(const ConstantRange &Other) const {
if (isEmptySet() || Other.isEmptySet()) if (isEmptySet() || Other.isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
// May straddle zero, so handle both positive and negative cases. // May straddle zero, so handle both positive and negative cases.
// 'PosMax' is the upper bound of the result of the ashr // 'PosMax' is the upper bound of the result of the ashr
@ -1074,16 +1074,16 @@ ConstantRange::ashr(const ConstantRange &Other) const {
max = PosMax; max = PosMax;
} }
if (min == max) if (min == max)
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(std::move(min), std::move(max)); return ConstantRange(std::move(min), std::move(max));
} }
ConstantRange ConstantRange::inverse() const { ConstantRange ConstantRange::inverse() const {
if (isFullSet()) if (isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false); return getEmpty();
if (isEmptySet()) if (isEmptySet())
return ConstantRange(getBitWidth(), /*isFullSet=*/true); return getFull();
return ConstantRange(Upper, Lower); return ConstantRange(Upper, Lower);
} }

View File

@ -3269,7 +3269,7 @@ void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) {
unsigned NumRanges = NumOperands / 2; unsigned NumRanges = NumOperands / 2;
Assert(NumRanges >= 1, "It should have at least one range!", Range); 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) { for (unsigned i = 0; i < NumRanges; ++i) {
ConstantInt *Low = ConstantInt *Low =
mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); 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. // Helper - get a range representing a poison value.
ConstantRange Float2IntPass::badRange() { ConstantRange Float2IntPass::badRange() {
return ConstantRange(MaxIntegerBW + 1, true); return ConstantRange::getFull(MaxIntegerBW + 1);
} }
ConstantRange Float2IntPass::unknownRange() { ConstantRange Float2IntPass::unknownRange() {
return ConstantRange(MaxIntegerBW + 1, false); return ConstantRange::getEmpty(MaxIntegerBW + 1);
} }
ConstantRange Float2IntPass::validateRange(ConstantRange R) { ConstantRange Float2IntPass::validateRange(ConstantRange R) {
if (R.getBitWidth() > MaxIntegerBW + 1) 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 // Path terminated cleanly - use the type of the integer input to seed
// the analysis. // the analysis.
unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits(); unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
auto Input = ConstantRange(BW, true); auto Input = ConstantRange::getFull(BW);
auto CastOp = (Instruction::CastOps)I->getOpcode(); auto CastOp = (Instruction::CastOps)I->getOpcode();
seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1))); seen(I, validateRange(Input.castOp(CastOp, MaxIntegerBW+1)));
continue; continue;

View File

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