Index: include/llvm/Analysis/ScalarEvolutionExpressions.h =================================================================== --- include/llvm/Analysis/ScalarEvolutionExpressions.h +++ include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -473,6 +473,29 @@ } }; + template + class CachingSCEVVisitor : public SCEVVisitor { + private: + // Memoize the result of each visit so that we only compute once for + // the same input SCEV. This is to avoid redundant computations when + // a SCEV is referenced by multiple SCEVs. Without memoization, this + // visit algorithm would have exponential time complexity in the worst + // case, causing the compiler to hang on certain tests. + DenseMap Results; + + public: + RetVal visit(const SCEV *S) { + auto It = Results.find(S); + if (It != Results.end()) + return It->second; + + RetVal Visited = SCEVVisitor::visit(S); + auto Result = Results.try_emplace(S, Visited); + assert(Result.second && "Should insert a new entry"); + return Result.first->second; + } + }; + /// Visit all nodes in the expression tree using worklist traversal. /// /// Visitor implements: @@ -566,29 +589,13 @@ /// The result from each visit is cached, so it will return the same /// SCEV for the same input. template - class SCEVRewriteVisitor : public SCEVVisitor { + class SCEVRewriteVisitor : public CachingSCEVVisitor { protected: ScalarEvolution &SE; - // Memoize the result of each visit so that we only compute once for - // the same input SCEV. This is to avoid redundant computations when - // a SCEV is referenced by multiple SCEVs. Without memoization, this - // visit algorithm would have exponential time complexity in the worst - // case, causing the compiler to hang on certain tests. - DenseMap RewriteResults; public: SCEVRewriteVisitor(ScalarEvolution &SE) : SE(SE) {} - const SCEV *visit(const SCEV *S) { - auto It = RewriteResults.find(S); - if (It != RewriteResults.end()) - return It->second; - auto* Visited = SCEVVisitor::visit(S); - auto Result = RewriteResults.try_emplace(S, Visited); - assert(Result.second && "Should insert a new entry"); - return Result.first->second; - } - const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; }