diff options
| -rw-r--r-- | llvm/include/llvm/IR/PassManager.h | 218 | ||||
| -rw-r--r-- | llvm/lib/IR/PassManager.cpp | 91 |
2 files changed, 143 insertions, 166 deletions
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 3c9414986e6..ddb9ea8f7f9 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -439,23 +439,43 @@ private: std::vector<polymorphic_ptr<FunctionPassConcept> > Passes; }; -/// \brief A module analysis pass manager with lazy running and caching of -/// results. -class ModuleAnalysisManager { -public: - ModuleAnalysisManager() {} +namespace detail { + +/// \brief A CRTP base used to implement analysis managers. +/// +/// This class template serves as the boiler plate of an analysis manager. Any +/// analysis manager can be implemented on top of this base class. Any +/// implementation will be required to provide specific hooks: +/// +/// - getResultImpl +/// - getCachedResultImpl +/// - invalidateImpl +/// +/// The details of the call pattern are within. +template <typename DerivedT, typename IRUnitT> +class AnalysisManagerBase { + DerivedT *derived_this() { return static_cast<DerivedT *>(this); } + const DerivedT *derived_this() const { return static_cast<const DerivedT *>(this); } + +protected: + typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; + typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT; + // FIXME: Provide template aliases for the models when we're using C++11 in + // a mode supporting them. + +public: /// \brief Get the result of an analysis pass for this module. /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template <typename PassT> const typename PassT::Result &getResult(Module *M) { - assert(ModuleAnalysisPasses.count(PassT::ID()) && + template <typename PassT> const typename PassT::Result &getResult(IRUnitT IR) { + assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); - const detail::AnalysisResultConcept<Module *> &ResultConcept = - getResultImpl(PassT::ID(), M); - typedef detail::AnalysisResultModel<Module *, PassT, typename PassT::Result> + const ResultConceptT &ResultConcept = + derived_this()->getResultImpl(PassT::ID(), IR); + typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> ResultModelT; return static_cast<const ResultModelT &>(ResultConcept).Result; } @@ -466,69 +486,100 @@ public: /// /// \returns null if there is no cached result. template <typename PassT> - const typename PassT::Result *getCachedResult(Module *M) const { - assert(ModuleAnalysisPasses.count(PassT::ID()) && + const typename PassT::Result *getCachedResult(IRUnitT IR) const { + assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); - const detail::AnalysisResultConcept<Module *> *ResultConcept = - getCachedResultImpl(PassT::ID(), M); + const ResultConceptT *ResultConcept = + derived_this()->getCachedResultImpl(PassT::ID(), IR); if (!ResultConcept) return 0; - typedef detail::AnalysisResultModel<Module *, PassT, typename PassT::Result> + typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> ResultModelT; return &static_cast<const ResultModelT *>(ResultConcept)->Result; } /// \brief Register an analysis pass with the manager. /// - /// This provides an initialized and set-up analysis pass to the - /// analysis - /// manager. Whomever is setting up analysis passes must use this to - /// populate + /// This provides an initialized and set-up analysis pass to the analysis + /// manager. Whomever is setting up analysis passes must use this to populate /// the manager with all of the analysis passes available. template <typename PassT> void registerPass(PassT Pass) { - assert(!ModuleAnalysisPasses.count(PassT::ID()) && + assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - ModuleAnalysisPasses[PassT::ID()] = - new detail::AnalysisPassModel<Module *, ModuleAnalysisManager, PassT>( - llvm_move(Pass)); + typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT; + AnalysisPasses[PassT::ID()] = new PassModelT(llvm_move(Pass)); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. template <typename PassT> void invalidate(Module *M) { - assert(ModuleAnalysisPasses.count(PassT::ID()) && + assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), M); } - /// \brief Invalidate analyses cached for an IR Module. + /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this module and invalidate /// them unless they are preserved by the PreservedAnalyses set. - void invalidate(Module *M, const PreservedAnalyses &PA); + void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { + derived_this()->invalidateImpl(IR, PA); + } + +protected: + /// \brief Lookup a registered analysis pass. + PassConceptT &lookupPass(void *PassID) { + typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(PassID); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } + + /// \brief Lookup a registered analysis pass. + const PassConceptT &lookupPass(void *PassID) const { + typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(PassID); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } + +private: + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap<void *, polymorphic_ptr<PassConceptT> > AnalysisPassMapT; + + /// \brief Collection of module analysis passes, indexed by ID. + AnalysisPassMapT AnalysisPasses; +}; + +} + +/// \brief A module analysis pass manager with lazy running and caching of +/// results. +class ModuleAnalysisManager + : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> { + friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>; + typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; + +public: + // Public methods provided by the base class. private: /// \brief Get a module pass result, running the pass if necessary. - const detail::AnalysisResultConcept<Module *> &getResultImpl(void *PassID, - Module *M); + const ResultConceptT &getResultImpl(void *PassID, Module *M); /// \brief Get a cached module pass result or return null. - const detail::AnalysisResultConcept<Module *> * - getCachedResultImpl(void *PassID, Module *M) const; + const ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; /// \brief Invalidate a module pass result. void invalidateImpl(void *PassID, Module *M); - /// \brief Map type from module analysis pass ID to pass concept pointer. - typedef DenseMap<void *, polymorphic_ptr<detail::AnalysisPassConcept< - Module *, ModuleAnalysisManager> > > - ModuleAnalysisPassMapT; - - /// \brief Collection of module analysis passes, indexed by ID. - ModuleAnalysisPassMapT ModuleAnalysisPasses; + /// \brief Invalidate results across a module. + void invalidateImpl(Module *M, const PreservedAnalyses &PA); /// \brief Map type from module analysis pass ID to pass result concept pointer. typedef DenseMap<void *, @@ -541,75 +592,15 @@ private: /// \brief A function analysis manager to coordinate and cache analyses run over /// a module. -class FunctionAnalysisManager { -public: - FunctionAnalysisManager() {} - - /// \brief Get the result of an analysis pass for a function. - /// - /// If there is not a valid cached result in the manager already, this will - /// re-run the analysis to produce a valid result. - template <typename PassT> - const typename PassT::Result &getResult(Function *F) { - assert(FunctionAnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - - const detail::AnalysisResultConcept<Function *> &ResultConcept = - getResultImpl(PassT::ID(), F); - typedef detail::AnalysisResultModel<Function *, PassT, - typename PassT::Result> ResultModelT; - return static_cast<const ResultModelT &>(ResultConcept).Result; - } - - /// \brief Get the cached result of an analysis pass for a function if - /// available. - /// - /// Does not run the analysis ever. - /// \returns null if a cached result is not available. - template <typename PassT> - const typename PassT::Result *getCachedResult(Function *F) { - assert(FunctionAnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being queried"); - - const detail::AnalysisResultConcept<Function *> *ResultConcept = - getCachedResultImpl(PassT::ID(), F); - if (!ResultConcept) - return 0; - - typedef detail::AnalysisResultModel<Function *, PassT, - typename PassT::Result> ResultModelT; - return &static_cast<const ResultModelT *>(ResultConcept)->Result; - } +class FunctionAnalysisManager + : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> { + friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>; + typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; - /// \brief Register an analysis pass with the manager. - /// - /// This provides an initialized and set-up analysis pass to the - /// analysis - /// manager. Whomever is setting up analysis passes must use this to - /// populate - /// the manager with all of the analysis passes available. - template <typename PassT> void registerPass(PassT Pass) { - assert(!FunctionAnalysisPasses.count(PassT::ID()) && - "Registered the same analysis pass twice!"); - FunctionAnalysisPasses[PassT::ID()] = new detail::AnalysisPassModel< - Function *, FunctionAnalysisManager, PassT>(llvm_move(Pass)); - } - - /// \brief Invalidate a specific analysis pass for an IR module. - /// - /// Note that the analysis result can disregard invalidation. - template <typename PassT> void invalidate(Function *F) { - assert(FunctionAnalysisPasses.count(PassT::ID()) && - "This analysis pass was not registered prior to being invalidated"); - invalidateImpl(PassT::ID(), F); - } - - /// \brief Invalidate analyses cached for an IR Function. - /// - /// Walk through all of the analyses cache for this IR function and - /// invalidate them unless they are preserved by the provided - /// PreservedAnalyses set. - void invalidate(Function *F, const PreservedAnalyses &PA); +public: + // Most public APIs are inherited from the CRTP base class. /// \brief Returns true if the analysis manager has an empty results cache. bool empty() const; @@ -624,23 +615,16 @@ public: private: /// \brief Get a function pass result, running the pass if necessary. - const detail::AnalysisResultConcept<Function *> &getResultImpl(void *PassID, - Function *F); + const ResultConceptT &getResultImpl(void *PassID, Function *F); /// \brief Get a cached function pass result or return null. - const detail::AnalysisResultConcept<Function *> * - getCachedResultImpl(void *PassID, Function *F) const; + const ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; /// \brief Invalidate a function pass result. void invalidateImpl(void *PassID, Function *F); - /// \brief Map type from function analysis pass ID to pass concept pointer. - typedef DenseMap<void *, polymorphic_ptr<detail::AnalysisPassConcept< - Function *, FunctionAnalysisManager> > > - FunctionAnalysisPassMapT; - - /// \brief Collection of function analysis passes, indexed by ID. - FunctionAnalysisPassMapT FunctionAnalysisPasses; + /// \brief Invalidate the results for a function.. + void invalidateImpl(Function *F, const PreservedAnalyses &PA); /// \brief List of function analysis pass IDs and associated concept pointers. /// diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp index 05aea0743ae..30b46b01c1d 100644 --- a/llvm/lib/IR/PassManager.cpp +++ b/llvm/lib/IR/PassManager.cpp @@ -23,37 +23,22 @@ PreservedAnalyses ModulePassManager::run(Module *M, ModuleAnalysisManager *AM) { return PA; } -void ModuleAnalysisManager::invalidate(Module *M, const PreservedAnalyses &PA) { - // FIXME: This is a total hack based on the fact that erasure doesn't - // invalidate iteration for DenseMap. - for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(), - E = ModuleAnalysisResults.end(); - I != E; ++I) - if (I->second->invalidate(M, PA)) - ModuleAnalysisResults.erase(I); -} - -const detail::AnalysisResultConcept<Module *> & +const ModuleAnalysisManager::ResultConceptT & ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) { ModuleAnalysisResultMapT::iterator RI; bool Inserted; llvm::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair( PassID, polymorphic_ptr<detail::AnalysisResultConcept<Module *> >())); - if (Inserted) { - // We don't have a cached result for this result. Look up the pass and run - // it to produce a result, which we then add to the cache. - ModuleAnalysisPassMapT::const_iterator PI = - ModuleAnalysisPasses.find(PassID); - assert(PI != ModuleAnalysisPasses.end() && - "Analysis passes must be registered prior to being queried!"); - RI->second = PI->second->run(M, this); - } + // If we don't have a cached result for this module, look up the pass and run + // it to produce a result, which we then add to the cache. + if (Inserted) + RI->second = lookupPass(PassID).run(M, this); return *RI->second; } -const detail::AnalysisResultConcept<Module *> * +const ModuleAnalysisManager::ResultConceptT * ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const { ModuleAnalysisResultMapT::const_iterator RI = ModuleAnalysisResults.find(PassID); return RI == ModuleAnalysisResults.end() ? 0 : &*RI->second; @@ -63,6 +48,17 @@ void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) { ModuleAnalysisResults.erase(PassID); } +void ModuleAnalysisManager::invalidateImpl(Module *M, + const PreservedAnalyses &PA) { + // FIXME: This is a total hack based on the fact that erasure doesn't + // invalidate iteration for DenseMap. + for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(), + E = ModuleAnalysisResults.end(); + I != E; ++I) + if (I->second->invalidate(M, PA)) + ModuleAnalysisResults.erase(I); +} + PreservedAnalyses FunctionPassManager::run(Function *F, FunctionAnalysisManager *AM) { PreservedAnalyses PA = PreservedAnalyses::all(); for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { @@ -74,25 +70,6 @@ PreservedAnalyses FunctionPassManager::run(Function *F, FunctionAnalysisManager return PA; } -void FunctionAnalysisManager::invalidate(Function *F, const PreservedAnalyses &PA) { - // Clear all the invalidated results associated specifically with this - // function. - SmallVector<void *, 8> InvalidatedPassIDs; - FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F]; - for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(), - E = ResultsList.end(); - I != E;) - if (I->second->invalidate(F, PA)) { - InvalidatedPassIDs.push_back(I->first); - I = ResultsList.erase(I); - } else { - ++I; - } - while (!InvalidatedPassIDs.empty()) - FunctionAnalysisResults.erase( - std::make_pair(InvalidatedPassIDs.pop_back_val(), F)); -} - bool FunctionAnalysisManager::empty() const { assert(FunctionAnalysisResults.empty() == FunctionAnalysisResultLists.empty() && @@ -106,29 +83,25 @@ void FunctionAnalysisManager::clear() { FunctionAnalysisResultLists.clear(); } -const detail::AnalysisResultConcept<Function *> & +const FunctionAnalysisManager::ResultConceptT & FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) { FunctionAnalysisResultMapT::iterator RI; bool Inserted; llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair( std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator())); + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. if (Inserted) { - // We don't have a cached result for this result. Look up the pass and run - // it to produce a result, which we then add to the cache. - FunctionAnalysisPassMapT::const_iterator PI = - FunctionAnalysisPasses.find(PassID); - 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, this))); + ResultList.push_back(std::make_pair(PassID, lookupPass(PassID).run(F, this))); RI->second = llvm::prior(ResultList.end()); } return *RI->second->second; } -const detail::AnalysisResultConcept<Function *> * +const FunctionAnalysisManager::ResultConceptT * FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const { FunctionAnalysisResultMapT::const_iterator RI = FunctionAnalysisResults.find(std::make_pair(PassID, F)); @@ -144,6 +117,26 @@ void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) { FunctionAnalysisResultLists[F].erase(RI->second); } +void FunctionAnalysisManager::invalidateImpl(Function *F, + const PreservedAnalyses &PA) { + // Clear all the invalidated results associated specifically with this + // function. + SmallVector<void *, 8> InvalidatedPassIDs; + FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F]; + for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) + if (I->second->invalidate(F, PA)) { + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + while (!InvalidatedPassIDs.empty()) + FunctionAnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), F)); +} + char FunctionAnalysisManagerModuleProxy::PassID; FunctionAnalysisManagerModuleProxy::Result |

