ConstantRange ConstantRange::ashr(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); // May straddle zero, so handle both positive and negative cases. // 'PosMax' is the upper bound of the result of the ashr // operation, when Upper of the LHS of ashr is a non-negative. // number. Since ashr of a non-negative number will result in a // smaller number, the Upper value of LHS is shifted right with // the minimum value of 'Other' instead of the maximum value. APInt PosMax = getSignedMax().ashr(Other.getUnsignedMin()) + 1; // 'PosMin' is the lower bound of the result of the ashr // operation, when Lower of the LHS is a non-negative number. // Since ashr of a non-negative number will result in a smaller // number, the Lower value of LHS is shifted right with the // maximum value of 'Other'. APInt PosMin = getSignedMin().ashr(Other.getUnsignedMax()); // 'NegMax' is the upper bound of the result of the ashr // operation, when Upper of the LHS of ashr is a negative number. // Since 'ashr' of a negative number will result in a bigger // number, the Upper value of LHS is shifted right with the // maximum value of 'Other'. APInt NegMax = getSignedMax().ashr(Other.getUnsignedMax()) + 1; // 'NegMin' is the lower bound of the result of the ashr // operation, when Lower of the LHS of ashr is a negative number. // Since 'ashr' of a negative number will result in a bigger // number, the Lower value of LHS is shifted right with the // minimum value of 'Other'. APInt NegMin = getSignedMin().ashr(Other.getUnsignedMin()); APInt max, min; if (getSignedMin().isNonNegative()) { // Upper and Lower of LHS are non-negative. min = PosMin; max = PosMax; } else if (getSignedMax().isNegative()) { // Upper and Lower of LHS are negative. min = NegMin; max = NegMax; } else { // Upper is non-negative and Lower is negative. min = NegMin; max = PosMax; } if (min == max) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(std::move(min), std::move(max)); }
ConstantRange ConstantRange::udiv(const ConstantRange &RHS) const { if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax() == 0) return ConstantRange(getBitWidth(), /*isFullSet=*/false); if (RHS.isFullSet()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax()); APInt RHS_umin = RHS.getUnsignedMin(); if (RHS_umin == 0) { // We want the lowest value in RHS excluding zero. Usually that would be 1 // except for a range in the form of [X, 1) in which case it would be X. if (RHS.getUpper() == 1) RHS_umin = RHS.getLower(); else RHS_umin = APInt(getBitWidth(), 1); } 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 ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(Lower, Upper); }
/// Annotate the Shr in (X << IVOperand) >> C as exact using the /// information from the IV's range. Returns true if anything changed, false /// otherwise. bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO, Value *IVOperand) { using namespace llvm::PatternMatch; if (BO->getOpcode() == Instruction::Shl) { bool Changed = false; ConstantRange IVRange = SE->getUnsignedRange(SE->getSCEV(IVOperand)); for (auto *U : BO->users()) { const APInt *C; if (match(U, m_AShr(m_Shl(m_Value(), m_Specific(IVOperand)), m_APInt(C))) || match(U, m_LShr(m_Shl(m_Value(), m_Specific(IVOperand)), m_APInt(C)))) { BinaryOperator *Shr = cast<BinaryOperator>(U); if (!Shr->isExact() && IVRange.getUnsignedMin().uge(*C)) { Shr->setIsExact(true); Changed = true; } } } return Changed; } return false; }
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::lshr(const ConstantRange &Amount) const { if (isEmptySet()) return *this; APInt min = getUnsignedMax().lshr(Amount.getUnsignedMin()); APInt max = getUnsignedMin().lshr(Amount.getUnsignedMax()); return ConstantRange(min, max); }
ConstantRange ConstantRange::lshr(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()); APInt min = getUnsignedMin().lshr(Other.getUnsignedMax()); if (min == max + 1) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(min, max + 1); }
ConstantRange ConstantRange::binaryOr(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); // TODO: replace this with something less conservative APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); if (umax.isMinValue()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(umax, APInt::getNullValue(getBitWidth())); }
ConstantRange 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); APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin()); APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1; if (NewU == NewL) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(NewL, NewU); }
ConstantRange ConstantRange::multiply(const ConstantRange &Other) const { // TODO: If either operand is a single element and the multiply is known to // be non-wrapping, round the result min and max value to the appropriate // multiple of that element. If wrapping is possible, at least adjust the // range according to the greatest power-of-two factor of the single element. if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); // Multiplication is signedness-independent. However different ranges can be // obtained depending on how the input ranges are treated. These different // ranges are all conservatively correct, but one might be better than the // other. We calculate two ranges; one treating the inputs as unsigned // and the other signed, then return the smallest of these ranges. // Unsigned range first. APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2); ConstantRange Result_zext = ConstantRange(this_min * Other_min, this_max * Other_max + 1); ConstantRange UR = Result_zext.truncate(getBitWidth()); // If the unsigned range doesn't wrap, and isn't negative then it's a range // from one positive number to another which is as good as we can generate. // In this case, skip the extra work of generating signed ranges which aren't // going to be better than this range. if (!UR.isWrappedSet() && (UR.getUpper().isNonNegative() || UR.getUpper().isMinSignedValue())) return UR; // Now the signed range. Because we could be dealing with negative numbers // here, the lower bound is the smallest of the cartesian product of the // lower and upper ranges; for example: // [-1,4) * [-2,3) = min(-1*-2, -1*2, 3*-2, 3*2) = -6. // Similarly for the upper bound, swapping min for max. this_min = getSignedMin().sext(getBitWidth() * 2); this_max = getSignedMax().sext(getBitWidth() * 2); Other_min = Other.getSignedMin().sext(getBitWidth() * 2); Other_max = Other.getSignedMax().sext(getBitWidth() * 2); auto L = {this_min * Other_min, this_min * Other_max, this_max * Other_min, this_max * Other_max}; auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); }; ConstantRange Result_sext(std::min(L, Compare), std::max(L, Compare) + 1); ConstantRange SR = Result_sext.truncate(getBitWidth()); return UR.isSizeStrictlySmallerThan(SR) ? UR : SR; }
ConstantRange ConstantRange::shl(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); APInt min = getUnsignedMin().shl(Other.getUnsignedMin()); APInt max = getUnsignedMax().shl(Other.getUnsignedMax()); // there's no overflow! APInt Zeros(getBitWidth(), getUnsignedMax().countLeadingZeros()); if (Zeros.ugt(Other.getUnsignedMax())) return ConstantRange(min, max + 1); // FIXME: implement the other tricky cases return ConstantRange(getBitWidth(), /*isFullSet=*/true); }
ConstantRange ConstantRange::shl(const ConstantRange &Amount) const { if (isEmptySet()) return *this; APInt min = getUnsignedMin() << Amount.getUnsignedMin(); APInt max = getUnsignedMax() << Amount.getUnsignedMax(); // there's no overflow! APInt Zeros(getBitWidth(), getUnsignedMax().countLeadingZeros()); if (Zeros.uge(Amount.getUnsignedMax())) return ConstantRange(min, max); // FIXME: implement the other tricky cases return ConstantRange(getBitWidth()); }
ConstantRange ConstantRange::multiply(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); if (isFullSet() || Other.isFullSet()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2); ConstantRange Result_zext = ConstantRange(this_min * Other_min, this_max * Other_max + 1); return Result_zext.truncate(getBitWidth()); }
ConstantRange ConstantRange::multiply(const ConstantRange &Other) const { // TODO: If either operand is a single element and the multiply is known to // be non-wrapping, round the result min and max value to the appropriate // multiple of that element. If wrapping is possible, at least adjust the // range according to the greatest power-of-two factor of the single element. if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2); ConstantRange Result_zext = ConstantRange(this_min * Other_min, this_max * Other_max + 1); return Result_zext.truncate(getBitWidth()); }
ConstantRange ConstantRange::shl(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); APInt max = getUnsignedMax(); APInt Other_umax = Other.getUnsignedMax(); // there's overflow! if (Other_umax.uge(max.countLeadingZeros())) return ConstantRange(getBitWidth(), /*isFullSet=*/true); // FIXME: implement the other tricky cases APInt min = getUnsignedMin(); min <<= Other.getUnsignedMin(); max <<= Other_umax; return ConstantRange(std::move(min), std::move(max) + 1); }
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)); } } }