diff options
author | Max Kazantsev <max.kazantsev@azul.com> | 2017-08-03 08:41:30 +0000 |
---|---|---|
committer | Max Kazantsev <max.kazantsev@azul.com> | 2017-08-03 08:41:30 +0000 |
commit | 511c1a306c885f5947c676677cc831d700852e5d (patch) | |
tree | 7886fbc26c866067851efce64344976e6964a584 /lib/Analysis/ScalarEvolution.cpp | |
parent | daeea6f68d6d67204c89a1f6100b8e958a02aa5f (diff) |
[SCEV] Re-enable "Cache results of computeExitLimit"
The patch rL309080 was reverted because it did not clean up the cache on "forgetValue"
method call. This patch re-enables this change, adds the missing check and introduces
two new unit tests that make sure that the cache is cleaned properly.
Differential Revision: https://reviews.llvm.org/D36087
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309925 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index d5abccb8dbb..d3baf532045 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -6200,7 +6200,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // own when it gets to that point. if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) { eraseValueFromMap(It->first); - forgetMemoizedResults(Old); + forgetMemoizedResults(Old, false); } if (PHINode *PN = dyn_cast<PHINode>(I)) ConstantEvolutionLoopExitValue.erase(PN); @@ -6264,6 +6264,12 @@ void ScalarEvolution::forgetLoop(const Loop *L) { PushDefUseChildren(I, Worklist); } + for (auto I = ExitLimits.begin(); I != ExitLimits.end(); ++I) { + auto &Query = I->first; + if (Query.L == L) + ExitLimits.erase(I); + } + // Forget all contained loops too, to avoid dangling entries in the // ValuesAtScopes map. for (Loop *I : *L) @@ -6526,6 +6532,18 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L, ScalarEvolution::ExitLimit ScalarEvolution::computeExitLimit(const Loop *L, BasicBlock *ExitingBlock, bool AllowPredicates) { + ExitLimitQuery Query(L, ExitingBlock, AllowPredicates); + auto MaybeEL = ExitLimits.find(Query); + if (MaybeEL != ExitLimits.end()) + return MaybeEL->second; + ExitLimit EL = computeExitLimitImpl(L, ExitingBlock, AllowPredicates); + ExitLimits.insert({Query, EL}); + return EL; +} + +ScalarEvolution::ExitLimit +ScalarEvolution::computeExitLimitImpl(const Loop *L, BasicBlock *ExitingBlock, + bool AllowPredicates) { // Okay, we've chosen an exiting block. See what condition causes us to exit // at this block and remember the exit block and whether all other targets @@ -10408,6 +10426,7 @@ ScalarEvolution::ScalarEvolution(ScalarEvolution &&Arg) BackedgeTakenCounts(std::move(Arg.BackedgeTakenCounts)), PredicatedBackedgeTakenCounts( std::move(Arg.PredicatedBackedgeTakenCounts)), + ExitLimits(std::move(Arg.ExitLimits)), ConstantEvolutionLoopExitValue( std::move(Arg.ConstantEvolutionLoopExitValue)), ValuesAtScopes(std::move(Arg.ValuesAtScopes)), @@ -10810,7 +10829,16 @@ bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { return SCEVExprContains(S, [&](const SCEV *Expr) { return Expr == Op; }); } -void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { +bool ScalarEvolution::ExitLimit::hasOperand(const SCEV *S) const { + auto IsS = [&](const SCEV *X) { return S == X; }; + auto ContainsS = [&](const SCEV *X) { + return !isa<SCEVCouldNotCompute>(X) && SCEVExprContains(X, IsS); + }; + return ContainsS(ExactNotTaken) || ContainsS(MaxNotTaken); +} + +void +ScalarEvolution::forgetMemoizedResults(const SCEV *S, bool EraseExitLimit) { ValuesAtScopes.erase(S); LoopDispositions.erase(S); BlockDispositions.erase(S); @@ -10843,6 +10871,13 @@ void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { 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) + for (auto I = ExitLimits.begin(), E = ExitLimits.end(); I != E; ++I) + if (I->second.hasOperand(S)) + ExitLimits.erase(I); } void ScalarEvolution::verify() const { |