Skip to content

Commit 6022a3a

Browse files
committed
[SCEV] Store predicates for EL/ENT in SmallVector.
Store predicates in ExitLimit and ExitNotTaken in a SmallVector instead of a SmallPtrSet. This guarantees the predicates can be iterated on in a predictable manner. This ensures the predicates can be printed and generated in a predictable order. This shifts de-duplication of predicates to construction time for ExitLimit. ExitNotTaken just takes predicates from ExitLimit, so they should also be free of duplicates. This was exposed by 2f7ccaf (#108777). Should fix https://lab.llvm.org/buildbot/#/builders/110/builds/1494.
1 parent d3ca484 commit 6022a3a

File tree

2 files changed

+48
-45
lines changed

2 files changed

+48
-45
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,15 +1125,10 @@ class ScalarEvolution {
11251125
// Not taken either exactly ConstantMaxNotTaken or zero times
11261126
bool MaxOrZero = false;
11271127

1128-
/// A set of predicate guards for this ExitLimit. The result is only valid
1129-
/// if all of the predicates in \c Predicates evaluate to 'true' at
1128+
/// A vector of predicate guards for this ExitLimit. The result is only
1129+
/// valid if all of the predicates in \c Predicates evaluate to 'true' at
11301130
/// run-time.
1131-
SmallPtrSet<const SCEVPredicate *, 4> Predicates;
1132-
1133-
void addPredicate(const SCEVPredicate *P) {
1134-
assert(!isa<SCEVUnionPredicate>(P) && "Only add leaf predicates here!");
1135-
Predicates.insert(P);
1136-
}
1131+
SmallVector<const SCEVPredicate *, 4> Predicates;
11371132

11381133
/// Construct either an exact exit limit from a constant, or an unknown
11391134
/// one from a SCEVCouldNotCompute. No other types of SCEVs are allowed
@@ -1142,12 +1137,11 @@ class ScalarEvolution {
11421137

11431138
ExitLimit(const SCEV *E, const SCEV *ConstantMaxNotTaken,
11441139
const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
1145-
ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *>
1146-
PredSetList = {});
1140+
ArrayRef<ArrayRef<const SCEVPredicate *>> PredLists = {});
11471141

11481142
ExitLimit(const SCEV *E, const SCEV *ConstantMaxNotTaken,
11491143
const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
1150-
const SmallPtrSetImpl<const SCEVPredicate *> &PredSet);
1144+
ArrayRef<const SCEVPredicate *> PredList);
11511145

11521146
/// Test whether this ExitLimit contains any computed information, or
11531147
/// whether it's all SCEVCouldNotCompute values.
@@ -1297,7 +1291,7 @@ class ScalarEvolution {
12971291
/// adding additional predicates to \p Preds as required.
12981292
const SCEVAddRecExpr *convertSCEVToAddRecWithPredicates(
12991293
const SCEV *S, const Loop *L,
1300-
SmallPtrSetImpl<const SCEVPredicate *> &Preds);
1294+
SmallVectorImpl<const SCEVPredicate *> &Preds);
13011295

13021296
/// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
13031297
/// constant, and std::nullopt if it isn't.
@@ -1489,12 +1483,13 @@ class ScalarEvolution {
14891483
const SCEV *ExactNotTaken;
14901484
const SCEV *ConstantMaxNotTaken;
14911485
const SCEV *SymbolicMaxNotTaken;
1492-
SmallPtrSet<const SCEVPredicate *, 4> Predicates;
1486+
SmallVector<const SCEVPredicate *, 4> Predicates;
14931487

1494-
explicit ExitNotTakenInfo(
1495-
PoisoningVH<BasicBlock> ExitingBlock, const SCEV *ExactNotTaken,
1496-
const SCEV *ConstantMaxNotTaken, const SCEV *SymbolicMaxNotTaken,
1497-
const SmallPtrSet<const SCEVPredicate *, 4> &Predicates)
1488+
explicit ExitNotTakenInfo(PoisoningVH<BasicBlock> ExitingBlock,
1489+
const SCEV *ExactNotTaken,
1490+
const SCEV *ConstantMaxNotTaken,
1491+
const SCEV *SymbolicMaxNotTaken,
1492+
ArrayRef<const SCEVPredicate *> Predicates)
14981493
: ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken),
14991494
ConstantMaxNotTaken(ConstantMaxNotTaken),
15001495
SymbolicMaxNotTaken(SymbolicMaxNotTaken), Predicates(Predicates) {}

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8693,12 +8693,12 @@ bool ScalarEvolution::BackedgeTakenInfo::isConstantMaxOrZero(
86938693
}
86948694

86958695
ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E)
8696-
: ExitLimit(E, E, E, false, {}) {}
8696+
: ExitLimit(E, E, E, false) {}
86978697

