Skip to content

Commit 39e5036

Browse files
authored
[SCEV] Add predicated version of getSymbolicMaxBackedgeTakenCount. (#93498)
This patch adds a predicated version of getSymbolicMaxBackedgeTakenCount. The intended use for this is loop access analysis for loops with uncountable exits. When analyzing dependences and computing runtime checks, we need the smallest upper bound on the number of iterations. In terms of memory safety, it shouldn't matter if any uncomputable exits leave the loop, as long as we prove that there are no dependences given the minimum of the countable exits. The same should apply also for generating runtime checks. PR: #93498
1 parent 4486fcb commit 39e5036

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

llvm/include/llvm/Analysis/ScalarEvolution.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,13 @@ class ScalarEvolution {
912912
return getBackedgeTakenCount(L, SymbolicMaximum);
913913
}
914914

915+
/// Similar to getSymbolicMaxBackedgeTakenCount, except it will add a set of
916+
/// SCEV predicates to Predicates that are required to be true in order for
917+
/// the answer to be correct. Predicates can be checked with run-time
918+
/// checks and can be used to perform loop versioning.
919+
const SCEV *getPredicatedSymbolicMaxBackedgeTakenCount(
920+
const Loop *L, SmallVector<const SCEVPredicate *, 4> &Predicates);
921+
915922
/// Return true if the backedge taken count is either the value returned by
916923
/// getConstantMaxBackedgeTakenCount or zero.
917924
bool isBackedgeTakenCountMaxOrZero(const Loop *L);
@@ -1549,7 +1556,9 @@ class ScalarEvolution {
15491556
ScalarEvolution *SE) const;
15501557

15511558
/// Get the symbolic max backedge taken count for the loop.
1552-
const SCEV *getSymbolicMax(const Loop *L, ScalarEvolution *SE);
1559+
const SCEV *
1560+
getSymbolicMax(const Loop *L, ScalarEvolution *SE,
1561+
SmallVector<const SCEVPredicate *, 4> *Predicates = nullptr);
15531562

15541563
/// Get the symbolic max backedge taken count for the particular loop exit.
15551564
const SCEV *getSymbolicMax(const BasicBlock *ExitingBlock,
@@ -1746,7 +1755,7 @@ class ScalarEvolution {
17461755

17471756
/// Similar to getBackedgeTakenInfo, but will add predicates as required
17481757
/// with the purpose of returning complete information.
1749-
const BackedgeTakenInfo &getPredicatedBackedgeTakenInfo(const Loop *L);
1758+
BackedgeTakenInfo &getPredicatedBackedgeTakenInfo(const Loop *L);
17501759

17511760
/// Compute the number of times the specified loop will iterate.
17521761
/// If AllowPredicates is set, we will create new SCEV predicates as
@@ -2311,6 +2320,9 @@ class PredicatedScalarEvolution {
23112320
/// Get the (predicated) backedge count for the analyzed loop.
23122321
const SCEV *getBackedgeTakenCount();
23132322

2323+
/// Get the (predicated) symbolic max backedge count for the analyzed loop.
2324+
const SCEV *getSymbolicMaxBackedgeTakenCount();
2325+
23142326
/// Adds a new predicate.
23152327
void addPredicate(const SCEVPredicate &Pred);
23162328

@@ -2379,6 +2391,9 @@ class PredicatedScalarEvolution {
23792391

23802392
/// The backedge taken count.
23812393
const SCEV *BackedgeCount = nullptr;
2394+
2395+
/// The symbolic backedge taken count.
2396+
const SCEV *SymbolicMaxBackedgeCount = nullptr;
23822397
};
23832398

23842399
template <> struct DenseMapInfo<ScalarEvolution::FoldID> {

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8295,6 +8295,11 @@ const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L,
82958295
llvm_unreachable("Invalid ExitCountKind!");
82968296
}
82978297

8298+
const SCEV *ScalarEvolution::getPredicatedSymbolicMaxBackedgeTakenCount(
8299+
const Loop *L, SmallVector<const SCEVPredicate *, 4> &Preds) {
8300+
return getPredicatedBackedgeTakenInfo(L).getSymbolicMax(L, this, &Preds);
8301+
}
8302+
82988303
bool ScalarEvolution::isBackedgeTakenCountMaxOrZero(const Loop *L) {
82998304
return getBackedgeTakenInfo(L).isConstantMaxOrZero(this);
83008305
}
@@ -8311,7 +8316,7 @@ static void PushLoopPHIs(const Loop *L,
83118316
Worklist.push_back(&PN);
83128317
}
83138318

8314-
const ScalarEvolution::BackedgeTakenInfo &
8319+
ScalarEvolution::BackedgeTakenInfo &
83158320
ScalarEvolution::getPredicatedBackedgeTakenInfo(const Loop *L) {
83168321
auto &BTI = getBackedgeTakenInfo(L);
83178322
if (BTI.hasFullInfo())
@@ -8644,9 +8649,9 @@ ScalarEvolution::BackedgeTakenInfo::getConstantMax(ScalarEvolution *SE) const {
86448649
return getConstantMax();
86458650
}
86468651

8647-
const SCEV *
8648-
ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(const Loop *L,
8649-
ScalarEvolution *SE) {
8652+
const SCEV *ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(
8653+
const Loop *L, ScalarEvolution *SE,
8654+
SmallVector<const SCEVPredicate *, 4> *Predicates) {
86508655
if (!SymbolicMax) {
86518656
// Form an expression for the maximum exit count possible for this loop. We
86528657
// merge the max and exact information to approximate a version of
@@ -8661,6 +8666,12 @@ ScalarEvolution::BackedgeTakenInfo::getSymbolicMax(const Loop *L,
86618666
"We should only have known counts for exiting blocks that "
86628667
"dominate latch!");
86638668
ExitCounts.push_back(ExitCount);
8669+
if (Predicates)
8670+
for (const auto *P : ENT.Predicates)
8671+
Predicates->push_back(P);
8672+
8673+
assert((Predicates || ENT.hasAlwaysTruePredicate()) &&
8674+
"Predicate should be always true!");
86648675
}
86658676
}
86668677
if (ExitCounts.empty())
@@ -13609,6 +13620,24 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
1360913620
P->print(OS, 4);
1361013621
}
1361113622

13623+
Preds.clear();
13624+
auto *PredSymbolicMax =
13625+
SE->getPredicatedSymbolicMaxBackedgeTakenCount(L, Preds);
13626+
if (SymbolicBTC != PredSymbolicMax) {
13627+
OS << "Loop ";
13628+
L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
13629+
OS << ": ";
13630+
if (!isa<SCEVCouldNotCompute>(PredSymbolicMax)) {
13631+
OS << "Predicated symbolic max backedge-taken count is ";
13632+
PrintSCEVWithTypeHint(OS, PredSymbolicMax);
13633+
} else
13634+
OS << "Unpredictable predicated symbolic max backedge-taken count.";
13635+
OS << "\n";
13636+
OS << " Predicates:\n";
13637+
for (const auto *P : Preds)
13638+
P->print(OS, 4);
13639+
}
13640+
1361213641
if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
1361313642
OS << "Loop ";
1361413643
L->getHeader()->printAsOperand(OS, /*PrintType=*/false);
@@ -14822,6 +14851,17 @@ const SCEV *PredicatedScalarEvolution::getBackedgeTakenCount() {
1482214851
return BackedgeCount;
1482314852
}
1482414853

14854+
const SCEV *PredicatedScalarEvolution::getSymbolicMaxBackedgeTakenCount() {
14855+
if (!SymbolicMaxBackedgeCount) {
14856+
SmallVector<const SCEVPredicate *, 4> Preds;
14857+
SymbolicMaxBackedgeCount =
14858+
SE.getPredicatedSymbolicMaxBackedgeTakenCount(&L, Preds);
14859+
for (const auto *P : Preds)
14860+
addPredicate(*P);
14861+
}
14862+
return SymbolicMaxBackedgeCount;
14863+
}
14864+
1482514865
void PredicatedScalarEvolution::addPredicate(const SCEVPredicate &Pred) {
1482614866
if (Preds->implies(&Pred))
1482714867
return;

llvm/test/Analysis/ScalarEvolution/predicated-symbolic-max-backedge-taken-count.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ define void @test1(i64 %x, ptr %a, ptr %b) {
1212
; CHECK-NEXT: Loop %header: Unpredictable symbolic max backedge-taken count.
1313
; CHECK-NEXT: symbolic max exit count for header: ***COULDNOTCOMPUTE***
1414
; CHECK-NEXT: symbolic max exit count for latch: ***COULDNOTCOMPUTE***
15+
; CHECK-NEXT: Loop %header: Predicated symbolic max backedge-taken count is (-1 + (1 umax %x))
16+
; CHECK-NEXT: Predicates:
17+
; CHECK-NEXT: {1,+,1}<%header> Added Flags: <nusw>
1518
;
1619
entry:
1720
br label %header
@@ -52,6 +55,9 @@ define void @test2(i64 %x, ptr %a) {
5255
; CHECK-NEXT: Loop %header: Unpredictable symbolic max backedge-taken count.
5356
; CHECK-NEXT: symbolic max exit count for header: ***COULDNOTCOMPUTE***
5457
; CHECK-NEXT: symbolic max exit count for latch: ***COULDNOTCOMPUTE***
58+
; CHECK-NEXT: Loop %header: Predicated symbolic max backedge-taken count is (-1 + (1 umax %x))
59+
; CHECK-NEXT: Predicates:
60+
; CHECK-NEXT: {1,+,1}<%header> Added Flags: <nusw>
5561
;
5662
entry:
5763
br label %header

0 commit comments

Comments
 (0)