Rewrite ScalarEvolution::hasOperand to use an explicit worklist instead

of recursion, to avoid excessive stack usage on deep expressions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156554 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman
2012-05-10 17:21:30 +00:00
parent e54874471c
commit ac84461e5a

View File

@@ -6860,43 +6860,58 @@ bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) {
} }
bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const {
switch (S->getSCEVType()) { SmallVector<const SCEV *, 8> Worklist;
case scConstant: Worklist.push_back(S);
return false; do {
case scTruncate: S = Worklist.pop_back_val();
case scZeroExtend:
case scSignExtend: { switch (S->getSCEVType()) {
const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S); case scConstant:
const SCEV *CastOp = Cast->getOperand(); break;
return Op == CastOp || hasOperand(CastOp, Op); case scTruncate:
} case scZeroExtend:
case scAddRecExpr: case scSignExtend: {
case scAddExpr: const SCEVCastExpr *Cast = cast<SCEVCastExpr>(S);
case scMulExpr: const SCEV *CastOp = Cast->getOperand();
case scUMaxExpr: if (Op == CastOp)
case scSMaxExpr: {
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
I != E; ++I) {
const SCEV *NAryOp = *I;
if (NAryOp == Op || hasOperand(NAryOp, Op))
return true; return true;
Worklist.push_back(CastOp);
break;
} }
return false; case scAddRecExpr:
} case scAddExpr:
case scUDivExpr: { case scMulExpr:
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S); case scUMaxExpr:
const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS(); case scSMaxExpr: {
return LHS == Op || hasOperand(LHS, Op) || const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
RHS == Op || hasOperand(RHS, Op); for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end();
} I != E; ++I) {
case scUnknown: const SCEV *NAryOp = *I;
return false; if (NAryOp == Op)
case scCouldNotCompute: return true;
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); Worklist.push_back(NAryOp);
default: }
llvm_unreachable("Unknown SCEV kind!"); break;
} }
case scUDivExpr: {
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS();
if (LHS == Op || RHS == Op)
return true;
Worklist.push_back(LHS);
Worklist.push_back(RHS);
break;
}
case scUnknown:
break;
case scCouldNotCompute:
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
default:
llvm_unreachable("Unknown SCEV kind!");
}
} while (!Worklist.empty());
return false;
} }
void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { void ScalarEvolution::forgetMemoizedResults(const SCEV *S) {