86988698
ScalarEvolution::ExitLimit::ExitLimit(
86998699
const SCEV *E, const SCEV *ConstantMaxNotTaken,
87008700
const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
8701-
ArrayRef<const SmallPtrSetImpl<const SCEVPredicate *> *> PredSetList)
8701+
ArrayRef<ArrayRef<const SCEVPredicate *>> PredLists)
87028702
: ExactNotTaken(E), ConstantMaxNotTaken(ConstantMaxNotTaken),
87038703
SymbolicMaxNotTaken(SymbolicMaxNotTaken), MaxOrZero(MaxOrZero) {
87048704
// If we prove the max count is zero, so is the symbolic bound. This happens
@@ -8721,22 +8721,29 @@ ScalarEvolution::ExitLimit::ExitLimit(
87218721
assert((isa<SCEVCouldNotCompute>(ConstantMaxNotTaken) ||
87228722
isa<SCEVConstant>(ConstantMaxNotTaken)) &&
87238723
"No point in having a non-constant max backedge taken count!");
8724-
for (const auto *PredSet : PredSetList)
8725-
for (const auto *P : *PredSet)
8726-
addPredicate(P);
8724+
SmallPtrSet<const SCEVPredicate *, 4> SeenPreds;
8725+
for (const auto PredList : PredLists)
8726+
for (const auto *P : PredList) {
8727+
if (SeenPreds.contains(P))
8728+
continue;
8729+
assert(!isa<SCEVUnionPredicate>(P) && "Only add leaf predicates here!");
8730+
SeenPreds.insert(P);
8731+
Predicates.push_back(P);
8732+
}
87278733
assert((isa<SCEVCouldNotCompute>(E) || !E->getType()->isPointerTy()) &&
87288734
"Backedge count should be int");
87298735
assert((isa<SCEVCouldNotCompute>(ConstantMaxNotTaken) ||
87308736
!ConstantMaxNotTaken->getType()->isPointerTy()) &&
87318737
"Max backedge count should be int");
87328738
}
87338739

8734-
ScalarEvolution::ExitLimit::ExitLimit(
8735-
const SCEV *E, const SCEV *ConstantMaxNotTaken,
8736-
const SCEV *SymbolicMaxNotTaken, bool MaxOrZero,
8737-
const SmallPtrSetImpl<const SCEVPredicate *> &PredSet)
8740+
ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E,
8741+
const SCEV *ConstantMaxNotTaken,
8742+
const SCEV *SymbolicMaxNotTaken,
8743+
bool MaxOrZero,
8744+
ArrayRef<const SCEVPredicate *> PredList)
87388745
: ExitLimit(E, ConstantMaxNotTaken, SymbolicMaxNotTaken, MaxOrZero,
8739-
{ &PredSet }) {}
8746+
ArrayRef({PredList})) {}
87408747

87418748
/// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each
87428749
/// computable exit into a persistent ExitNotTakenInfo array.
@@ -9098,7 +9105,7 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
90989105
SymbolicMaxBECount =
90999106
isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
91009107
return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, false,
9101-
{ &EL0.Predicates, &EL1.Predicates });
9108+
{ArrayRef(EL0.Predicates), ArrayRef(EL1.Predicates)});
91029109
}
91039110

