@@ -220,6 +220,11 @@ static cl::opt<unsigned>
220220 cl::desc("Size of the expression which is considered huge"),
221221 cl::init(4096));
222222
223+ static cl::opt<unsigned> RangeIterThreshold(
224+ "scev-range-iter-threshold", cl::Hidden,
225+ cl::desc("Threshold for switching to iteratively computing SCEV ranges"),
226+ cl::init(32));
227+
223228static cl::opt<bool>
224229ClassifyExpressions("scalar-evolution-classify-expressions",
225230 cl::Hidden, cl::init(true),
@@ -6425,18 +6430,78 @@ getRangeForUnknownRecurrence(const SCEVUnknown *U) {
64256430 return FullSet;
64266431}
64276432
6433+ const ConstantRange &
6434+ ScalarEvolution::getRangeRefIter(const SCEV *S,
6435+ ScalarEvolution::RangeSignHint SignHint) {
6436+ DenseMap<const SCEV *, ConstantRange> &Cache =
6437+ SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
6438+ : SignedRanges;
6439+ SmallVector<const SCEV *> WorkList;
6440+ SmallPtrSet<const SCEV *, 8> Seen;
6441+
6442+ // Add Expr to the worklist, if Expr is either an N-ary expression or a
6443+ // SCEVUnknown PHI node.
6444+ auto AddToWorklist = [&WorkList, &Seen, &Cache](const SCEV *Expr) {
6445+ if (!Seen.insert(Expr).second)
6446+ return;
6447+ if (Cache.find(Expr) != Cache.end())
6448+ return;
6449+ if (isa<SCEVNAryExpr>(Expr) || isa<SCEVUDivExpr>(Expr))
6450+ WorkList.push_back(Expr);
6451+ else if (auto *UnknownS = dyn_cast<SCEVUnknown>(Expr))
6452+ if (isa<PHINode>(UnknownS->getValue()))
6453+ WorkList.push_back(Expr);
6454+ };
6455+ AddToWorklist(S);
6456+
6457+ // Build worklist by queuing operands of N-ary expressions and phi nodes.
6458+ for (unsigned I = 0; I != WorkList.size(); ++I) {
6459+ const SCEV *P = WorkList[I];
6460+ if (auto *NaryS = dyn_cast<SCEVNAryExpr>(P)) {
6461+ for (const SCEV *Op : NaryS->operands())
6462+ AddToWorklist(Op);
6463+ } else if (auto *UDiv = dyn_cast<SCEVUDivExpr>(P)) {
6464+ AddToWorklist(UDiv->getLHS());
6465+ AddToWorklist(UDiv->getRHS());
6466+ } else {
6467+ auto *UnknownS = cast<SCEVUnknown>(P);
6468+ if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue())) {
6469+ if (!PendingPhiRangesIter.insert(P).second)
6470+ continue;
6471+ for (auto &Op : reverse(P->operands()))
6472+ AddToWorklist(getSCEV(Op));
6473+ }
6474+ }
6475+ }
6476+
6477+ if (!WorkList.empty()) {
6478+ // Use getRangeRef to compute ranges for items in the worklist in reverse
6479+ // order. This will force ranges for earlier operands to be computed before
6480+ // their users in most cases.
6481+ for (const SCEV *P :
6482+ reverse(make_range(WorkList.begin() + 1, WorkList.end()))) {
6483+ getRangeRef(P, SignHint);
6484+
6485+ if (auto *UnknownS = dyn_cast<SCEVUnknown>(P))
6486+ if (const PHINode *P = dyn_cast<PHINode>(UnknownS->getValue()))
6487+ PendingPhiRangesIter.erase(P);
6488+ }
6489+ }
6490+
6491+ return getRangeRef(S, SignHint, 0);
6492+ }
6493+
64286494/// Determine the range for a particular SCEV. If SignHint is
64296495/// HINT_RANGE_UNSIGNED (resp. HINT_RANGE_SIGNED) then getRange prefers ranges
64306496/// with a "cleaner" unsigned (resp. signed) representation.
6431- const ConstantRange &
6432- ScalarEvolution::getRangeRef(const SCEV *S,
6433- ScalarEvolution::RangeSignHint SignHint) {
6497+ const ConstantRange &ScalarEvolution::getRangeRef(
6498+ const SCEV *S, ScalarEvolution::RangeSignHint SignHint, unsigned Depth) {
64346499 DenseMap<const SCEV *, ConstantRange> &Cache =
64356500 SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
64366501 : SignedRanges;
64376502 ConstantRange::PreferredRangeType RangeType =
6438- SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED
6439- ? ConstantRange::Unsigned : ConstantRange::Signed;
6503+ SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? ConstantRange::Unsigned
6504+ : ConstantRange::Signed;
64406505
64416506 // See if we've computed this range already.
64426507 DenseMap<const SCEV *, ConstantRange>::iterator I = Cache.find(S);
@@ -6446,6 +6511,11 @@ ScalarEvolution::getRangeRef(const SCEV *S,
64466511 if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
64476512 return setRange(C, SignHint, ConstantRange(C->getAPInt()));
64486513
6514+ // Switch to iteratively computing the range for S, if it is part of a deeply
6515+ // nested expression.
6516+ if (Depth > RangeIterThreshold)
6517+ return getRangeRefIter(S, SignHint);
6518+
64496519 unsigned BitWidth = getTypeSizeInBits(S->getType());
64506520 ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true);
64516521 using OBO = OverflowingBinaryOperator;
@@ -6465,23 +6535,23 @@ ScalarEvolution::getRangeRef(const SCEV *S,
64656535 }
64666536
64676537 if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
6468- ConstantRange X = getRangeRef(Add->getOperand(0), SignHint);
6538+ ConstantRange X = getRangeRef(Add->getOperand(0), SignHint, Depth + 1 );
64696539 unsigned WrapType = OBO::AnyWrap;
64706540 if (Add->hasNoSignedWrap())
64716541 WrapType |= OBO::NoSignedWrap;
64726542 if (Add->hasNoUnsignedWrap())
64736543 WrapType |= OBO::NoUnsignedWrap;
64746544 for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i)
6475- X = X.addWithNoWrap(getRangeRef(Add->getOperand(i), SignHint),
6545+ X = X.addWithNoWrap(getRangeRef(Add->getOperand(i), SignHint, Depth + 1 ),
64766546 WrapType, RangeType);
64776547 return setRange(Add, SignHint,
64786548 ConservativeResult.intersectWith(X, RangeType));
64796549 }
64806550
64816551 if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
6482- ConstantRange X = getRangeRef(Mul->getOperand(0), SignHint);
6552+ ConstantRange X = getRangeRef(Mul->getOperand(0), SignHint, Depth + 1 );
64836553 for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i)
6484- X = X.multiply(getRangeRef(Mul->getOperand(i), SignHint));
6554+ X = X.multiply(getRangeRef(Mul->getOperand(i), SignHint, Depth + 1 ));
64856555 return setRange(Mul, SignHint,
64866556 ConservativeResult.intersectWith(X, RangeType));
64876557 }
@@ -6507,41 +6577,42 @@ ScalarEvolution::getRangeRef(const SCEV *S,
65076577 }
65086578
65096579 const auto *NAry = cast<SCEVNAryExpr>(S);
6510- ConstantRange X = getRangeRef(NAry->getOperand(0), SignHint);
6580+ ConstantRange X = getRangeRef(NAry->getOperand(0), SignHint, Depth + 1 );
65116581 for (unsigned i = 1, e = NAry->getNumOperands(); i != e; ++i)
6512- X = X.intrinsic(ID, {X, getRangeRef(NAry->getOperand(i), SignHint)});
6582+ X = X.intrinsic(
6583+ ID, {X, getRangeRef(NAry->getOperand(i), SignHint, Depth + 1)});
65136584 return setRange(S, SignHint,
65146585 ConservativeResult.intersectWith(X, RangeType));
65156586 }
65166587
65176588 if (const SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
6518- ConstantRange X = getRangeRef(UDiv->getLHS(), SignHint);
6519- ConstantRange Y = getRangeRef(UDiv->getRHS(), SignHint);
6589+ ConstantRange X = getRangeRef(UDiv->getLHS(), SignHint, Depth + 1 );
6590+ ConstantRange Y = getRangeRef(UDiv->getRHS(), SignHint, Depth + 1 );
65206591 return setRange(UDiv, SignHint,
65216592 ConservativeResult.intersectWith(X.udiv(Y), RangeType));
65226593 }
65236594
65246595 if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
6525- ConstantRange X = getRangeRef(ZExt->getOperand(), SignHint);
6596+ ConstantRange X = getRangeRef(ZExt->getOperand(), SignHint, Depth + 1 );
65266597 return setRange(ZExt, SignHint,
65276598 ConservativeResult.intersectWith(X.zeroExtend(BitWidth),
65286599 RangeType));
65296600 }
65306601
65316602 if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
6532- ConstantRange X = getRangeRef(SExt->getOperand(), SignHint);
6603+ ConstantRange X = getRangeRef(SExt->getOperand(), SignHint, Depth + 1 );
65336604 return setRange(SExt, SignHint,
65346605 ConservativeResult.intersectWith(X.signExtend(BitWidth),
65356606 RangeType));
65366607 }
65376608
65386609 if (const SCEVPtrToIntExpr *PtrToInt = dyn_cast<SCEVPtrToIntExpr>(S)) {
6539- ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint);
6610+ ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint, Depth + 1 );
65406611 return setRange(PtrToInt, SignHint, X);
65416612 }
65426613
65436614 if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
6544- ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint);
6615+ ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint, Depth + 1 );
65456616 return setRange(Trunc, SignHint,
65466617 ConservativeResult.intersectWith(X.truncate(BitWidth),
65476618 RangeType));
@@ -6671,12 +6742,13 @@ ScalarEvolution::getRangeRef(const SCEV *S,
66716742 RangeType);
66726743
66736744 // A range of Phi is a subset of union of all ranges of its input.
6674- if (const PHINode *Phi = dyn_cast<PHINode>(U->getValue())) {
6745+ if (PHINode *Phi = dyn_cast<PHINode>(U->getValue())) {
66756746 // Make sure that we do not run over cycled Phis.
66766747 if (PendingPhiRanges.insert(Phi).second) {
66776748 ConstantRange RangeFromOps(BitWidth, /*isFullSet=*/false);
6749+
66786750 for (const auto &Op : Phi->operands()) {
6679- auto OpRange = getRangeRef(getSCEV(Op), SignHint);
6751+ auto OpRange = getRangeRef(getSCEV(Op), SignHint, Depth + 1 );
66806752 RangeFromOps = RangeFromOps.unionWith(OpRange);
66816753 // No point to continue if we already have a full set.
66826754 if (RangeFromOps.isFullSet())
0 commit comments