// intersect1Wrapped - This helper function is used to intersect two ranges when // it is known that LHS is wrapped and RHS isn't. // ConstantRange ConstantRange::intersect1Wrapped(const ConstantRange &LHS, const ConstantRange &RHS) { assert(LHS.isWrappedSet() && !RHS.isWrappedSet()); // Check to see if we overlap on the Left side of RHS... // if (RHS.Lower.ult(LHS.Upper)) { // We do overlap on the left side of RHS, see if we overlap on the right of // RHS... if (RHS.Upper.ugt(LHS.Lower)) { // Ok, the result overlaps on both the left and right sides. See if the // resultant interval will be smaller if we wrap or not... // if (LHS.getSetSize().ult(RHS.getSetSize())) return LHS; else return RHS; } else { // No overlap on the right, just on the left. return ConstantRange(RHS.Lower, LHS.Upper); } } else { // We don't overlap on the left side of RHS, see if we overlap on the right // of RHS... if (RHS.Upper.ugt(LHS.Lower)) { // Simple overlap... return ConstantRange(LHS.Lower, RHS.Upper); } else { // No overlap... return ConstantRange(LHS.getBitWidth(), false); } } }
/// intersectWith - Return the range that results from the intersection of this /// range with another range. /// ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); // Handle common special cases if (isEmptySet() || CR.isFullSet()) return *this; if (isFullSet() || CR.isEmptySet()) return CR; if (!isWrappedSet()) { if (!CR.isWrappedSet()) { using namespace APIntOps; APInt L = umax(Lower, CR.Lower); APInt U = umin(Upper, CR.Upper); if (L.ult(U)) // If range isn't empty... return ConstantRange(L, U); else return ConstantRange(getBitWidth(), false);// Otherwise, empty set } else return intersect1Wrapped(CR, *this); } else { // We know "this" is wrapped... if (!CR.isWrappedSet()) return intersect1Wrapped(*this, CR); else { // Both ranges are wrapped... using namespace APIntOps; APInt L = umax(Lower, CR.Lower); APInt U = umin(Upper, CR.Upper); return ConstantRange(L, U); } } return *this; }
ConstantRange ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, const ConstantRange &Other, unsigned NoWrapKind) { typedef OverflowingBinaryOperator OBO; // Computes the intersection of CR0 and CR1. It is different from // intersectWith in that the ConstantRange returned will only contain elements // in both CR0 and CR1 (i.e. SubsetIntersect(X, Y) is a *subset*, proper or // not, of both X and Y). auto SubsetIntersect = [](const ConstantRange &CR0, const ConstantRange &CR1) { return CR0.inverse().unionWith(CR1.inverse()).inverse(); }; assert(BinOp >= Instruction::BinaryOpsBegin && BinOp < Instruction::BinaryOpsEnd && "Binary operators only!"); assert((NoWrapKind == OBO::NoSignedWrap || NoWrapKind == OBO::NoUnsignedWrap || NoWrapKind == (OBO::NoUnsignedWrap | OBO::NoSignedWrap)) && "NoWrapKind invalid!"); unsigned BitWidth = Other.getBitWidth(); if (BinOp != Instruction::Add) // Conservative answer: empty set return ConstantRange(BitWidth, false); if (auto *C = Other.getSingleElement()) if (C->isMinValue()) // Full set: nothing signed / unsigned wraps when added to 0. return ConstantRange(BitWidth); ConstantRange Result(BitWidth); if (NoWrapKind & OBO::NoUnsignedWrap) Result = SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth), -Other.getUnsignedMax())); if (NoWrapKind & OBO::NoSignedWrap) { APInt SignedMin = Other.getSignedMin(); APInt SignedMax = Other.getSignedMax(); if (SignedMax.isStrictlyPositive()) Result = SubsetIntersect( Result, ConstantRange(APInt::getSignedMinValue(BitWidth), APInt::getSignedMinValue(BitWidth) - SignedMax)); if (SignedMin.isNegative()) Result = SubsetIntersect( Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin, APInt::getSignedMinValue(BitWidth))); } return Result; }
bool ConstantRange::isSizeStrictlySmallerThan(const ConstantRange &Other) const { assert(getBitWidth() == Other.getBitWidth()); if (isFullSet()) return false; if (Other.isFullSet()) return true; return (Upper - Lower).ult(Other.Upper - Other.Lower); }
ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, const ConstantRange &CR) { uint32_t W = CR.getBitWidth(); switch (Pred) { default: assert(!"Invalid ICmp predicate to makeICmpRegion()"); case ICmpInst::ICMP_EQ: return CR; case ICmpInst::ICMP_NE: if (CR.isSingleElement()) return ConstantRange(CR.getUpper(), CR.getLower()); return ConstantRange(W); case ICmpInst::ICMP_ULT: return ConstantRange(APInt::getMinValue(W), CR.getUnsignedMax()); case ICmpInst::ICMP_SLT: return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax()); case ICmpInst::ICMP_ULE: { APInt UMax(CR.getUnsignedMax()); if (UMax.isMaxValue()) return ConstantRange(W); return ConstantRange(APInt::getMinValue(W), UMax + 1); } case ICmpInst::ICMP_SLE: { APInt SMax(CR.getSignedMax()); if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue()) return ConstantRange(W); return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); } case ICmpInst::ICMP_UGT: return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W)); case ICmpInst::ICMP_SGT: return ConstantRange(CR.getSignedMin() + 1, APInt::getSignedMinValue(W)); case ICmpInst::ICMP_UGE: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMinValue()) return ConstantRange(W); return ConstantRange(UMin, APInt::getNullValue(W)); } case ICmpInst::ICMP_SGE: { APInt SMin(CR.getSignedMin()); if (SMin.isMinSignedValue()) return ConstantRange(W); return ConstantRange(SMin, APInt::getSignedMinValue(W)); } } }
ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &CR) { if (CR.isEmptySet()) return CR; uint32_t W = CR.getBitWidth(); switch (Pred) { default: llvm_unreachable("Invalid ICmp predicate to makeAllowedICmpRegion()"); case CmpInst::ICMP_EQ: return CR; case CmpInst::ICMP_NE: if (CR.isSingleElement()) return ConstantRange(CR.getUpper(), CR.getLower()); return ConstantRange(W); case CmpInst::ICMP_ULT: { APInt UMax(CR.getUnsignedMax()); if (UMax.isMinValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(APInt::getMinValue(W), UMax); } case CmpInst::ICMP_SLT: { APInt SMax(CR.getSignedMax()); if (SMax.isMinSignedValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(APInt::getSignedMinValue(W), SMax); } case CmpInst::ICMP_ULE: { APInt UMax(CR.getUnsignedMax()); if (UMax.isMaxValue()) return ConstantRange(W); return ConstantRange(APInt::getMinValue(W), UMax + 1); } case CmpInst::ICMP_SLE: { APInt SMax(CR.getSignedMax()); if (SMax.isMaxSignedValue()) return ConstantRange(W); return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); } case CmpInst::ICMP_UGT: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMaxValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(UMin + 1, APInt::getNullValue(W)); } case CmpInst::ICMP_SGT: { APInt SMin(CR.getSignedMin()); if (SMin.isMaxSignedValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(SMin + 1, APInt::getSignedMinValue(W)); } case CmpInst::ICMP_UGE: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMinValue()) return ConstantRange(W); return ConstantRange(UMin, APInt::getNullValue(W)); } case CmpInst::ICMP_SGE: { APInt SMin(CR.getSignedMin()); if (SMin.isMinSignedValue()) return ConstantRange(W); return ConstantRange(SMin, APInt::getSignedMinValue(W)); } } }
/// unionWith - Return the range that results from the union of this range with /// another range. The resultant range is guaranteed to include the elements of /// both sets, but may contain more. For example, [3, 9) union [12,15) is /// [3, 15), which includes 9, 10, and 11, which were not included in either /// set before. /// ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); if ( isFullSet() || CR.isEmptySet()) return *this; if (CR.isFullSet() || isEmptySet()) return CR; if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); if (!isWrappedSet() && !CR.isWrappedSet()) { if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) { // If the two ranges are disjoint, find the smaller gap and bridge it. APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); return ConstantRange(CR.Lower, Upper); } APInt L = Lower, U = Upper; if (CR.Lower.ult(L)) L = CR.Lower; if ((CR.Upper - 1).ugt(U - 1)) U = CR.Upper; if (L == 0 && U == 0) return ConstantRange(getBitWidth()); return ConstantRange(L, U); } if (!CR.isWrappedSet()) { // ------U L----- and ------U L----- : this // L--U L--U : CR if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower)) return *this; // ------U L----- : this // L---------U : CR if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) return ConstantRange(getBitWidth()); // ----U L---- : this // L---U : CR // <d1> <d2> if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); return ConstantRange(CR.Lower, Upper); } // ----U L----- : this // L----U : CR if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper)) return ConstantRange(CR.Lower, Upper); // ------U L---- : this // L-----U : CR assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) && "ConstantRange::unionWith missed a case with one range wrapped"); return ConstantRange(Lower, CR.Upper); } // ------U L---- and ------U L---- : this // -U L----------- and ------------U L : CR if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) return ConstantRange(getBitWidth()); APInt L = Lower, U = Upper; if (CR.Upper.ugt(U)) U = CR.Upper; if (CR.Lower.ult(L)) L = CR.Lower; return ConstantRange(L, U); }
/// intersectWith - Return the range that results from the intersection of this /// range with another range. The resultant range is guaranteed to include all /// elements contained in both input ranges, and to have the smallest possible /// set size that does so. Because there may be two intersections with the /// same set size, A.intersectWith(B) might not be equal to B.intersectWith(A). ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); // Handle common cases. if ( isEmptySet() || CR.isFullSet()) return *this; if (CR.isEmptySet() || isFullSet()) return CR; if (!isWrappedSet() && CR.isWrappedSet()) return CR.intersectWith(*this); if (!isWrappedSet() && !CR.isWrappedSet()) { if (Lower.ult(CR.Lower)) { if (Upper.ule(CR.Lower)) return ConstantRange(getBitWidth(), false); if (Upper.ult(CR.Upper)) return ConstantRange(CR.Lower, Upper); return CR; } if (Upper.ult(CR.Upper)) return *this; if (Lower.ult(CR.Upper)) return ConstantRange(Lower, CR.Upper); return ConstantRange(getBitWidth(), false); } if (isWrappedSet() && !CR.isWrappedSet()) { if (CR.Lower.ult(Upper)) { if (CR.Upper.ult(Upper)) return CR; if (CR.Upper.ule(Lower)) return ConstantRange(CR.Lower, Upper); if (getSetSize().ult(CR.getSetSize())) return *this; return CR; } if (CR.Lower.ult(Lower)) { if (CR.Upper.ule(Lower)) return ConstantRange(getBitWidth(), false); return ConstantRange(Lower, CR.Upper); } return CR; } if (CR.Upper.ult(Upper)) { if (CR.Lower.ult(Upper)) { if (getSetSize().ult(CR.getSetSize())) return *this; return CR; } if (CR.Lower.ult(Lower)) return ConstantRange(Lower, CR.Upper); return CR; } if (CR.Upper.ule(Lower)) { if (CR.Lower.ult(Lower)) return *this; return ConstantRange(CR.Lower, Upper); } if (getSetSize().ult(CR.getSetSize())) return *this; return CR; }
/// unionWith - Return the range that results from the union of this range with /// another range. The resultant range is guaranteed to include the elements of /// both sets, but may contain more. For example, [3, 9) union [12,15) is /// [3, 15), which includes 9, 10, and 11, which were not included in either /// set before. /// ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); if ( isFullSet() || CR.isEmptySet()) return *this; if (CR.isFullSet() || isEmptySet()) return CR; if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); APInt L = Lower, U = Upper; if (!isWrappedSet() && !CR.isWrappedSet()) { if (CR.Lower.ult(L)) L = CR.Lower; if (CR.Upper.ugt(U)) U = CR.Upper; } if (isWrappedSet() && !CR.isWrappedSet()) { if ((CR.Lower.ult(Upper) && CR.Upper.ult(Upper)) || (CR.Lower.ugt(Lower) && CR.Upper.ugt(Lower))) { return *this; } if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) { return ConstantRange(getBitWidth()); } if (CR.Lower.ule(Upper) && CR.Upper.ule(Lower)) { APInt d1 = CR.Upper - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) { U = CR.Upper; } else { L = CR.Upper; } } if (Upper.ult(CR.Lower) && CR.Upper.ult(Lower)) { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) { U = CR.Lower + 1; } else { L = CR.Upper - 1; } } if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper)) { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Lower; if (d1.ult(d2)) { U = CR.Lower + 1; } else { L = CR.Lower; } } } if (isWrappedSet() && CR.isWrappedSet()) { if (Lower.ult(CR.Upper) || CR.Lower.ult(Upper)) return ConstantRange(getBitWidth()); if (CR.Upper.ugt(U)) { U = CR.Upper; } if (CR.Lower.ult(L)) { L = CR.Lower; } if (L == U) return ConstantRange(getBitWidth()); } return ConstantRange(L, U); }
ConstantRange Float2IntPass::validateRange(ConstantRange R) { if (R.getBitWidth() > MaxIntegerBW + 1) return badRange(); return R; }