From dbc3fbafe7cbf10bac30da4d4b6eb6082fed3daa Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 21 Apr 2019 15:22:54 +0000 Subject: [PATCH] [ConstantRange] Add getNonEmpty() constructor ConstantRanges have an annoying special case: If upper and lower are the same, it can be either an empty or a full set. When constructing constant ranges nearly always a full set is intended, but this still requires an explicit check in many places. This revision adds a getNonEmpty() constructor that disambiguates this case: If upper and lower are the same, a full set is created. Differential Revision: https://reviews.llvm.org/D60947 llvm-svn: 358854 --- llvm/include/llvm/IR/ConstantRange.h | 8 ++++ llvm/lib/Analysis/ScalarEvolution.cpp | 6 +-- llvm/lib/Analysis/ValueTracking.cpp | 3 +- llvm/lib/IR/ConstantRange.cpp | 74 ++++++++--------------------------- 4 files changed, 27 insertions(+), 64 deletions(-) diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index ec57e08..6dbe405 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -79,6 +79,14 @@ public: return ConstantRange(BitWidth, true); } + /// Create non-empty constant range with the given bounds. If Lower and + /// Upper are the same, a full range is returned. + static ConstantRange getNonEmpty(APInt Lower, APInt Upper) { + if (Lower == Upper) + return getFull(Lower.getBitWidth()); + return ConstantRange(std::move(Lower), std::move(Upper)); + } + /// 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/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 01b4019..1f69bc8 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -5808,12 +5808,8 @@ static ConstantRange getRangeForAffineARHelper(APInt Step, Descending ? std::move(StartUpper) : std::move(MovedBoundary); NewUpper += 1; - // If we end up with full range, return a proper full range. - if (NewLower == NewUpper) - return ConstantRange::getFull(BitWidth); - // No overflow detected, return [StartLower, StartUpper + Offset + 1) range. - return ConstantRange(std::move(NewLower), std::move(NewUpper)); + return ConstantRange::getNonEmpty(std::move(NewLower), std::move(NewUpper)); } ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 9c7b0fa..3b08a2d 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5726,8 +5726,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) { else if (auto *SI = dyn_cast(V)) setLimitsForSelectPattern(*SI, Lower, Upper); - ConstantRange CR = Lower != Upper ? ConstantRange(Lower, Upper) - : ConstantRange::getFull(BitWidth); + ConstantRange CR = ConstantRange::getNonEmpty(Lower, Upper); 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 87b66fa..7bd14e6 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -101,18 +101,10 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, return getEmpty(W); return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax)); } - case CmpInst::ICMP_ULE: { - APInt UMax(CR.getUnsignedMax()); - if (UMax.isMaxValue()) - return getFull(W); - return ConstantRange(APInt::getMinValue(W), std::move(UMax) + 1); - } - case CmpInst::ICMP_SLE: { - APInt SMax(CR.getSignedMax()); - if (SMax.isMaxSignedValue()) - return getFull(W); - return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax) + 1); - } + case CmpInst::ICMP_ULE: + return getNonEmpty(APInt::getMinValue(W), CR.getUnsignedMax() + 1); + case CmpInst::ICMP_SLE: + return getNonEmpty(APInt::getSignedMinValue(W), CR.getSignedMax() + 1); case CmpInst::ICMP_UGT: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMaxValue()) @@ -125,18 +117,10 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, return getEmpty(W); return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W)); } - case CmpInst::ICMP_UGE: { - APInt UMin(CR.getUnsignedMin()); - if (UMin.isMinValue()) - return getFull(W); - return ConstantRange(std::move(UMin), APInt::getNullValue(W)); - } - case CmpInst::ICMP_SGE: { - APInt SMin(CR.getSignedMin()); - if (SMin.isMinSignedValue()) - return getFull(W); - return ConstantRange(std::move(SMin), APInt::getSignedMinValue(W)); - } + case CmpInst::ICMP_UGE: + return getNonEmpty(CR.getUnsignedMin(), APInt::getNullValue(W)); + case CmpInst::ICMP_SGE: + return getNonEmpty(CR.getSignedMin(), APInt::getSignedMinValue(W)); } } @@ -948,9 +932,7 @@ ConstantRange::smax(const ConstantRange &Other) const { return getEmpty(); APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin()); APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1; - if (NewU == NewL) - return getFull(); - return ConstantRange(std::move(NewL), std::move(NewU)); + return getNonEmpty(std::move(NewL), std::move(NewU)); } ConstantRange @@ -961,9 +943,7 @@ ConstantRange::umax(const ConstantRange &Other) const { return getEmpty(); APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1; - if (NewU == NewL) - return getFull(); - return ConstantRange(std::move(NewL), std::move(NewU)); + return getNonEmpty(std::move(NewL), std::move(NewU)); } ConstantRange @@ -974,9 +954,7 @@ ConstantRange::smin(const ConstantRange &Other) const { return getEmpty(); APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin()); APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1; - if (NewU == NewL) - return getFull(); - return ConstantRange(std::move(NewL), std::move(NewU)); + return getNonEmpty(std::move(NewL), std::move(NewU)); } ConstantRange @@ -987,9 +965,7 @@ ConstantRange::umin(const ConstantRange &Other) const { return getEmpty(); APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin()); APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1; - if (NewU == NewL) - return getFull(); - return ConstantRange(std::move(NewL), std::move(NewU)); + return getNonEmpty(std::move(NewL), std::move(NewU)); } ConstantRange @@ -1012,13 +988,7 @@ ConstantRange::udiv(const ConstantRange &RHS) const { } APInt Upper = getUnsignedMax().udiv(RHS_umin) + 1; - - // If the LHS is Full and the RHS is a wrapped interval containing 1 then - // this could occur. - if (Lower == Upper) - return getFull(); - - return ConstantRange(std::move(Lower), std::move(Upper)); + return getNonEmpty(std::move(Lower), std::move(Upper)); } ConstantRange @@ -1029,9 +999,7 @@ ConstantRange::binaryAnd(const ConstantRange &Other) const { // TODO: replace this with something less conservative APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); - if (umin.isAllOnesValue()) - return getFull(); - return ConstantRange(APInt::getNullValue(getBitWidth()), std::move(umin) + 1); + return getNonEmpty(APInt::getNullValue(getBitWidth()), std::move(umin) + 1); } ConstantRange @@ -1042,9 +1010,7 @@ ConstantRange::binaryOr(const ConstantRange &Other) const { // TODO: replace this with something less conservative APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); - if (umax.isNullValue()) - return getFull(); - return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth())); + return getNonEmpty(std::move(umax), APInt::getNullValue(getBitWidth())); } ConstantRange @@ -1079,10 +1045,7 @@ ConstantRange::lshr(const ConstantRange &Other) const { APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()) + 1; APInt min = getUnsignedMin().lshr(Other.getUnsignedMax()); - if (min == max) - return getFull(); - - return ConstantRange(std::move(min), std::move(max)); + return getNonEmpty(std::move(min), std::move(max)); } ConstantRange @@ -1133,10 +1096,7 @@ ConstantRange::ashr(const ConstantRange &Other) const { min = NegMin; max = PosMax; } - if (min == max) - return getFull(); - - return ConstantRange(std::move(min), std::move(max)); + return getNonEmpty(std::move(min), std::move(max)); } ConstantRange ConstantRange::inverse() const { -- 2.7.4