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 
MachineFunctionAnalysisManager()43   MachineFunctionAnalysisManager() : Base(), FAM(nullptr), MAM(nullptr) {}
MachineFunctionAnalysisManager(FunctionAnalysisManager & FAM,ModuleAnalysisManager & MAM)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.
getResult(Function & F)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>
getCachedResult(Function & F)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.
getResult(Module & M)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.
getCachedResult(Module & M)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)
Base()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 
addPass(PassT && Pass)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>
addDoInitialization(PassConceptT * Pass)171   addDoInitialization(PassConceptT *Pass) {}
172 
173   template <typename PassT>
174   std::enable_if_t<is_detected<has_init_t, PassT>::value>
addDoInitialization(PassConceptT * Pass)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>
addDoFinalization(PassConceptT * Pass)193   addDoFinalization(PassConceptT *Pass) {}
194 
195   template <typename PassT>
196   std::enable_if_t<is_detected<has_fini_t, PassT>::value>
addDoFinalization(PassConceptT * Pass)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>
addRunOnModule(PassConceptT * Pass)220   addRunOnModule(PassConceptT *Pass) {}
221 
222   template <typename PassT>
223   std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
addRunOnModule(PassConceptT * Pass)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