diff options
author | Dan Gohman <gohman@apple.com> | 2010-11-18 00:34:22 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2010-11-18 00:34:22 +0000 |
commit | 9c9fcfc719158a46cb2e41b66d7dc1a63cd48d74 (patch) | |
tree | 0cb0e06e1130bcdd21c88cffb2b516e27bb31a56 | |
parent | 18333616cd824bee3abecd607d3aa432b5cf507d (diff) | |
download | external_llvm-9c9fcfc719158a46cb2e41b66d7dc1a63cd48d74.zip external_llvm-9c9fcfc719158a46cb2e41b66d7dc1a63cd48d74.tar.gz external_llvm-9c9fcfc719158a46cb2e41b66d7dc1a63cd48d74.tar.bz2 |
Introduce memoization for ScalarEvolution dominates and properlyDominates
queries, and SCEVExpander getRelevantLoop queries.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119595 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Analysis/ScalarEvolution.h | 23 | ||||
-rw-r--r-- | include/llvm/Analysis/ScalarEvolutionExpander.h | 6 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 114 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolutionExpander.cpp | 43 |
4 files changed, 110 insertions, 76 deletions
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 4ae0f5a..94da1ec 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -151,6 +151,14 @@ namespace llvm { LoopComputable ///< The SCEV varies predictably with the loop. }; + /// BlockDisposition - An enum describing the relationship between a + /// SCEV and a basic block. + enum BlockDisposition { + DoesNotDominateBlock, ///< The SCEV does not dominate the block. + DominatesBlock, ///< The SCEV dominates the block. + ProperlyDominatesBlock ///< The SCEV properly dominates the block. + }; + private: /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be /// notified whenever a Value is deleted. @@ -246,6 +254,13 @@ namespace llvm { /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); + /// BlockDispositions - Memoized computeBlockDisposition results. + std::map<const SCEV *, + std::map<const BasicBlock *, BlockDisposition> > BlockDispositions; + + /// computeBlockDisposition - Compute a BlockDisposition value. + BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); + /// UnsignedRanges - Memoized results from getUnsignedRange DenseMap<const SCEV *, ConstantRange> UnsignedRanges; @@ -697,13 +712,17 @@ namespace llvm { /// to compute the value of the expression at any particular loop iteration. bool hasComputableLoopEvolution(const SCEV *S, const Loop *L); + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given block. + BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB); + /// dominates - Return true if elements that makes up the given SCEV /// dominate the specified basic block. - bool dominates(const SCEV *S, BasicBlock *BB) const; + bool dominates(const SCEV *S, const BasicBlock *BB); /// properlyDominates - Return true if elements that makes up the given SCEV /// properly dominate the specified basic block. - bool properlyDominates(const SCEV *S, BasicBlock *BB) const; + bool properlyDominates(const SCEV *S, const BasicBlock *BB); /// hasOperand - Test whether the given SCEV has Op as a direct or /// indirect operand. diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 4b02f82..39d378e 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -35,6 +35,9 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; + /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + DenseMap<const SCEV *, const Loop *> RelevantLoops; + /// PostIncLoops - Addrecs referring to any of the given loops are expanded /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode /// returns the add instruction that adds one to the phi for {0,+,1}<L>, @@ -168,6 +171,9 @@ namespace llvm { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } + /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + const Loop *getRelevantLoop(const SCEV *); + Value *visitConstant(const SCEVConstant *S) { return S->getValue(); } diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 777c1c8..04ec67f 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -5790,6 +5790,7 @@ void ScalarEvolution::releaseMemory() { ConstantEvolutionLoopExitValue.clear(); ValuesAtScopes.clear(); LoopDispositions.clear(); + BlockDispositions.clear(); UnsignedRanges.clear(); SignedRanges.clear(); UniqueSCEVs.clear(); @@ -5990,64 +5991,35 @@ bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) { return getLoopDisposition(S, L) == LoopComputable; } -bool ScalarEvolution::dominates(const SCEV *S, BasicBlock *BB) const { - switch (S->getSCEVType()) { - case scConstant: - return true; - case scTruncate: - case scZeroExtend: - case scSignExtend: - return dominates(cast<SCEVCastExpr>(S)->getOperand(), BB); - case scAddRecExpr: { - const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S); - if (!DT->dominates(AR->getLoop()->getHeader(), BB)) - return false; - } - // FALL THROUGH into SCEVNAryExpr handling. - case scAddExpr: - case scMulExpr: - case scUMaxExpr: - case scSMaxExpr: { - const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S); - for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); - I != E; ++I) - if (!dominates(*I, BB)) - return false; - return true; - } - case scUDivExpr: { - const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S); - return dominates(UDiv->getLHS(), BB) && dominates(UDiv->getRHS(), BB); - } - case scUnknown: - if (Instruction *I = - dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue())) - return DT->dominates(I->getParent(), BB); - return true; - case scCouldNotCompute: - llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); - return false; - default: break; - } - llvm_unreachable("Unknown SCEV kind!"); - return false; +ScalarEvolution::BlockDisposition +ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) { + std::map<const BasicBlock *, BlockDisposition> &Values = BlockDispositions[S]; + std::pair<std::map<const BasicBlock *, BlockDisposition>::iterator, bool> + Pair = Values.insert(std::make_pair(BB, DoesNotDominateBlock)); + if (!Pair.second) + return Pair.first->second; + + BlockDisposition D = computeBlockDisposition(S, BB); + return BlockDispositions[S][BB] = D; } -bool ScalarEvolution::properlyDominates(const SCEV *S, BasicBlock *BB) const { +ScalarEvolution::BlockDisposition +ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) { switch (S->getSCEVType()) { case scConstant: - return true; + return ProperlyDominatesBlock; case scTruncate: case scZeroExtend: case scSignExtend: - return properlyDominates(cast<SCEVCastExpr>(S)->getOperand(), BB); + return getBlockDisposition(cast<SCEVCastExpr>(S)->getOperand(), BB); case scAddRecExpr: { // This uses a "dominates" query instead of "properly dominates" query - // because the instruction which produces the addrec's value is a PHI, and - // a PHI effectively properly dominates its entire containing block. + // to test for proper dominance too, because the instruction which + // produces the addrec's value is a PHI, and a PHI effectively properly + // dominates its entire containing block. const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S); if (!DT->dominates(AR->getLoop()->getHeader(), BB)) - return false; + return DoesNotDominateBlock; } // FALL THROUGH into SCEVNAryExpr handling. case scAddExpr: @@ -6055,29 +6027,54 @@ bool ScalarEvolution::properlyDominates(const SCEV *S, BasicBlock *BB) const { case scUMaxExpr: case scSMaxExpr: { const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S); + bool Proper = true; for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); - I != E; ++I) - if (!properlyDominates(*I, BB)) - return false; - return true; + I != E; ++I) { + BlockDisposition D = getBlockDisposition(*I, BB); + if (D == DoesNotDominateBlock) + return DoesNotDominateBlock; + if (D == DominatesBlock) + Proper = false; + } + return Proper ? ProperlyDominatesBlock : DominatesBlock; } case scUDivExpr: { const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S); - return properlyDominates(UDiv->getLHS(), BB) && - properlyDominates(UDiv->getRHS(), BB); + const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS(); + BlockDisposition LD = getBlockDisposition(LHS, BB); + if (LD == DoesNotDominateBlock) + return DoesNotDominateBlock; + BlockDisposition RD = getBlockDisposition(RHS, BB); + if (RD == DoesNotDominateBlock) + return DoesNotDominateBlock; + return (LD == ProperlyDominatesBlock && RD == ProperlyDominatesBlock) ? + ProperlyDominatesBlock : DominatesBlock; } case scUnknown: if (Instruction *I = - dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue())) - return DT->properlyDominates(I->getParent(), BB); - return true; + dyn_cast<Instruction>(cast<SCEVUnknown>(S)->getValue())) { + if (I->getParent() == BB) + return DominatesBlock; + if (DT->properlyDominates(I->getParent(), BB)) + return ProperlyDominatesBlock; + return DoesNotDominateBlock; + } + return ProperlyDominatesBlock; case scCouldNotCompute: llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); - return false; + return DoesNotDominateBlock; default: break; } llvm_unreachable("Unknown SCEV kind!"); - return false; + return DoesNotDominateBlock; +} + +bool ScalarEvolution::dominates(const SCEV *S, const BasicBlock *BB) { + return getBlockDisposition(S, BB) >= DominatesBlock; +} + +bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) { + return getBlockDisposition(S, BB) == ProperlyDominatesBlock; } bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { @@ -6125,6 +6122,7 @@ bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { ValuesAtScopes.erase(S); LoopDispositions.erase(S); + BlockDispositions.erase(S); UnsignedRanges.erase(S); SignedRanges.erase(S); } diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index d9eb8c1..b7c110f 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -608,15 +608,22 @@ static const Loop *PickMostRelevantLoop(const Loop *A, const Loop *B, return A; // Arbitrarily break the tie. } -/// GetRelevantLoop - Get the most relevant loop associated with the given +/// getRelevantLoop - Get the most relevant loop associated with the given /// expression, according to PickMostRelevantLoop. -static const Loop *GetRelevantLoop(const SCEV *S, LoopInfo &LI, - DominatorTree &DT) { +const Loop *SCEVExpander::getRelevantLoop(const SCEV *S) { + // Test whether we've already computed the most relevant loop for this SCEV. + std::pair<DenseMap<const SCEV *, const Loop *>::iterator, bool> Pair = + RelevantLoops.insert(std::make_pair(S, static_cast<const Loop *>(0))); + if (!Pair.second) + return Pair.first->second; + if (isa<SCEVConstant>(S)) + // A constant has no relevant loops. return 0; if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) { if (const Instruction *I = dyn_cast<Instruction>(U->getValue())) - return LI.getLoopFor(I->getParent()); + return Pair.first->second = SE.LI->getLoopFor(I->getParent()); + // A non-instruction has no relevant loops. return 0; } if (const SCEVNAryExpr *N = dyn_cast<SCEVNAryExpr>(S)) { @@ -625,16 +632,22 @@ static const Loop *GetRelevantLoop(const SCEV *S, LoopInfo &LI, L = AR->getLoop(); for (SCEVNAryExpr::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) - L = PickMostRelevantLoop(L, GetRelevantLoop(*I, LI, DT), DT); - return L; + L = PickMostRelevantLoop(L, getRelevantLoop(*I), *SE.DT); + return RelevantLoops[N] = L; + } + if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S)) { + const Loop *Result = getRelevantLoop(C->getOperand()); + return RelevantLoops[C] = Result; + } + if (const SCEVUDivExpr *D = dyn_cast<SCEVUDivExpr>(S)) { + const Loop *Result = + PickMostRelevantLoop(getRelevantLoop(D->getLHS()), + getRelevantLoop(D->getRHS()), + *SE.DT); + return RelevantLoops[D] = Result; } - if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S)) - return GetRelevantLoop(C->getOperand(), LI, DT); - if (const SCEVUDivExpr *D = dyn_cast<SCEVUDivExpr>(S)) - return PickMostRelevantLoop(GetRelevantLoop(D->getLHS(), LI, DT), - GetRelevantLoop(D->getRHS(), LI, DT), - DT); llvm_unreachable("Unexpected SCEV type!"); + return 0; } namespace { @@ -682,8 +695,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops; for (std::reverse_iterator<SCEVAddExpr::op_iterator> I(S->op_end()), E(S->op_begin()); I != E; ++I) - OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT), - *I)); + OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I)); // Sort by loop. Use a stable sort so that constants follow non-constants and // pointer operands precede non-pointer operands. @@ -752,8 +764,7 @@ Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops; for (std::reverse_iterator<SCEVMulExpr::op_iterator> I(S->op_end()), E(S->op_begin()); I != E; ++I) - OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT), - *I)); + OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I)); // Sort by loop. Use a stable sort so that constants follow non-constants. std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT)); |