91049111
ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimitFromICmp(
@@ -10131,7 +10138,7 @@ const SCEV *ScalarEvolution::stripInjectiveFunctions(const SCEV *S) const {
1013110138
/// If the equation does not have a solution, SCEVCouldNotCompute is returned.
1013210139
static const SCEV *
1013310140
SolveLinEquationWithOverflow(const APInt &A, const SCEV *B,
10134-
SmallPtrSetImpl<const SCEVPredicate *> *Predicates,
10141+
SmallVectorImpl<const SCEVPredicate *> *Predicates,
1013510142

1013610143
ScalarEvolution &SE) {
1013710144
uint32_t BW = A.getBitWidth();
@@ -10162,7 +10169,7 @@ SolveLinEquationWithOverflow(const APInt &A, const SCEV *B,
1016210169
// Avoid adding a predicate that is known to be false.
1016310170
if (SE.isKnownPredicate(CmpInst::ICMP_NE, URem, Zero))
1016410171
return SE.getCouldNotCompute();
10165-
Predicates->insert(SE.getEqualPredicate(URem, Zero));
10172+
Predicates->push_back(SE.getEqualPredicate(URem, Zero));
1016610173
}
1016710174
}
1016810175

@@ -10466,7 +10473,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
1046610473
// effectively V != 0. We know and take advantage of the fact that this
1046710474
// expression only being used in a comparison by zero context.
1046810475

10469-
SmallPtrSet<const SCEVPredicate *, 4> Predicates;
10476+
SmallVector<const SCEVPredicate *> Predicates;
1047010477
// If the value is a constant
1047110478
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
1047210479
// If the value is already zero, the branch will execute zero times.
@@ -12885,7 +12892,7 @@ ScalarEvolution::ExitLimit
1288512892
ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
1288612893
const Loop *L, bool IsSigned,
1288712894
bool ControlsOnlyExit, bool AllowPredicates) {
12888-
SmallPtrSet<const SCEVPredicate *, 4> Predicates;
12895+
SmallVector<const SCEVPredicate *> Predicates;
1288912896

1289012897
const SCEVAddRecExpr *IV = dyn_cast<SCEVAddRecExpr>(LHS);
1289112898
bool PredicatedIV = false;
@@ -13325,7 +13332,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
1332513332
ScalarEvolution::ExitLimit ScalarEvolution::howManyGreaterThans(
1332613333
const SCEV *LHS, const SCEV *RHS, const Loop *L, bool IsSigned,
1332713334
bool ControlsOnlyExit, bool AllowPredicates) {
13328-
SmallPtrSet<const SCEVPredicate *, 4> Predicates;
13335+
SmallVector<const SCEVPredicate *> Predicates;
1332913336
// We handle only IV > Invariant
1333013337
if (!isLoopInvariant(RHS, L))
1333113338
return getCouldNotCompute();
@@ -13695,7 +13702,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
1369513702
PrintSCEVWithTypeHint(OS, EC);
1369613703
if (isa<SCEVCouldNotCompute>(EC)) {
1369713704
// Retry with predicates.
13698-
SmallVector<const SCEVPredicate *, 4> Predicates;
13705+
SmallVector<const SCEVPredicate *> Predicates;
1369913706
EC = SE->getPredicatedExitCount(L, ExitingBlock, &Predicates);
1370013707
if (!isa<SCEVCouldNotCompute>(EC)) {
1370113708
OS << "\n predicated exit count for " << ExitingBlock->getName()
@@ -13747,7 +13754,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
1374713754
PrintSCEVWithTypeHint(OS, ExitBTC);
1374813755
if (isa<SCEVCouldNotCompute>(ExitBTC)) {
1374913756
// Retry with predicates.
13750-
SmallVector<const SCEVPredicate *, 4> Predicates;
13757+
SmallVector<const SCEVPredicate *> Predicates;
1375113758
ExitBTC = SE->getPredicatedExitCount(L, ExitingBlock, &Predicates,
1375213759
ScalarEvolution::SymbolicMaximum);
1375313760
if (!isa<SCEVCouldNotCompute>(ExitBTC)) {
@@ -14727,7 +14734,7 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
1472714734
/// If \p NewPreds is non-null, rewrite is free to add further predicates to
1472814735
/// \p NewPreds such that the result will be an AddRecExpr.
1472914736
static const SCEV *rewrite(const SCEV *S, const Loop *L, ScalarEvolution &SE,
14730-
SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
14737+
SmallVectorImpl<const SCEVPredicate *> *NewPreds,
1473114738
const SCEVPredicate *Pred) {
1473214739
SCEVPredicateRewriter Rewriter(L, SE, NewPreds, Pred);
1473314740
return Rewriter.visit(S);
@@ -14783,17 +14790,18 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
1478314790
}
1478414791

1478514792
private:
14786-
explicit SCEVPredicateRewriter(const Loop *L, ScalarEvolution &SE,
14787-
SmallPtrSetImpl<const SCEVPredicate *> *NewPreds,
14788-
const SCEVPredicate *Pred)
14793+
explicit SCEVPredicateRewriter(
14794+
const Loop *L, ScalarEvolution &SE,
14795+
SmallVectorImpl<const SCEVPredicate *> *NewPreds,
14796+
const SCEVPredicate *Pred)
1478914797
: SCEVRewriteVisitor(SE), NewPreds(NewPreds), Pred(Pred), L(L) {}
1479014798

1479114799
bool addOverflowAssumption(const SCEVPredicate *P) {
1479214800
if (!NewPreds) {
1479314801
// Check if we've already made this assumption.
1479414802
return Pred && Pred->implies(P);
1479514803
}
14796-
NewPreds->insert(P);
14804+
NewPreds->push_back(P);
1479714805
return true;
1479814806
}
1479914807

@@ -14829,7 +14837,7 @@ class SCEVPredicateRewriter : public SCEVRewriteVisitor<SCEVPredicateRewriter> {
1482914837
return PredicatedRewrite->first;
1483014838
}
1483114839

14832-
SmallPtrSetImpl<const SCEVPredicate *> *NewPreds;
14840+
SmallVectorImpl<const SCEVPredicate *> *NewPreds;
1483314841
const SCEVPredicate *Pred;
1483414842
const Loop *L;
1483514843
};
@@ -14844,8 +14852,8 @@ ScalarEvolution::rewriteUsingPredicate(const SCEV *S, const Loop *L,
1484414852

1484514853
const SCEVAddRecExpr *ScalarEvolution::convertSCEVToAddRecWithPredicates(
1484614854
const SCEV *S, const Loop *L,
14847-
SmallPtrSetImpl<const SCEVPredicate *> &Preds) {
14848-
SmallPtrSet<const SCEVPredicate *, 4> TransformPreds;
14855+
SmallVectorImpl<const SCEVPredicate *> &Preds) {
14856+
SmallVector<const SCEVPredicate *> TransformPreds;
1484914857
S = SCEVPredicateRewriter::rewrite(S, L, *this, &TransformPreds, nullptr);
1485014858
auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
1485114859

@@ -14854,7 +14862,7 @@ const SCEVAddRecExpr *ScalarEvolution::convertSCEVToAddRecWithPredicates(
1485414862

1485514863
// Since the transformation was successful, we can now transfer the SCEV
1485614864
// predicates.
14857-
Preds.insert(TransformPreds.begin(), TransformPreds.end());
14865+
Preds.append(TransformPreds.begin(), TransformPreds.end());
1485814866

1485914867
return AddRec;
1486014868
}
@@ -15101,7 +15109,7 @@ bool PredicatedScalarEvolution::hasNoOverflow(
1510115109

1510215110
const SCEVAddRecExpr *PredicatedScalarEvolution::getAsAddRec(Value *V) {
1510315111
const SCEV *Expr = this->getSCEV(V);
15104-
SmallPtrSet<const SCEVPredicate *, 4> NewPreds;
15112+
SmallVector<const SCEVPredicate *, 4> NewPreds;
1510515113
auto *New = SE.convertSCEVToAddRecWithPredicates(Expr, &L, NewPreds);
1510615114

1510715115
if (!New)

0 commit comments

Comments
 (0)