diff options
-rw-r--r-- | llvm/include/llvm/Analysis/CGSCCPassManager.h | 299 | ||||
-rw-r--r-- | llvm/include/llvm/Analysis/LoopPassManager.h | 139 | ||||
-rw-r--r-- | llvm/include/llvm/IR/PassManager.h | 180 | ||||
-rw-r--r-- | llvm/lib/Analysis/CGSCCPassManager.cpp | 63 | ||||
-rw-r--r-- | llvm/lib/Analysis/LoopPassManager.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/IR/PassManager.cpp | 31 | ||||
-rw-r--r-- | llvm/test/Other/new-pass-manager.ll | 6 |
7 files changed, 147 insertions, 602 deletions
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h index cede4b0d117..6fc84b6a2de 100644 --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -41,146 +41,16 @@ typedef PassManager<LazyCallGraph::SCC> CGSCCPassManager; /// pass manager infrastructure. typedef AnalysisManager<LazyCallGraph::SCC> CGSCCAnalysisManager; -/// \brief A module analysis which acts as a proxy for a CGSCC analysis -/// manager. -/// -/// This primarily proxies invalidation information from the module analysis -/// manager and module pass manager to a CGSCC analysis manager. You should -/// never use a CGSCC analysis manager from within (transitively) a module -/// pass manager unless your parent module pass has received a proxy result -/// object for it. -/// -/// Note that the proxy's result is a move-only object and represents ownership -/// of the validity of the analyses in the \c CGSCCAnalysisManager it provides. -class CGSCCAnalysisManagerModuleProxy - : public AnalysisBase<CGSCCAnalysisManagerModuleProxy> { -public: - class Result { - public: - explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} - Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) { - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of its responsibilty to clear the - // analysis state. - Arg.CGAM = nullptr; - } - Result &operator=(Result &&RHS) { - CGAM = RHS.CGAM; - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of its responsibilty to clear the - // analysis state. - RHS.CGAM = nullptr; - return *this; - } - ~Result(); - - /// \brief Accessor for the \c CGSCCAnalysisManager. - CGSCCAnalysisManager &getManager() { return *CGAM; } - - /// \brief Handler for invalidation of the module. - /// - /// If this analysis itself is preserved, then we assume that the call - /// graph of the module hasn't changed and thus we don't need to invalidate - /// *all* cached data associated with a \c SCC* in the \c - /// CGSCCAnalysisManager. - /// - /// Regardless of whether this analysis is marked as preserved, all of the - /// analyses in the \c CGSCCAnalysisManager are potentially invalidated - /// based on the set of preserved analyses. - bool invalidate(Module &M, const PreservedAnalyses &PA); - - private: - CGSCCAnalysisManager *CGAM; - }; - - explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) - : CGAM(&CGAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg) - : CGAM(Arg.CGAM) {} - CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) - : CGAM(std::move(Arg.CGAM)) {} - CGSCCAnalysisManagerModuleProxy & - operator=(CGSCCAnalysisManagerModuleProxy RHS) { - std::swap(CGAM, RHS.CGAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// - /// This doesn't do any interesting work, it is primarily used to insert our - /// proxy result object into the module analysis cache so that we can proxy - /// invalidation to the CGSCC analysis manager. - /// - /// In debug builds, it will also assert that the analysis manager is empty - /// as no queries should arrive at the CGSCC analysis manager prior to - /// this analysis being requested. - Result run(Module &M); - -private: - CGSCCAnalysisManager *CGAM; -}; +extern template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>; +/// A proxy from a \c CGSCCAnalysisManager to a \c Module. +typedef InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module> + CGSCCAnalysisManagerModuleProxy; -/// \brief A CGSCC analysis which acts as a proxy for a module analysis -/// manager. -/// -/// This primarily provides an accessor to a parent module analysis manager to -/// CGSCC passes. Only the const interface of the module analysis manager is -/// provided to indicate that once inside of a CGSCC analysis pass you -/// cannot request a module analysis to actually run. Instead, the user must -/// rely on the \c getCachedResult API. -/// -/// This proxy *doesn't* manage the invalidation in any way. That is handled by -/// the recursive return path of each layer of the pass manager and the -/// returned PreservedAnalysis set. -class ModuleAnalysisManagerCGSCCProxy - : public AnalysisBase<ModuleAnalysisManagerCGSCCProxy> { -public: - /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy. - class Result { - public: - explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} - // We have to explicitly define all the special member functions because - // MSVC refuses to generate them. - Result(const Result &Arg) : MAM(Arg.MAM) {} - Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} - Result &operator=(Result RHS) { - std::swap(MAM, RHS.MAM); - return *this; - } - - const ModuleAnalysisManager &getManager() const { return *MAM; } - - /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(LazyCallGraph::SCC &) { return false; } - - private: - const ModuleAnalysisManager *MAM; - }; - - ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) - : MAM(&MAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg) - : MAM(Arg.MAM) {} - ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) - : MAM(std::move(Arg.MAM)) {} - ModuleAnalysisManagerCGSCCProxy & - operator=(ModuleAnalysisManagerCGSCCProxy RHS) { - std::swap(MAM, RHS.MAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// Nothing to see here, it just forwards the \c MAM reference into the - /// result. - Result run(LazyCallGraph::SCC &) { return Result(*MAM); } - -private: - const ModuleAnalysisManager *MAM; -}; +extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager, + LazyCallGraph::SCC>; +/// A proxy from a \c ModuleAnalysisManager to an \c SCC. +typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, LazyCallGraph::SCC> + ModuleAnalysisManagerCGSCCProxy; /// \brief The core module pass which does a post-order walk of the SCCs and /// runs a CGSCC pass over each one. @@ -266,149 +136,16 @@ createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)); } -/// \brief A CGSCC analysis which acts as a proxy for a function analysis -/// manager. -/// -/// This primarily proxies invalidation information from the CGSCC analysis -/// manager and CGSCC pass manager to a function analysis manager. You should -/// never use a function analysis manager from within (transitively) a CGSCC -/// pass manager unless your parent CGSCC pass has received a proxy result -/// object for it. -/// -/// Note that the proxy's result is a move-only object and represents ownership -/// of the validity of the analyses in the \c FunctionAnalysisManager it -/// provides. -class FunctionAnalysisManagerCGSCCProxy - : public AnalysisBase<FunctionAnalysisManagerCGSCCProxy> { -public: - class Result { - public: - explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} - Result(Result &&Arg) : FAM(std::move(Arg.FAM)) { - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibilty to clear the - // analysis state. - Arg.FAM = nullptr; - } - Result &operator=(Result &&RHS) { - FAM = RHS.FAM; - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibilty to clear the - // analysis state. - RHS.FAM = nullptr; - return *this; - } - ~Result(); - - /// \brief Accessor for the \c FunctionAnalysisManager. - FunctionAnalysisManager &getManager() { return *FAM; } - - /// \brief Handler for invalidation of the SCC. - /// - /// If this analysis itself is preserved, then we assume that the set of \c - /// Function objects in the \c SCC hasn't changed and thus we don't need - /// to invalidate *all* cached data associated with a \c Function* in the \c - /// FunctionAnalysisManager. - /// - /// Regardless of whether this analysis is marked as preserved, all of the - /// analyses in the \c FunctionAnalysisManager are potentially invalidated - /// based on the set of preserved analyses. - bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA); - - private: - FunctionAnalysisManager *FAM; - }; - - explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) - : FAM(&FAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionAnalysisManagerCGSCCProxy( - const FunctionAnalysisManagerCGSCCProxy &Arg) - : FAM(Arg.FAM) {} - FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg) - : FAM(std::move(Arg.FAM)) {} - FunctionAnalysisManagerCGSCCProxy & - operator=(FunctionAnalysisManagerCGSCCProxy RHS) { - std::swap(FAM, RHS.FAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// - /// This doesn't do any interesting work, it is primarily used to insert our - /// proxy result object into the module analysis cache so that we can proxy - /// invalidation to the function analysis manager. - /// - /// In debug builds, it will also assert that the analysis manager is empty - /// as no queries should arrive at the function analysis manager prior to - /// this analysis being requested. - Result run(LazyCallGraph::SCC &C); - -private: - FunctionAnalysisManager *FAM; -}; +extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager, + LazyCallGraph::SCC>; +/// A proxy from a \c FunctionAnalysisManager to an \c SCC. +typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, LazyCallGraph::SCC> + FunctionAnalysisManagerCGSCCProxy; -/// \brief A function analysis which acts as a proxy for a CGSCC analysis -/// manager. -/// -/// This primarily provides an accessor to a parent CGSCC analysis manager to -/// function passes. Only the const interface of the CGSCC analysis manager is -/// provided to indicate that once inside of a function analysis pass you -/// cannot request a CGSCC analysis to actually run. Instead, the user must -/// rely on the \c getCachedResult API. -/// -/// This proxy *doesn't* manage the invalidation in any way. That is handled by -/// the recursive return path of each layer of the pass manager and the -/// returned PreservedAnalysis set. -class CGSCCAnalysisManagerFunctionProxy - : public AnalysisBase<CGSCCAnalysisManagerFunctionProxy> { -public: - /// \brief Result proxy object for \c CGSCCAnalysisManagerFunctionProxy. - class Result { - public: - explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} - // We have to explicitly define all the special member functions because - // MSVC refuses to generate them. - Result(const Result &Arg) : CGAM(Arg.CGAM) {} - Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} - Result &operator=(Result RHS) { - std::swap(CGAM, RHS.CGAM); - return *this; - } - - const CGSCCAnalysisManager &getManager() const { return *CGAM; } - - /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function &) { return false; } - - private: - const CGSCCAnalysisManager *CGAM; - }; - - CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) - : CGAM(&CGAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManagerFunctionProxy( - const CGSCCAnalysisManagerFunctionProxy &Arg) - : CGAM(Arg.CGAM) {} - CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg) - : CGAM(std::move(Arg.CGAM)) {} - CGSCCAnalysisManagerFunctionProxy & - operator=(CGSCCAnalysisManagerFunctionProxy RHS) { - std::swap(CGAM, RHS.CGAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// Nothing to see here, it just forwards the \c CGAM reference into the - /// result. - Result run(Function &) { return Result(*CGAM); } - -private: - const CGSCCAnalysisManager *CGAM; -}; +extern template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>; +/// A proxy from a \c CGSCCAnalysisManager to a \c Function. +typedef OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function> + CGSCCAnalysisManagerFunctionProxy; /// \brief Adaptor that maps from a SCC to its functions. /// diff --git a/llvm/include/llvm/Analysis/LoopPassManager.h b/llvm/include/llvm/Analysis/LoopPassManager.h index 9fd4c7bd141..8693855b313 100644 --- a/llvm/include/llvm/Analysis/LoopPassManager.h +++ b/llvm/include/llvm/Analysis/LoopPassManager.h @@ -36,136 +36,15 @@ typedef PassManager<Loop> LoopPassManager; /// pass manager infrastructure. typedef AnalysisManager<Loop> LoopAnalysisManager; -/// \brief A function analysis which acts as a proxy for a loop analysis -/// manager. -/// -/// This primarily proxies invalidation information from the function analysis -/// manager and function pass manager to a loop analysis manager. You should -/// never use a loop analysis manager from within (transitively) a function -/// pass manager unless your parent function pass has received a proxy result -/// object for it. -class LoopAnalysisManagerFunctionProxy - : public AnalysisBase<LoopAnalysisManagerFunctionProxy> { -public: - class Result { - public: - explicit Result(LoopAnalysisManager &LAM) : LAM(&LAM) {} - // We have to explicitly define all the special member functions because - // MSVC refuses to generate them. - Result(const Result &Arg) : LAM(Arg.LAM) {} - Result(Result &&Arg) : LAM(std::move(Arg.LAM)) {} - Result &operator=(Result RHS) { - std::swap(LAM, RHS.LAM); - return *this; - } - ~Result(); - - /// \brief Accessor for the \c LoopAnalysisManager. - LoopAnalysisManager &getManager() { return *LAM; } - - /// \brief Handler for invalidation of the function. - /// - /// If this analysis itself is preserved, then we assume that the function - /// hasn't changed and thus we don't need to invalidate *all* cached data - /// associated with a \c Loop* in the \c LoopAnalysisManager. - /// - /// Regardless of whether this analysis is marked as preserved, all of the - /// analyses in the \c LoopAnalysisManager are potentially invalidated based - /// on the set of preserved analyses. - bool invalidate(Function &F, const PreservedAnalyses &PA); - - private: - LoopAnalysisManager *LAM; - }; - - explicit LoopAnalysisManagerFunctionProxy(LoopAnalysisManager &LAM) - : LAM(&LAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - LoopAnalysisManagerFunctionProxy(const LoopAnalysisManagerFunctionProxy &Arg) - : LAM(Arg.LAM) {} - LoopAnalysisManagerFunctionProxy(LoopAnalysisManagerFunctionProxy &&Arg) - : LAM(std::move(Arg.LAM)) {} - LoopAnalysisManagerFunctionProxy & - operator=(LoopAnalysisManagerFunctionProxy RHS) { - std::swap(LAM, RHS.LAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// - /// This doesn't do any interesting work, it is primarily used to insert our - /// proxy result object into the function analysis cache so that we can proxy - /// invalidation to the loop analysis manager. - /// - /// In debug builds, it will also assert that the analysis manager is empty as - /// no queries should arrive at the loop analysis manager prior to this - /// analysis being requested. - Result run(Function &F); - -private: - LoopAnalysisManager *LAM; -}; - -/// \brief A loop analysis which acts as a proxy for a function analysis -/// manager. -/// -/// This primarily provides an accessor to a parent function analysis manager to -/// loop passes. Only the const interface of the function analysis manager is -/// provided to indicate that once inside of a loop analysis pass you cannot -/// request a function analysis to actually run. Instead, the user must rely on -/// the \c getCachedResult API. -/// -/// This proxy *doesn't* manage the invalidation in any way. That is handled by -/// the recursive return path of each layer of the pass manager and the -/// returned PreservedAnalysis set. -class FunctionAnalysisManagerLoopProxy - : public AnalysisBase<FunctionAnalysisManagerLoopProxy> { -public: - /// \brief Result proxy object for \c FunctionAnalysisManagerLoopProxy. - class Result { - public: - explicit Result(const FunctionAnalysisManager &FAM) : FAM(&FAM) {} - // We have to explicitly define all the special member functions because - // MSVC refuses to generate them. - Result(const Result &Arg) : FAM(Arg.FAM) {} - Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} - Result &operator=(Result RHS) { - std::swap(FAM, RHS.FAM); - return *this; - } - - const FunctionAnalysisManager &getManager() const { return *FAM; } - - /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function &) { return false; } - - private: - const FunctionAnalysisManager *FAM; - }; - - FunctionAnalysisManagerLoopProxy(const FunctionAnalysisManager &FAM) - : FAM(&FAM) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionAnalysisManagerLoopProxy(const FunctionAnalysisManagerLoopProxy &Arg) - : FAM(Arg.FAM) {} - FunctionAnalysisManagerLoopProxy(FunctionAnalysisManagerLoopProxy &&Arg) - : FAM(std::move(Arg.FAM)) {} - FunctionAnalysisManagerLoopProxy & - operator=(FunctionAnalysisManagerLoopProxy RHS) { - std::swap(FAM, RHS.FAM); - return *this; - } - - /// \brief Run the analysis pass and create our proxy result object. - /// Nothing to see here, it just forwards the \c FAM reference into the - /// result. - Result run(Loop &) { return Result(*FAM); } - -private: - const FunctionAnalysisManager *FAM; -}; +extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; +/// A proxy from a \c LoopAnalysisManager to a \c Function. +typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function> + LoopAnalysisManagerFunctionProxy; + +extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>; +/// A proxy from a \c FunctionAnalysisManager to a \c Loop. +typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop> + FunctionAnalysisManagerLoopProxy; /// \brief Adaptor that maps from a function to its loops. /// diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 68f74f8a616..e51142d5e32 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -651,23 +651,76 @@ typedef AnalysisManager<Function> FunctionAnalysisManager; /// Note that the proxy's result is a move-only object and represents ownership /// of the validity of the analyses in the \c FunctionAnalysisManager it /// provides. -class FunctionAnalysisManagerModuleProxy - : public AnalysisBase<FunctionAnalysisManagerModuleProxy> { +template <typename AnalysisManagerT, typename IRUnitT> +class InnerAnalysisManagerProxy + : public AnalysisBase< + InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> { public: - class Result; + class Result { + public: + explicit Result(AnalysisManagerT &AM) : AM(&AM) {} + Result(Result &&Arg) : AM(std::move(Arg.AM)) { + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + Arg.AM = nullptr; + } + Result &operator=(Result &&RHS) { + AM = RHS.AM; + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + RHS.AM = nullptr; + return *this; + } + ~Result() { + // AM is cleared in a moved from state where there is nothing to do. + if (!AM) + return; + + // Clear out the analysis manager if we're being destroyed -- it means we + // didn't even see an invalidate call when we got invalidated. + AM->clear(); + } + + /// \brief Accessor for the analysis manager. + AnalysisManagerT &getManager() { return *AM; } + + /// \brief Handler for invalidation of the module. + /// + /// If this analysis itself is preserved, then we assume that the set of \c + /// Function objects in the \c Module hasn't changed and thus we don't need + /// to invalidate *all* cached data associated with a \c Function* in the \c + /// FunctionAnalysisManager. + /// + /// Regardless of whether this analysis is marked as preserved, all of the + /// analyses in the \c FunctionAnalysisManager are potentially invalidated + /// based on the set of preserved analyses. + bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) { + // If this proxy isn't marked as preserved, then we can't even invalidate + // individual function analyses, there may be an invalid set of Function + // objects in the cache making it impossible to incrementally preserve + // them. Just clear the entire manager. + if (!PA.preserved(InnerAnalysisManagerProxy::ID())) + AM->clear(); + + // Return false to indicate that this result is still a valid proxy. + return false; + } + + private: + AnalysisManagerT *AM; + }; - explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) - : FAM(&FAM) {} + explicit InnerAnalysisManagerProxy(AnalysisManagerT &AM) : AM(&AM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManagerModuleProxy( - const FunctionAnalysisManagerModuleProxy &Arg) - : FAM(Arg.FAM) {} - FunctionAnalysisManagerModuleProxy(FunctionAnalysisManagerModuleProxy &&Arg) - : FAM(std::move(Arg.FAM)) {} - FunctionAnalysisManagerModuleProxy & - operator=(FunctionAnalysisManagerModuleProxy RHS) { - std::swap(FAM, RHS.FAM); + InnerAnalysisManagerProxy(const InnerAnalysisManagerProxy &Arg) + : AM(Arg.AM) {} + InnerAnalysisManagerProxy(InnerAnalysisManagerProxy &&Arg) + : AM(std::move(Arg.AM)) {} + InnerAnalysisManagerProxy &operator=(InnerAnalysisManagerProxy RHS) { + std::swap(AM, RHS.AM); return *this; } @@ -680,53 +733,17 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module &M); + Result run(IRUnitT &IR) { return Result(*AM); } private: - FunctionAnalysisManager *FAM; + AnalysisManagerT *AM; }; -/// \brief The result proxy object for the -/// \c FunctionAnalysisManagerModuleProxy. -/// -/// See its documentation for more information. -class FunctionAnalysisManagerModuleProxy::Result { -public: - explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} - Result(Result &&Arg) : FAM(std::move(Arg.FAM)) { - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibilty to clear the - // analysis state. - Arg.FAM = nullptr; - } - Result &operator=(Result &&RHS) { - FAM = RHS.FAM; - // We have to null out the analysis manager in the moved-from state - // because we are taking ownership of the responsibilty to clear the - // analysis state. - RHS.FAM = nullptr; - return *this; - } - ~Result(); - - /// \brief Accessor for the \c FunctionAnalysisManager. - FunctionAnalysisManager &getManager() { return *FAM; } - - /// \brief Handler for invalidation of the module. - /// - /// If this analysis itself is preserved, then we assume that the set of \c - /// Function objects in the \c Module hasn't changed and thus we don't need - /// to invalidate *all* cached data associated with a \c Function* in the \c - /// FunctionAnalysisManager. - /// - /// Regardless of whether this analysis is marked as preserved, all of the - /// analyses in the \c FunctionAnalysisManager are potentially invalidated - /// based on the set of preserved analyses. - bool invalidate(Module &M, const PreservedAnalyses &PA); - -private: - FunctionAnalysisManager *FAM; -}; +extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager, + Module>; +/// Provide the \c FunctionAnalysisManager to \c Module proxy. +typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> + FunctionAnalysisManagerModuleProxy; /// \brief A function analysis which acts as a proxy for a module analysis /// manager. @@ -740,55 +757,60 @@ private: /// This proxy *doesn't* manage the invalidation in any way. That is handled by /// the recursive return path of each layer of the pass manager and the /// returned PreservedAnalysis set. -class ModuleAnalysisManagerFunctionProxy - : public AnalysisBase<ModuleAnalysisManagerFunctionProxy> { +template <typename AnalysisManagerT, typename IRUnitT> +class OuterAnalysisManagerProxy + : public AnalysisBase< + OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> { public: - /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. + /// \brief Result proxy object for \c OuterAnalysisManagerProxy. class Result { public: - explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} + explicit Result(const AnalysisManagerT &AM) : AM(&AM) {} // We have to explicitly define all the special member functions because // MSVC refuses to generate them. - Result(const Result &Arg) : MAM(Arg.MAM) {} - Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} + Result(const Result &Arg) : AM(Arg.AM) {} + Result(Result &&Arg) : AM(std::move(Arg.AM)) {} Result &operator=(Result RHS) { - std::swap(MAM, RHS.MAM); + std::swap(AM, RHS.AM); return *this; } - const ModuleAnalysisManager &getManager() const { return *MAM; } + const AnalysisManagerT &getManager() const { return *AM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function &) { return false; } + bool invalidate(IRUnitT &) { return false; } private: - const ModuleAnalysisManager *MAM; + const AnalysisManagerT *AM; }; - ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) - : MAM(&MAM) {} + OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - ModuleAnalysisManagerFunctionProxy( - const ModuleAnalysisManagerFunctionProxy &Arg) - : MAM(Arg.MAM) {} - ModuleAnalysisManagerFunctionProxy(ModuleAnalysisManagerFunctionProxy &&Arg) - : MAM(std::move(Arg.MAM)) {} - ModuleAnalysisManagerFunctionProxy & - operator=(ModuleAnalysisManagerFunctionProxy RHS) { - std::swap(MAM, RHS.MAM); + OuterAnalysisManagerProxy(const OuterAnalysisManagerProxy &Arg) + : AM(Arg.AM) {} + OuterAnalysisManagerProxy(OuterAnalysisManagerProxy &&Arg) + : AM(std::move(Arg.AM)) {} + OuterAnalysisManagerProxy &operator=(OuterAnalysisManagerProxy RHS) { + std::swap(AM, RHS.AM); return *this; } /// \brief Run the analysis pass and create our proxy result object. - /// Nothing to see here, it just forwards the \c MAM reference into the + /// Nothing to see here, it just forwards the \c AM reference into the /// result. - Result run(Function &) { return Result(*MAM); } + Result run(IRUnitT &) { return Result(*AM); } private: - const ModuleAnalysisManager *MAM; + const AnalysisManagerT *AM; }; +extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager, + Function>; +/// Provide the \c ModuleAnalysisManager to \c Fucntion proxy. +typedef OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> + ModuleAnalysisManagerFunctionProxy; + /// \brief Trivial adaptor that maps from a module to its functions. /// /// Designed to allow composition of a FunctionPass(Manager) and diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp index 69c37f57528..d5058d6aab1 100644 --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -13,59 +13,12 @@ using namespace llvm; -CGSCCAnalysisManagerModuleProxy::Result -CGSCCAnalysisManagerModuleProxy::run(Module &M) { - assert(CGAM->empty() && "CGSCC analyses ran prior to the module proxy!"); - return Result(*CGAM); -} - -CGSCCAnalysisManagerModuleProxy::Result::~Result() { - // CGAM is cleared in a moved from state where there is nothing to do. - if (!CGAM) - return; - - // Clear out the analysis manager if we're being destroyed -- it means we - // didn't even see an invalidate call when we got invalidated. - CGAM->clear(); -} - -bool CGSCCAnalysisManagerModuleProxy::Result::invalidate( - Module &M, const PreservedAnalyses &PA) { - // If this proxy isn't marked as preserved, then we can't even invalidate - // individual CGSCC analyses, there may be an invalid set of SCC objects in - // the cache making it impossible to incrementally preserve them. - // Just clear the entire manager. - if (!PA.preserved(ID())) - CGAM->clear(); - - // Return false to indicate that this result is still a valid proxy. - return false; -} - -FunctionAnalysisManagerCGSCCProxy::Result -FunctionAnalysisManagerCGSCCProxy::run(LazyCallGraph::SCC &C) { - return Result(*FAM); -} - -FunctionAnalysisManagerCGSCCProxy::Result::~Result() { - // FAM is cleared in a moved from state where there is nothing to do. - if (!FAM) - return; - - // Clear out the analysis manager if we're being destroyed -- it means we - // didn't even see an invalidate call when we got invalidated. - FAM->clear(); -} - -bool FunctionAnalysisManagerCGSCCProxy::Result::invalidate( - LazyCallGraph::SCC &C, const PreservedAnalyses &PA) { - // If this proxy isn't marked as preserved, then we can't even invalidate - // individual function analyses, there may be an invalid set of Function - // objects in the cache making it impossible to incrementally preserve them. - // Just clear the entire manager. - if (!PA.preserved(ID())) - FAM->clear(); - - // Return false to indicate that this result is still a valid proxy. - return false; +// Explicit instantiations for the core proxy templates. +namespace llvm { +template class InnerAnalysisManagerProxy<CGSCCAnalysisManager, Module>; +template class OuterAnalysisManagerProxy<ModuleAnalysisManager, + LazyCallGraph::SCC>; +template class InnerAnalysisManagerProxy<FunctionAnalysisManager, + LazyCallGraph::SCC>; +template class OuterAnalysisManagerProxy<CGSCCAnalysisManager, Function>; } diff --git a/llvm/lib/Analysis/LoopPassManager.cpp b/llvm/lib/Analysis/LoopPassManager.cpp index 1d87e07b837..fd77b786262 100644 --- a/llvm/lib/Analysis/LoopPassManager.cpp +++ b/llvm/lib/Analysis/LoopPassManager.cpp @@ -11,31 +11,8 @@ using namespace llvm; -LoopAnalysisManagerFunctionProxy::Result -LoopAnalysisManagerFunctionProxy::run(Function &F) { - // TODO: In FunctionAnalysisManagerModuleProxy we assert that the - // AnalysisManager is empty, but if we do that here we run afoul of the fact - // that we still have results for previous functions alive. Should we be - // clearing those when we finish a function? - //assert(LAM->empty() && "Loop analyses ran prior to the function proxy!"); - return Result(*LAM); -} - -LoopAnalysisManagerFunctionProxy::Result::~Result() { - // Clear out the analysis manager if we're being destroyed -- it means we - // didn't even see an invalidate call when we got invalidated. - LAM->clear(); -} - -bool LoopAnalysisManagerFunctionProxy::Result::invalidate( - Function &F, const PreservedAnalyses &PA) { - // If this proxy isn't marked as preserved, then we can't even invalidate - // individual loop analyses, there may be an invalid set of Loops in the cache - // making it impossible to incrementally preserve them. Just clear the entire - // manager. - if (!PA.preserved(ID())) - LAM->clear(); - - // Return false to indicate that this result is still a valid proxy. - return false; +// Explicit instantiations for core typedef'ed templates. +namespace llvm { +template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; +template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>; } diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp index 06491ae08a7..18e7a73f03e 100644 --- a/llvm/lib/IR/PassManager.cpp +++ b/llvm/lib/IR/PassManager.cpp @@ -13,31 +13,8 @@ using namespace llvm; -FunctionAnalysisManagerModuleProxy::Result -FunctionAnalysisManagerModuleProxy::run(Module &M) { - assert(FAM->empty() && "Function analyses ran prior to the module proxy!"); - return Result(*FAM); -} - -FunctionAnalysisManagerModuleProxy::Result::~Result() { - // FAM is cleared in a moved from state where there is nothing to do. - if (!FAM) - return; - - // Clear out the analysis manager if we're being destroyed -- it means we - // didn't even see an invalidate call when we got invalidated. - FAM->clear(); -} - -bool FunctionAnalysisManagerModuleProxy::Result::invalidate( - Module &M, const PreservedAnalyses &PA) { - // If this proxy isn't marked as preserved, then we can't even invalidate - // individual function analyses, there may be an invalid set of Function - // objects in the cache making it impossible to incrementally preserve them. - // Just clear the entire manager. - if (!PA.preserved(ID())) - FAM->clear(); - - // Return false to indicate that this result is still a valid proxy. - return false; +// Explicit template instantiations for core template typedefs. +namespace llvm { +template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; +template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; } diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll index f1a7ef68ff6..11a31ae8f7a 100644 --- a/llvm/test/Other/new-pass-manager.ll +++ b/llvm/test/Other/new-pass-manager.ll @@ -20,7 +20,7 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS ; CHECK-CGSCC-PASS: Starting llvm::Module pass manager run ; CHECK-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor -; CHECK-CGSCC-PASS-NEXT: Running analysis: CGSCCAnalysisManagerModuleProxy +; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<CGSCCAnalysisManager, llvm::Module> ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass @@ -35,7 +35,7 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS ; CHECK-FUNCTION-PASS: Starting llvm::Module pass manager run ; CHECK-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor -; CHECK-FUNCTION-PASS-NEXT: Running analysis: FunctionAnalysisManagerModuleProxy +; CHECK-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<FunctionAnalysisManager, llvm::Module> ; CHECK-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass ; CHECK-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run @@ -65,7 +65,7 @@ ; CHECK-FUNCTION-PRINT: Starting llvm::Module pass manager run ; CHECK-FUNCTION-PRINT: Running pass: VerifierPass ; CHECK-FUNCTION-PRINT: Running pass: ModuleToFunctionPassAdaptor -; CHECK-FUNCTION-PRINT: Running analysis: FunctionAnalysisManagerModuleProxy +; CHECK-FUNCTION-PRINT: Running analysis: InnerAnalysisManagerProxy<FunctionAnalysisManager, llvm::Module> ; CHECK-FUNCTION-PRINT: Starting llvm::Function pass manager run ; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass ; CHECK-FUNCTION-PRINT-NOT: ModuleID |