| //===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This header defines the pass manager interface for codegen. The codegen |
| // pipeline consists of only machine function passes. There is no container |
| // relationship between IR module/function and machine function in terms of pass |
| // manager organization. So there is no need for adaptor classes (for example |
| // ModuleToMachineFunctionAdaptor). Since invalidation could only happen among |
| // machine function passes, there is no proxy classes to handle cross-IR-unit |
| // invalidation. IR analysis results are provided for machine function passes by |
| // their respective analysis managers such as ModuleAnalysisManager and |
| // FunctionAnalysisManager. |
| // |
| // TODO: Add MachineFunctionProperties support. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H |
| #define LLVM_CODEGEN_MACHINEPASSMANAGER_H |
| |
| #include "llvm/ADT/FunctionExtras.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/CodeGen/MachineFunction.h" |
| #include "llvm/IR/PassManager.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/Support/type_traits.h" |
| |
| namespace llvm { |
| class Module; |
| |
| extern template class AnalysisManager<MachineFunction>; |
| |
| /// An AnalysisManager<MachineFunction> that also exposes IR analysis results. |
| class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> { |
| public: |
| using Base = AnalysisManager<MachineFunction>; |
| |
| MachineFunctionAnalysisManager() : Base(false), FAM(nullptr), MAM(nullptr) {} |
| MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM, |
| ModuleAnalysisManager &MAM, |
| bool DebugLogging = false) |
| : Base(DebugLogging), FAM(&FAM), MAM(&MAM) {} |
| MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default; |
| MachineFunctionAnalysisManager & |
| operator=(MachineFunctionAnalysisManager &&) = default; |
| |
| /// Get the result of an analysis pass for a Function. |
| /// |
| /// Runs the analysis if a cached result is not available. |
| template <typename PassT> typename PassT::Result &getResult(Function &F) { |
| return FAM->getResult<PassT>(F); |
| } |
| |
| /// Get the cached result of an analysis pass for a Function. |
| /// |
| /// This method never runs the analysis. |
| /// |
| /// \returns null if there is no cached result. |
| template <typename PassT> |
| typename PassT::Result *getCachedResult(Function &F) { |
| return FAM->getCachedResult<PassT>(F); |
| } |
| |
| /// Get the result of an analysis pass for a Module. |
| /// |
| /// Runs the analysis if a cached result is not available. |
| template <typename PassT> typename PassT::Result &getResult(Module &M) { |
| return MAM->getResult<PassT>(M); |
| } |
| |
| /// Get the cached result of an analysis pass for a Module. |
| /// |
| /// This method never runs the analysis. |
| /// |
| /// \returns null if there is no cached result. |
| template <typename PassT> typename PassT::Result *getCachedResult(Module &M) { |
| return MAM->getCachedResult<PassT>(M); |
| } |
| |
| /// Get the result of an analysis pass for a MachineFunction. |
| /// |
| /// Runs the analysis if a cached result is not available. |
| using Base::getResult; |
| |
| /// Get the cached result of an analysis pass for a MachineFunction. |
| /// |
| /// This method never runs the analysis. |
| /// |
| /// returns null if there is no cached result. |
| using Base::getCachedResult; |
| |
| // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed. |
| FunctionAnalysisManager *FAM; |
| ModuleAnalysisManager *MAM; |
| }; |
| |
| extern template class PassManager<MachineFunction>; |
| |
| /// MachineFunctionPassManager adds/removes below features to/from the base |
| /// PassManager template instantiation. |
| /// |
| /// - Support passes that implement doInitialization/doFinalization. This is for |
| /// machine function passes to work on module level constructs. One such pass |
| /// is AsmPrinter. |
| /// |
| /// - Support machine module pass which runs over the module (for example, |
| /// MachineOutliner). A machine module pass needs to define the method: |
| /// |
| /// ```Error run(Module &, MachineFunctionAnalysisManager &)``` |
| /// |
| /// FIXME: machine module passes still need to define the usual machine |
| /// function pass interface, namely, |
| /// `PreservedAnalyses run(MachineFunction &, |
| /// MachineFunctionAnalysisManager &)` |
| /// But this interface wouldn't be executed. It is just a placeholder |
| /// to satisfy the pass manager type-erased inteface. This |
| /// special-casing of machine module pass is due to its limited use |
| /// cases and the unnecessary complexity it may bring to the machine |
| /// pass manager. |
| /// |
| /// - The base class `run` method is replaced by an alternative `run` method. |
| /// See details below. |
| /// |
| /// - Support codegening in the SCC order. Users include interprocedural |
| /// register allocation (IPRA). |
| class MachineFunctionPassManager |
| : public PassManager<MachineFunction, MachineFunctionAnalysisManager> { |
| using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>; |
| |
| public: |
| MachineFunctionPassManager(bool DebugLogging = false, |
| bool RequireCodeGenSCCOrder = false, |
| bool VerifyMachineFunction = false) |
| : Base(DebugLogging), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder), |
| VerifyMachineFunction(VerifyMachineFunction) {} |
| MachineFunctionPassManager(MachineFunctionPassManager &&) = default; |
| MachineFunctionPassManager & |
| operator=(MachineFunctionPassManager &&) = default; |
| |
| /// Run machine passes for a Module. |
| /// |
| /// The intended use is to start the codegen pipeline for a Module. The base |
| /// class's `run` method is deliberately hidden by this due to the observation |
| /// that we don't yet have the use cases of compositing two instances of |
| /// machine pass managers, or compositing machine pass managers with other |
| /// types of pass managers. |
| Error run(Module &M, MachineFunctionAnalysisManager &MFAM); |
| |
| template <typename PassT> void addPass(PassT &&Pass) { |
| Base::addPass(std::forward<PassT>(Pass)); |
| PassConceptT *P = Passes.back().get(); |
| addDoInitialization<PassT>(P); |
| addDoFinalization<PassT>(P); |
| |
| // Add machine module pass. |
| addRunOnModule<PassT>(P); |
| } |
| |
| private: |
| template <typename PassT> |
| using has_init_t = decltype(std::declval<PassT &>().doInitialization( |
| std::declval<Module &>(), |
| std::declval<MachineFunctionAnalysisManager &>())); |
| |
| template <typename PassT> |
| std::enable_if_t<!is_detected<has_init_t, PassT>::value> |
| addDoInitialization(PassConceptT *Pass) {} |
| |
| template <typename PassT> |
| std::enable_if_t<is_detected<has_init_t, PassT>::value> |
| addDoInitialization(PassConceptT *Pass) { |
| using PassModelT = |
| detail::PassModel<MachineFunction, PassT, PreservedAnalyses, |
| MachineFunctionAnalysisManager>; |
| auto *P = static_cast<PassModelT *>(Pass); |
| InitializationFuncs.emplace_back( |
| [=](Module &M, MachineFunctionAnalysisManager &MFAM) { |
| return P->Pass.doInitialization(M, MFAM); |
| }); |
| } |
| |
| template <typename PassT> |
| using has_fini_t = decltype(std::declval<PassT &>().doFinalization( |
| std::declval<Module &>(), |
| std::declval<MachineFunctionAnalysisManager &>())); |
| |
| template <typename PassT> |
| std::enable_if_t<!is_detected<has_fini_t, PassT>::value> |
| addDoFinalization(PassConceptT *Pass) {} |
| |
| template <typename PassT> |
| std::enable_if_t<is_detected<has_fini_t, PassT>::value> |
| addDoFinalization(PassConceptT *Pass) { |
| using PassModelT = |
| detail::PassModel<MachineFunction, PassT, PreservedAnalyses, |
| MachineFunctionAnalysisManager>; |
| auto *P = static_cast<PassModelT *>(Pass); |
| FinalizationFuncs.emplace_back( |
| [=](Module &M, MachineFunctionAnalysisManager &MFAM) { |
| return P->Pass.doFinalization(M, MFAM); |
| }); |
| } |
| |
| template <typename PassT> |
| using is_machine_module_pass_t = decltype(std::declval<PassT &>().run( |
| std::declval<Module &>(), |
| std::declval<MachineFunctionAnalysisManager &>())); |
| |
| template <typename PassT> |
| using is_machine_function_pass_t = decltype(std::declval<PassT &>().run( |
| std::declval<MachineFunction &>(), |
| std::declval<MachineFunctionAnalysisManager &>())); |
| |
| template <typename PassT> |
| std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value> |
| addRunOnModule(PassConceptT *Pass) {} |
| |
| template <typename PassT> |
| std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value> |
| addRunOnModule(PassConceptT *Pass) { |
| static_assert(is_detected<is_machine_function_pass_t, PassT>::value, |
| "machine module pass needs to define machine function pass " |
| "api. sorry."); |
| |
| using PassModelT = |
| detail::PassModel<MachineFunction, PassT, PreservedAnalyses, |
| MachineFunctionAnalysisManager>; |
| auto *P = static_cast<PassModelT *>(Pass); |
| MachineModulePasses.emplace( |
| Passes.size() - 1, |
| [=](Module &M, MachineFunctionAnalysisManager &MFAM) { |
| return P->Pass.run(M, MFAM); |
| }); |
| } |
| |
| using FuncTy = Error(Module &, MachineFunctionAnalysisManager &); |
| SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs; |
| SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs; |
| |
| using PassIndex = decltype(Passes)::size_type; |
| std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses; |
| |
| // Run codegen in the SCC order. |
| bool RequireCodeGenSCCOrder; |
| |
| bool VerifyMachineFunction; |
| }; |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H |