Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This header defines the pass manager interface for codegen. The codegen
     10 // pipeline consists of only machine function passes. There is no container
     11 // relationship between IR module/function and machine function in terms of pass
     12 // manager organization. So there is no need for adaptor classes (for example
     13 // ModuleToMachineFunctionAdaptor). Since invalidation could only happen among
     14 // machine function passes, there is no proxy classes to handle cross-IR-unit
     15 // invalidation. IR analysis results are provided for machine function passes by
     16 // their respective analysis managers such as ModuleAnalysisManager and
     17 // FunctionAnalysisManager.
     18 //
     19 // TODO: Add MachineFunctionProperties support.
     20 //
     21 //===----------------------------------------------------------------------===//
     22 
     23 #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
     24 #define LLVM_CODEGEN_MACHINEPASSMANAGER_H
     25 
     26 #include "llvm/ADT/FunctionExtras.h"
     27 #include "llvm/ADT/SmallVector.h"
     28 #include "llvm/CodeGen/MachineFunction.h"
     29 #include "llvm/IR/PassManager.h"
     30 #include "llvm/Support/Error.h"
     31 #include "llvm/Support/type_traits.h"
     32 
     33 namespace llvm {
     34 class Module;
     35 
     36 extern template class AnalysisManager<MachineFunction>;
     37 
     38 /// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
     39 class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
     40 public:
     41   using Base = AnalysisManager<MachineFunction>;
     42 
     43   MachineFunctionAnalysisManager() : Base(), FAM(nullptr), MAM(nullptr) {}
     44   MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
     45                                  ModuleAnalysisManager &MAM)
     46       : Base(), FAM(&FAM), MAM(&MAM) {}
     47   MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
     48   MachineFunctionAnalysisManager &
     49   operator=(MachineFunctionAnalysisManager &&) = default;
     50 
     51   /// Get the result of an analysis pass for a Function.
     52   ///
     53   /// Runs the analysis if a cached result is not available.
     54   template <typename PassT> typename PassT::Result &getResult(Function &F) {
     55     return FAM->getResult<PassT>(F);
     56   }
     57 
     58   /// Get the cached result of an analysis pass for a Function.
     59   ///
     60   /// This method never runs the analysis.
     61   ///
     62   /// \returns null if there is no cached result.
     63   template <typename PassT>
     64   typename PassT::Result *getCachedResult(Function &F) {
     65     return FAM->getCachedResult<PassT>(F);
     66   }
     67 
     68   /// Get the result of an analysis pass for a Module.
     69   ///
     70   /// Runs the analysis if a cached result is not available.
     71   template <typename PassT> typename PassT::Result &getResult(Module &M) {
     72     return MAM->getResult<PassT>(M);
     73   }
     74 
     75   /// Get the cached result of an analysis pass for a Module.
     76   ///
     77   /// This method never runs the analysis.
     78   ///
     79   /// \returns null if there is no cached result.
     80   template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
     81     return MAM->getCachedResult<PassT>(M);
     82   }
     83 
     84   /// Get the result of an analysis pass for a MachineFunction.
     85   ///
     86   /// Runs the analysis if a cached result is not available.
     87   using Base::getResult;
     88 
     89   /// Get the cached result of an analysis pass for a MachineFunction.
     90   ///
     91   /// This method never runs the analysis.
     92   ///
     93   /// returns null if there is no cached result.
     94   using Base::getCachedResult;
     95 
     96   // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
     97   FunctionAnalysisManager *FAM;
     98   ModuleAnalysisManager *MAM;
     99 };
    100 
    101 extern template class PassManager<MachineFunction>;
    102 
    103 /// MachineFunctionPassManager adds/removes below features to/from the base
    104 /// PassManager template instantiation.
    105 ///
    106 /// - Support passes that implement doInitialization/doFinalization. This is for
    107 ///   machine function passes to work on module level constructs. One such pass
    108 ///   is AsmPrinter.
    109 ///
    110 /// - Support machine module pass which runs over the module (for example,
    111 ///   MachineOutliner). A machine module pass needs to define the method:
    112 ///
    113 ///   ```Error run(Module &, MachineFunctionAnalysisManager &)```
    114 ///
    115 ///   FIXME: machine module passes still need to define the usual machine
    116 ///          function pass interface, namely,
    117 ///          `PreservedAnalyses run(MachineFunction &,
    118 ///                                 MachineFunctionAnalysisManager &)`
    119 ///          But this interface wouldn't be executed. It is just a placeholder
    120 ///          to satisfy the pass manager type-erased inteface. This
    121 ///          special-casing of machine module pass is due to its limited use
    122 ///          cases and the unnecessary complexity it may bring to the machine
    123 ///          pass manager.
    124 ///
    125 /// - The base class `run` method is replaced by an alternative `run` method.
    126 ///   See details below.
    127 ///
    128 /// - Support codegening in the SCC order. Users include interprocedural
    129 ///   register allocation (IPRA).
    130 class MachineFunctionPassManager
    131     : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
    132   using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
    133 
    134 public:
    135   MachineFunctionPassManager(bool DebugLogging = false,
    136                              bool RequireCodeGenSCCOrder = false,
    137                              bool VerifyMachineFunction = false)
    138       : Base(), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder),
    139         VerifyMachineFunction(VerifyMachineFunction) {}
    140   MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
    141   MachineFunctionPassManager &
    142   operator=(MachineFunctionPassManager &&) = default;
    143 
    144   /// Run machine passes for a Module.
    145   ///
    146   /// The intended use is to start the codegen pipeline for a Module. The base
    147   /// class's `run` method is deliberately hidden by this due to the observation
    148   /// that we don't yet have the use cases of compositing two instances of
    149   /// machine pass managers, or compositing machine pass managers with other
    150   /// types of pass managers.
    151   Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
    152 
    153   template <typename PassT> void addPass(PassT &&Pass) {
    154     Base::addPass(std::forward<PassT>(Pass));
    155     PassConceptT *P = Passes.back().get();
    156     addDoInitialization<PassT>(P);
    157     addDoFinalization<PassT>(P);
    158 
    159     // Add machine module pass.
    160     addRunOnModule<PassT>(P);
    161   }
    162 
    163 private:
    164   template <typename PassT>
    165   using has_init_t = decltype(std::declval<PassT &>().doInitialization(
    166       std::declval<Module &>(),
    167       std::declval<MachineFunctionAnalysisManager &>()));
    168 
    169   template <typename PassT>
    170   std::enable_if_t<!is_detected<has_init_t, PassT>::value>
    171   addDoInitialization(PassConceptT *Pass) {}
    172 
    173   template <typename PassT>
    174   std::enable_if_t<is_detected<has_init_t, PassT>::value>
    175   addDoInitialization(PassConceptT *Pass) {
    176     using PassModelT =
    177         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
    178                           MachineFunctionAnalysisManager>;
    179     auto *P = static_cast<PassModelT *>(Pass);
    180     InitializationFuncs.emplace_back(
    181         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
    182           return P->Pass.doInitialization(M, MFAM);
    183         });
    184   }
    185 
    186   template <typename PassT>
    187   using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
    188       std::declval<Module &>(),
    189       std::declval<MachineFunctionAnalysisManager &>()));
    190 
    191   template <typename PassT>
    192   std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
    193   addDoFinalization(PassConceptT *Pass) {}
    194 
    195   template <typename PassT>
    196   std::enable_if_t<is_detected<has_fini_t, PassT>::value>
    197   addDoFinalization(PassConceptT *Pass) {
    198     using PassModelT =
    199         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
    200                           MachineFunctionAnalysisManager>;
    201     auto *P = static_cast<PassModelT *>(Pass);
    202     FinalizationFuncs.emplace_back(
    203         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
    204           return P->Pass.doFinalization(M, MFAM);
    205         });
    206   }
    207 
    208   template <typename PassT>
    209   using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
    210       std::declval<Module &>(),
    211       std::declval<MachineFunctionAnalysisManager &>()));
    212 
    213   template <typename PassT>
    214   using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
    215       std::declval<MachineFunction &>(),
    216       std::declval<MachineFunctionAnalysisManager &>()));
    217 
    218   template <typename PassT>
    219   std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
    220   addRunOnModule(PassConceptT *Pass) {}
    221 
    222   template <typename PassT>
    223   std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
    224   addRunOnModule(PassConceptT *Pass) {
    225     static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
    226                   "machine module pass needs to define machine function pass "
    227                   "api. sorry.");
    228 
    229     using PassModelT =
    230         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
    231                           MachineFunctionAnalysisManager>;
    232     auto *P = static_cast<PassModelT *>(Pass);
    233     MachineModulePasses.emplace(
    234         Passes.size() - 1,
    235         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
    236           return P->Pass.run(M, MFAM);
    237         });
    238   }
    239 
    240   using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
    241   SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
    242   SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
    243 
    244   using PassIndex = decltype(Passes)::size_type;
    245   std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
    246 
    247   // Run codegen in the SCC order.
    248   bool RequireCodeGenSCCOrder;
    249 
    250   bool VerifyMachineFunction;
    251 };
    252 
    253 } // end namespace llvm
    254 
    255 #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
    256