diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2017-10-13 17:13:44 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2017-10-13 17:13:44 +0000 |
commit | c70a7a02ea091d8430b36e1258597483f68897a8 (patch) | |
tree | 296e482dc4be87536ca9eb788eee2453c6d7d0a6 /llvm/lib | |
parent | 7ccaff7db01464a88f4bf550c7928e7754fed00c (diff) | |
download | bcm5719-llvm-c70a7a02ea091d8430b36e1258597483f68897a8.tar.gz bcm5719-llvm-c70a7a02ea091d8430b36e1258597483f68897a8.zip |
[SCEV] Maintain and use a loop->loop invalidation dependency
Summary:
This change uses the loop use list added in the previous change to remember the
loops that appear in the trip count expressions of other loops; and uses it in
forgetLoop. This lets us not scan every loop in the function on a forgetLoop
call.
With this change we no longer invalidate clear out backedge taken counts on
forgetValue. I think this is fine -- the contract is that SCEV users must call
forgetLoop(L) if their change to the IR could have changed the trip count of L;
solely calling forgetValue on a value feeding into the backedge condition of L
is not enough. Moreover, I don't think we can strengthen forgetValue to be
sufficient for invalidating trip counts without significantly re-architecting
SCEV. For instance, if we have the loop:
I = *Ptr;
E = I + 10;
do {
// ...
} while (++I != E);
then the backedge taken count of the loop is 9, and it has no reference to
either I or E, i.e. there is no way in SCEV today to re-discover the dependency
of the loop's trip count on E or I. So a SCEV client cannot change E to (say)
"I + 20", call forgetValue(E) and expect the loop's trip count to be updated.
Reviewers: atrick, sunfish, mkazantsev
Subscribers: mcrosier, llvm-commits
Differential Revision: https://reviews.llvm.org/D38435
llvm-svn: 315713
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 80 |
1 files changed, 49 insertions, 31 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index a9f404f3dff..f7d4e5191ee 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6293,6 +6293,7 @@ ScalarEvolution::getPredicatedBackedgeTakenInfo(const Loop *L) { BackedgeTakenInfo Result = computeBackedgeTakenCount(L, /*AllowPredicates=*/true); + addToLoopUseLists(Result, L); return PredicatedBackedgeTakenCounts.find(L)->second = std::move(Result); } @@ -6368,6 +6369,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // recusive call to getBackedgeTakenInfo (on a different // loop), which would invalidate the iterator computed // earlier. + addToLoopUseLists(Result, L); return BackedgeTakenCounts.find(L)->second = std::move(Result); } @@ -6405,8 +6407,14 @@ void ScalarEvolution::forgetLoop(const Loop *L) { auto LoopUsersItr = LoopUsers.find(CurrL); if (LoopUsersItr != LoopUsers.end()) { - for (auto *S : LoopUsersItr->second) - forgetMemoizedResults(S); + for (auto LoopOrSCEV : LoopUsersItr->second) { + if (auto *S = LoopOrSCEV.dyn_cast<const SCEV *>()) + forgetMemoizedResults(S); + else { + BackedgeTakenCounts.erase(LoopOrSCEV.get<const Loop *>()); + PredicatedBackedgeTakenCounts.erase(LoopOrSCEV.get<const Loop *>()); + } + } LoopUsers.erase(LoopUsersItr); } @@ -6551,6 +6559,34 @@ bool ScalarEvolution::BackedgeTakenInfo::hasOperand(const SCEV *S, return false; } +static void findUsedLoopsInSCEVExpr(const SCEV *S, + SmallPtrSetImpl<const Loop *> &Result) { + struct FindUsedLoops { + SmallPtrSetImpl<const Loop *> &LoopsUsed; + FindUsedLoops(SmallPtrSetImpl<const Loop *> &LoopsUsed) + : LoopsUsed(LoopsUsed) {} + bool follow(const SCEV *S) { + if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) + LoopsUsed.insert(AR->getLoop()); + return true; + } + + bool isDone() const { return false; } + }; + FindUsedLoops F(Result); + SCEVTraversal<FindUsedLoops>(F).visitAll(S); +} + +void ScalarEvolution::BackedgeTakenInfo::findUsedLoops( + ScalarEvolution &SE, SmallPtrSetImpl<const Loop *> &Result) const { + if (auto *S = getMax()) + if (S != SE.getCouldNotCompute()) + findUsedLoopsInSCEVExpr(S, Result); + for (auto &ENT : ExitNotTaken) + if (ENT.ExactNotTaken != SE.getCouldNotCompute()) + findUsedLoopsInSCEVExpr(ENT.ExactNotTaken, Result); +} + ScalarEvolution::ExitLimit::ExitLimit(const SCEV *E) : ExactNotTaken(E), MaxNotTaken(E) { assert((isa<SCEVCouldNotCompute>(MaxNotTaken) || @@ -11034,21 +11070,6 @@ ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) { ++I; } - auto RemoveSCEVFromBackedgeMap = - [S, this](DenseMap<const Loop *, BackedgeTakenInfo> &Map) { - for (auto I = Map.begin(), E = Map.end(); I != E;) { - BackedgeTakenInfo &BEInfo = I->second; - if (BEInfo.hasOperand(S, this)) { - BEInfo.clear(); - Map.erase(I++); - } else - ++I; - } - }; - - RemoveSCEVFromBackedgeMap(BackedgeTakenCounts); - RemoveSCEVFromBackedgeMap(PredicatedBackedgeTakenCounts); - // TODO: There is a suspicion that we only need to do it when there is a // SCEVUnknown somewhere inside S. Need to check this. if (EraseExitLimit) @@ -11058,22 +11079,19 @@ ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) { } void ScalarEvolution::addToLoopUseLists(const SCEV *S) { - struct FindUsedLoops { - SmallPtrSet<const Loop *, 8> LoopsUsed; - bool follow(const SCEV *S) { - if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) - LoopsUsed.insert(AR->getLoop()); - return true; - } - - bool isDone() const { return false; } - }; + SmallPtrSet<const Loop *, 8> LoopsUsed; + findUsedLoopsInSCEVExpr(S, LoopsUsed); + for (auto *L : LoopsUsed) + LoopUsers[L].push_back({S}); +} - FindUsedLoops F; - SCEVTraversal<FindUsedLoops>(F).visitAll(S); +void ScalarEvolution::addToLoopUseLists( + const ScalarEvolution::BackedgeTakenInfo &BTI, const Loop *L) { + SmallPtrSet<const Loop *, 8> LoopsUsed; + BTI.findUsedLoops(*this, LoopsUsed); - for (auto *L : F.LoopsUsed) - LoopUsers[L].push_back(S); + for (auto *UsedL : LoopsUsed) + LoopUsers[UsedL].push_back({L}); } void ScalarEvolution::verify() const { |