From 977934f00f7cac6476650db75f6497495908b486 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 24 Mar 2019 09:34:40 +0000 Subject: [PATCH] [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 --- llvm/include/llvm/IR/ConstantRange.h | 22 +++++- llvm/lib/Analysis/LazyValueInfo.cpp | 10 +-- llvm/lib/Analysis/ScalarEvolution.cpp | 14 ++-- llvm/lib/Analysis/ValueTracking.cpp | 2 +- llvm/lib/IR/ConstantRange.cpp | 128 +++++++++++++++---------------- llvm/lib/IR/Verifier.cpp | 2 +- llvm/lib/Transforms/Scalar/Float2Int.cpp | 6 +- llvm/unittests/IR/ConstantRangeTest.cpp | 6 +- 8 files changed, 105 insertions(+), 85 deletions(-) diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index 2356b70..2d59b94 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -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. diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 4e915be..9442044 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -963,7 +963,7 @@ Optional 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(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(Result.getConstant())) && "ConstantInt value must be represented as constantrange"); - return ConstantRange(Width, /*isFullSet=*/true); + return ConstantRange::getFull(Width); } static LazyValueInfo::Tristate diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 8726ab3..920e0dd 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -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 diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 4c2e7f2..d3cbd07 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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(V)) if (auto *Range = IIQ.getMetadata(I, LLVMContext::MD_range)) diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 16def8b..732f5c0 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -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); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index ae76e31..61a9fd6 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -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(Range->getOperand(2 * i)); diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp index 4a1275d..cb0288a 100644 --- a/llvm/lib/Transforms/Scalar/Float2Int.cpp +++ b/llvm/lib/Transforms/Scalar/Float2Int.cpp @@ -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 &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; diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index 2469d86..058f5342 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -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) { -- 2.7.4