diff options
| -rw-r--r-- | llvm/include/llvm/IR/IRPrintingPasses.h | 2 | ||||
| -rw-r--r-- | llvm/include/llvm/IR/PassManager.h | 91 | ||||
| -rw-r--r-- | llvm/include/llvm/IR/PassManagerInternal.h | 37 | ||||
| -rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 15 | ||||
| -rw-r--r-- | llvm/unittests/IR/PassManagerTest.cpp | 57 |
5 files changed, 51 insertions, 151 deletions
diff --git a/llvm/include/llvm/IR/IRPrintingPasses.h b/llvm/include/llvm/IR/IRPrintingPasses.h index 0825e0696ca..bc6de19a6c3 100644 --- a/llvm/include/llvm/IR/IRPrintingPasses.h +++ b/llvm/include/llvm/IR/IRPrintingPasses.h @@ -30,7 +30,7 @@ class Module; class ModulePass; class PreservedAnalyses; class raw_ostream; -template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; +template <typename IRUnitT> class AnalysisManager; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 3c72b0bb99c..e2d4d990143 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -171,7 +171,7 @@ private: }; // Forward declare the analysis manager template. -template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; +template <typename IRUnitT> class AnalysisManager; /// A CRTP mix-in to automatically provide informational APIs needed for /// passes. @@ -222,11 +222,8 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> { /// that analysis manager to each pass it runs, as well as calling the analysis /// manager's invalidation routine with the PreservedAnalyses of each pass it /// runs. -template <typename IRUnitT, - typename AnalysisManagerT = AnalysisManager<IRUnitT>, - typename... ExtraArgTs> -class PassManager : public PassInfoMixin< - PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> { +template <typename IRUnitT> +class PassManager : public PassInfoMixin<PassManager<IRUnitT>> { public: /// \brief Construct a pass manager. /// @@ -244,8 +241,7 @@ public: } /// \brief Run all of the passes in this manager over the IR. - PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) { + PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) { PreservedAnalyses PA = PreservedAnalyses::all(); if (DebugLogging) @@ -256,7 +252,7 @@ public: dbgs() << "Running pass: " << Passes[Idx]->name() << " on " << IR.getName() << "\n"; - PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM, ExtraArgs...); + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); // Update the analysis manager as each pass runs and potentially // invalidates analyses. We also update the preserved set of analyses @@ -282,15 +278,12 @@ public: } template <typename PassT> void addPass(PassT Pass) { - typedef detail::PassModel<IRUnitT, PassT, PreservedAnalyses, - AnalysisManagerT, ExtraArgTs...> - PassModelT; + typedef detail::PassModel<IRUnitT, PassT> PassModelT; Passes.emplace_back(new PassModelT(std::move(Pass))); } private: - typedef detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> - PassConceptT; + typedef detail::PassConcept<IRUnitT> PassConceptT; PassManager(const PassManager &) = delete; PassManager &operator=(const PassManager &) = delete; @@ -315,10 +308,10 @@ typedef PassManager<Function> FunctionPassManager; /// This analysis manager can be used for any IR unit where the address of the /// IR unit sufficies as its identity. It manages the cache for a unit of IR via /// the address of each unit of IR cached. -template <typename IRUnitT, typename... ExtraArgTs> +template <typename IRUnitT> class AnalysisManager { typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; - typedef detail::AnalysisPassConcept<IRUnitT, ExtraArgTs...> PassConceptT; + typedef detail::AnalysisPassConcept<IRUnitT> PassConceptT; public: // Most public APIs are inherited from the CRTP base class. @@ -365,11 +358,11 @@ public: /// /// 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> - typename PassT::Result &getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) { + template <typename PassT> typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); - ResultConceptT &ResultConcept = getResultImpl(PassT::ID(), IR, ExtraArgs...); + + ResultConceptT &ResultConcept = getResultImpl(PassT::ID(), IR); typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> ResultModelT; return static_cast<ResultModelT &>(ResultConcept).Result; @@ -414,7 +407,7 @@ public: /// away. template <typename PassBuilderT> bool registerPass(PassBuilderT PassBuilder) { typedef decltype(PassBuilder()) PassT; - typedef detail::AnalysisPassModel<IRUnitT, PassT, ExtraArgTs...> PassModelT; + typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT; auto &PassPtr = AnalysisPasses[PassT::ID()]; if (PassPtr) @@ -509,8 +502,7 @@ private: } /// \brief Get an analysis result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR, - ExtraArgTs... ExtraArgs) { + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { typename AnalysisResultMapT::iterator RI; bool Inserted; std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( @@ -523,7 +515,7 @@ private: if (DebugLogging) dbgs() << "Running analysis: " << P.name() << "\n"; AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; - ResultList.emplace_back(PassID, P.run(IR, *this, ExtraArgs...)); + ResultList.emplace_back(PassID, P.run(IR, *this)); // P.run may have inserted elements into AnalysisResults and invalidated // RI. @@ -615,7 +607,7 @@ 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. -template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> +template <typename AnalysisManagerT, typename IRUnitT> class InnerAnalysisManagerProxy : public AnalysisInfoMixin< InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> { @@ -697,10 +689,7 @@ 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(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &, - ExtraArgTs...) { - return Result(*AM); - } + Result run(IRUnitT &IR, AnalysisManager<IRUnitT> &) { return Result(*AM); } private: friend AnalysisInfoMixin< @@ -710,9 +699,8 @@ private: AnalysisManagerT *AM; }; -template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> -char - InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::PassID; +template <typename AnalysisManagerT, typename IRUnitT> +char InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>::PassID; extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; @@ -732,7 +720,7 @@ typedef InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> /// 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. -template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> +template <typename AnalysisManagerT, typename IRUnitT> class OuterAnalysisManagerProxy : public AnalysisInfoMixin< OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> { @@ -774,10 +762,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c AM reference into the /// result. - Result run(IRUnitT &, AnalysisManager<IRUnitT, ExtraArgTs...> &, - ExtraArgTs...) { - return Result(*AM); - } + Result run(IRUnitT &, AnalysisManager<IRUnitT> &) { return Result(*AM); } private: friend AnalysisInfoMixin< @@ -787,9 +772,8 @@ private: const AnalysisManagerT *AM; }; -template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> -char - OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::PassID; +template <typename AnalysisManagerT, typename IRUnitT> +char OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT>::PassID; extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; @@ -890,30 +874,15 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { /// /// This is a no-op pass which simply forces a specific analysis pass's result /// to be available when it is run. -template <typename AnalysisT, typename IRUnitT, - typename AnalysisManagerT = AnalysisManager<IRUnitT>, - typename... ExtraArgTs> -struct RequireAnalysisPass; - -/// A specialization of the RequireAnalysisPass for generic IR unit analysis -/// managers and pass managers that have no extra arguments. -/// -/// If there are extra arguments at the pass's run level there may also be -/// extra arguments to the analysis manager's \c getResult routine. We can't -/// guess how to effectively map the arguments from one to the other, and so -/// only the specialization with no extra arguments is provided generically. -/// Specific patterns of run-method extra arguments and analysis manager extra -/// arguments will have to be defined as appropriate for those patterns. -template <typename AnalysisT, typename IRUnitT> -struct RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManager<IRUnitT>> - : PassInfoMixin< - RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManager<IRUnitT>>> { +template <typename AnalysisT> +struct RequireAnalysisPass : PassInfoMixin<RequireAnalysisPass<AnalysisT>> { /// \brief Run this pass over some unit of IR. /// /// This pass can be run over any unit of IR and use any analysis manager /// provided they satisfy the basic API requirements. When this pass is /// created, these methods can be instantiated to satisfy whatever the /// context requires. + template <typename IRUnitT> PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> &AM) { (void)AM.template getResult<AnalysisT>(Arg); @@ -935,8 +904,8 @@ struct InvalidateAnalysisPass /// provided they satisfy the basic API requirements. When this pass is /// created, these methods can be instantiated to satisfy whatever the /// context requires. - template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> - PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...) { + template <typename IRUnitT> + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> &AM) { // We have to directly invalidate the analysis result as we can't // enumerate all other analyses and use the preserved set to control it. AM.template invalidate<AnalysisT>(Arg); @@ -951,8 +920,8 @@ struct InvalidateAnalysisPass /// analysis passes to be re-run to produce fresh results if any are needed. struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> { /// \brief Run this pass over some unit of IR. - template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> - PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) { + template <typename IRUnitT> + PreservedAnalyses run(IRUnitT &, AnalysisManager<IRUnitT> &) { return PreservedAnalyses::none(); } }; diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h index dcc0a1cb2d9..2ffd55225fb 100644 --- a/llvm/include/llvm/IR/PassManagerInternal.h +++ b/llvm/include/llvm/IR/PassManagerInternal.h @@ -23,7 +23,7 @@ namespace llvm { -template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; +template <typename IRUnitT> class AnalysisManager; class PreservedAnalyses; /// \brief Implementation details of the pass manager interfaces. @@ -31,18 +31,12 @@ namespace detail { /// \brief Template for the abstract base class used to dispatch /// polymorphically over pass objects. -template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> -struct PassConcept { +template <typename IRUnitT> struct PassConcept { // Boiler plate necessary for the container of derived classes. virtual ~PassConcept() {} /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) = 0; + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; @@ -53,9 +47,9 @@ struct PassConcept { /// Can be instantiated for any object which provides a \c run method accepting /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to /// be a copyable object. -template <typename IRUnitT, typename PassT, typename PreservedAnalysesT, - typename AnalysisManagerT, typename... ExtraArgTs> -struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> { +template <typename IRUnitT, typename PassT, + typename PreservedAnalysesT = PreservedAnalyses> +struct PassModel : PassConcept<IRUnitT> { explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -70,9 +64,8 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> { return *this; } - PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM, - ExtraArgTs... ExtraArgs) override { - return Pass.run(IR, AM, ExtraArgs...); + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) override { + return Pass.run(IR, AM); } StringRef name() override { return PassT::name(); } PassT Pass; @@ -212,15 +205,14 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true> /// /// This concept is parameterized over the IR unit that it can run over and /// produce an analysis result. -template <typename IRUnitT, typename... ExtraArgTs> struct AnalysisPassConcept { +template <typename IRUnitT> struct AnalysisPassConcept { virtual ~AnalysisPassConcept() {} /// \brief Method to run this analysis over a unit of IR. /// \returns A unique_ptr to the analysis result object to be queried by /// users. virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>> - run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM, - ExtraArgTs... ExtraArgs) = 0; + run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; @@ -231,8 +223,8 @@ template <typename IRUnitT, typename... ExtraArgTs> struct AnalysisPassConcept { /// Can wrap any type which implements a suitable \c run method. The method /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments /// and produce an object which can be wrapped in a \c AnalysisResultModel. -template <typename IRUnitT, typename PassT, typename... ExtraArgTs> -struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, ExtraArgTs...> { +template <typename IRUnitT, typename PassT> +struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> { explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -255,9 +247,8 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, ExtraArgTs...> { /// /// The return is wrapped in an \c AnalysisResultModel. std::unique_ptr<AnalysisResultConcept<IRUnitT>> - run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM, - ExtraArgTs... ExtraArgs) override { - return make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...)); + run(IRUnitT &IR, AnalysisManager<IRUnitT> &AM) override { + return make_unique<ResultModelT>(Pass.run(IR, AM)); } /// \brief The model delegates to a static \c PassT::name method. diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index df4702653cf..cdbc2a24bf3 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -516,9 +516,8 @@ bool PassBuilder::parseModulePass(ModulePassManager &MPM, } #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ - MPM.addPass( \ - RequireAnalysisPass< \ - std::remove_reference<decltype(CREATE_PASS)>::type, Module>()); \ + MPM.addPass(RequireAnalysisPass< \ + std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return true; \ } \ if (Name == "invalidate<" NAME ">") { \ @@ -579,8 +578,7 @@ bool PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ CGPM.addPass(RequireAnalysisPass< \ - std::remove_reference<decltype(CREATE_PASS)>::type, \ - LazyCallGraph::SCC>()); \ + std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return true; \ } \ if (Name == "invalidate<" NAME ">") { \ @@ -639,9 +637,8 @@ bool PassBuilder::parseFunctionPass(FunctionPassManager &FPM, } #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ - FPM.addPass( \ - RequireAnalysisPass< \ - std::remove_reference<decltype(CREATE_PASS)>::type, Function>()); \ + FPM.addPass(RequireAnalysisPass< \ + std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return true; \ } \ if (Name == "invalidate<" NAME ">") { \ @@ -691,7 +688,7 @@ bool PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, #define LOOP_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">") { \ LPM.addPass(RequireAnalysisPass< \ - std::remove_reference<decltype(CREATE_PASS)>::type, Loop>()); \ + std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return true; \ } \ if (Name == "invalidate<" NAME ">") { \ diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp index 47fb8b70f1b..c2ac863260a 100644 --- a/llvm/unittests/IR/PassManagerTest.cpp +++ b/llvm/unittests/IR/PassManagerTest.cpp @@ -331,61 +331,4 @@ TEST_F(PassManagerTest, Basic) { EXPECT_EQ(1, ModuleAnalysisRuns); } - -// A customized pass manager that passes extra arguments through the -// infrastructure. -typedef AnalysisManager<Function, int> CustomizedAnalysisManager; -typedef PassManager<Function, CustomizedAnalysisManager, int, int &> - CustomizedPassManager; - -class CustomizedAnalysis : public AnalysisInfoMixin<CustomizedAnalysis> { -public: - struct Result { - Result(int I) : I(I) {} - int I; - }; - - Result run(Function &F, CustomizedAnalysisManager &AM, int I) { - return Result(I); - } - -private: - friend AnalysisInfoMixin<CustomizedAnalysis>; - static char PassID; -}; - -char CustomizedAnalysis::PassID; - -struct CustomizedPass : PassInfoMixin<CustomizedPass> { - std::function<void(CustomizedAnalysis::Result &, int &)> Callback; - - template <typename CallbackT> - CustomizedPass(CallbackT Callback) : Callback(Callback) {} - - PreservedAnalyses run(Function &F, CustomizedAnalysisManager &AM, int I, - int &O) { - Callback(AM.getResult<CustomizedAnalysis>(F, I), O); - return PreservedAnalyses::none(); - } -}; - -TEST_F(PassManagerTest, CustomizedPassManagerArgs) { - CustomizedAnalysisManager AM; - AM.registerPass([&] { return CustomizedAnalysis(); }); - - CustomizedPassManager PM; - - // Add an instance of the customized pass that just accumulates the input - // after it is round-tripped through the analysis. - int Result = 0; - PM.addPass( - CustomizedPass([](CustomizedAnalysis::Result &R, int &O) { O += R.I; })); - - // Run this over every function with the input of 42. - for (Function &F : *M) - PM.run(F, AM, 42, Result); - - // And ensure that we accumulated the correct result. - EXPECT_EQ(42 * (int)M->size(), Result); -} } |

