From 5f347a9bd1ba861c9f243b540449761b91c4692f Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 22 Nov 2013 12:11:02 +0000 Subject: [PATCH] [PM] Teach the analysis managers to pass themselves as arguments to the run methods of the analysis passes. Also generalizes and re-uses the SFINAE for transformation passes so that users can write an analysis pass and only accept an analysis manager if that is useful to their pass. This completes the plumbing to make an analysis manager available through every pass's run method if desired so that passes no longer need to be constructed around them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195451 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/PassManager.h | 66 ++++++++++++++++++++++++-------- lib/IR/PassManager.cpp | 4 +- unittests/IR/PassManagerTest.cpp | 2 +- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 3ec4f6c71fb..111d3736841 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -169,12 +169,13 @@ template struct PassConcept { /// \brief SFINAE metafunction for computing whether \c PassT has a run method /// accepting an \c AnalysisManagerT. -template +template class PassRunAcceptsAnalysisManager { typedef char SmallType; struct BigType { char a, b; }; - template + template struct Checker; template static SmallType f(Checker *); @@ -191,7 +192,7 @@ public: /// \c run method also accepts an \c AnalysisManagerT*, we pass it along. template ::Value> + IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value> struct PassModel; /// \brief Specialization of \c PassModel for passes that accept an analyis @@ -312,14 +313,16 @@ struct AnalysisResultModel struct AnalysisPassConcept { +template +struct AnalysisPassConcept { virtual ~AnalysisPassConcept() {} virtual AnalysisPassConcept *clone() = 0; /// \brief Method to run this analysis over a unit of IR. /// \returns The analysis result object to be queried by users, the caller /// takes ownership. - virtual AnalysisResultConcept *run(IRUnitT IR) = 0; + virtual AnalysisResultConcept *run(IRUnitT IR, + AnalysisManagerT *AM) = 0; }; /// \brief Wrapper to model the analysis pass concept. @@ -327,8 +330,17 @@ template struct AnalysisPassConcept { /// Can wrap any type which implements a suitable \c run method. The method /// must accept the IRUnitT as an argument and produce an object which can be /// wrapped in a \c AnalysisResultModel. -template -struct AnalysisPassModel : AnalysisPassConcept { +template ::Value > struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } @@ -339,7 +351,30 @@ struct AnalysisPassModel : AnalysisPassConcept { /// \brief The model delegates to the \c PassT::run method. /// /// The return is wrapped in an \c AnalysisResultModel. - virtual ResultModelT *run(IRUnitT IR) { + virtual ResultModelT *run(IRUnitT IR, AnalysisManagerT *AM) { + return new ResultModelT(Pass.run(IR, AM)); + } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + virtual ResultModelT *run(IRUnitT IR, AnalysisManagerT *) { return new ResultModelT(Pass.run(IR)); } @@ -436,7 +471,8 @@ public: assert(!ModuleAnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); ModuleAnalysisPasses[PassT::ID()] = - new detail::AnalysisPassModel(llvm_move(Pass)); + new detail::AnalysisPassModel( + llvm_move(Pass)); } /// \brief Invalidate a specific analysis pass for an IR module. @@ -463,8 +499,8 @@ private: void invalidateImpl(void *PassID, Module *M); /// \brief Map type from module analysis pass ID to pass concept pointer. - typedef DenseMap > > + typedef DenseMap > > ModuleAnalysisPassMapT; /// \brief Collection of module analysis passes, indexed by ID. @@ -511,8 +547,8 @@ public: template void registerPass(PassT Pass) { assert(!FunctionAnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - FunctionAnalysisPasses[PassT::ID()] = - new detail::AnalysisPassModel(llvm_move(Pass)); + FunctionAnalysisPasses[PassT::ID()] = new detail::AnalysisPassModel< + Function *, FunctionAnalysisManager, PassT>(llvm_move(Pass)); } /// \brief Invalidate a specific analysis pass for an IR module. @@ -551,8 +587,8 @@ private: void invalidateImpl(void *PassID, Function *F); /// \brief Map type from function analysis pass ID to pass concept pointer. - typedef DenseMap > > + typedef DenseMap > > FunctionAnalysisPassMapT; /// \brief Collection of function analysis passes, indexed by ID. diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index f2d0cd99e61..fe16adcaeb3 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -47,7 +47,7 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) { ModuleAnalysisPasses.find(PassID); assert(PI != ModuleAnalysisPasses.end() && "Analysis passes must be registered prior to being queried!"); - RI->second = PI->second->run(M); + RI->second = PI->second->run(M, this); } return *RI->second; @@ -115,7 +115,7 @@ FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) { assert(PI != FunctionAnalysisPasses.end() && "Analysis passes must be registered prior to being queried!"); FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F]; - ResultList.push_back(std::make_pair(PassID, PI->second->run(F))); + ResultList.push_back(std::make_pair(PassID, PI->second->run(F, this))); RI->second = llvm::prior(ResultList.end()); } diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index b0d4cbe0318..8115da862dc 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -32,7 +32,7 @@ public: TestAnalysisPass(int &Runs) : Runs(Runs) {} /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F) { + Result run(Function *F, FunctionAnalysisManager *AM) { ++Runs; int Count = 0; for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI)