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 | 8ea83d81e017864d068c7ff53841bc0b0a76d414 (patch) | |
tree | 1c393a490b087d5575674322c0e69cfa76648519 /llvm/lib/Analysis | |
parent | ef6c8da50fac204fe9dca3061cd17ac383504974 (diff) | |
download | bcm5719-llvm-8ea83d81e017864d068c7ff53841bc0b0a76d414.tar.gz bcm5719-llvm-8ea83d81e017864d068c7ff53841bc0b0a76d414.zip |
Introduce memoization for ScalarEvolution dominates and properlyDominates
queries, and SCEVExpander getRelevantLoop queries.
llvm-svn: 119595
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 114 | ||||
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolutionExpander.cpp | 43 |
2 files changed, 83 insertions, 74 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 777c1c8ab66..04ec67f5b39 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/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/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/llvm/lib/Analysis/ScalarEvolutionExpander.cpp index d9eb8c1ca65..b7c110f28cf 100644 --- a/llvm/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/llvm/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)); |