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/IR/PassManager.h"
29 #include "llvm/Support/Error.h"
30 
31 #include <map>
32 
33 namespace llvm {
34 class Module;
35 class Function;
36 class MachineFunction;
37 
38 extern template class AnalysisManager<MachineFunction>;
39 
40 /// Like \c AnalysisKey, but only for machine passes.
41 struct alignas(8) MachinePassKey {};
42 
43 /// A CRTP mix-in that provides informational APIs needed for machine passes.
44 ///
45 /// This provides some boilerplate for types that are machine passes. It
46 /// automatically mixes in \c PassInfoMixin.
47 template <typename DerivedT>
48 struct MachinePassInfoMixin : public PassInfoMixin<DerivedT> {
49   static MachinePassKey *ID() {
50     static_assert(std::is_base_of<MachinePassInfoMixin, DerivedT>::value,
51                   "Must pass the derived type as the template argument!");
52     return &DerivedT::Key;
53   }
54 };
55 
56 /// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
57 class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
58 public:
59   using Base = AnalysisManager<MachineFunction>;
60 
61   MachineFunctionAnalysisManager() : FAM(nullptr), MAM(nullptr) {}
62   MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
63                                  ModuleAnalysisManager &MAM)
64       : FAM(&FAM), MAM(&MAM) {}
65   MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
66   MachineFunctionAnalysisManager &
67   operator=(MachineFunctionAnalysisManager &&) = default;
68 
69   /// Get the result of an analysis pass for a Function.
70   ///
71   /// Runs the analysis if a cached result is not available.
72   template <typename PassT> typename PassT::Result &getResult(Function &F) {
73     return FAM->getResult<PassT>(F);
74   }
75 
76   /// Get the cached result of an analysis pass for a Function.
77   ///
78   /// This method never runs the analysis.
79   ///
80   /// \returns null if there is no cached result.
81   template <typename PassT>
82   typename PassT::Result *getCachedResult(Function &F) {
83     return FAM->getCachedResult<PassT>(F);
84   }
85 
86   /// Get the result of an analysis pass for a Module.
87   ///
88   /// Runs the analysis if a cached result is not available.
89   template <typename PassT> typename PassT::Result &getResult(Module &M) {
90     return MAM->getResult<PassT>(M);
91   }
92 
93   /// Get the cached result of an analysis pass for a Module.
94   ///
95   /// This method never runs the analysis.
96   ///
97   /// \returns null if there is no cached result.
98   template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
99     return MAM->getCachedResult<PassT>(M);
100   }
101 
102   /// Get the result of an analysis pass for a MachineFunction.
103   ///
104   /// Runs the analysis if a cached result is not available.
105   using Base::getResult;
106 
107   /// Get the cached result of an analysis pass for a MachineFunction.
108   ///
109   /// This method never runs the analysis.
110   ///
111   /// returns null if there is no cached result.
112   using Base::getCachedResult;
113 
114   // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
115   FunctionAnalysisManager *FAM;
116   ModuleAnalysisManager *MAM;
117 };
118 
119 extern template class PassManager<MachineFunction>;
120 
121 /// MachineFunctionPassManager adds/removes below features to/from the base
122 /// PassManager template instantiation.
123 ///
124 /// - Support passes that implement doInitialization/doFinalization. This is for
125 ///   machine function passes to work on module level constructs. One such pass
126 ///   is AsmPrinter.
127 ///
128 /// - Support machine module pass which runs over the module (for example,
129 ///   MachineOutliner). A machine module pass needs to define the method:
130 ///
131 ///   ```Error run(Module &, MachineFunctionAnalysisManager &)```
132 ///
133 ///   FIXME: machine module passes still need to define the usual machine
134 ///          function pass interface, namely,
135 ///          `PreservedAnalyses run(MachineFunction &,
136 ///                                 MachineFunctionAnalysisManager &)`
137 ///          But this interface wouldn't be executed. It is just a placeholder
138 ///          to satisfy the pass manager type-erased inteface. This
139 ///          special-casing of machine module pass is due to its limited use
140 ///          cases and the unnecessary complexity it may bring to the machine
141 ///          pass manager.
142 ///
143 /// - The base class `run` method is replaced by an alternative `run` method.
144 ///   See details below.
145 ///
146 /// - Support codegening in the SCC order. Users include interprocedural
147 ///   register allocation (IPRA).
148 class MachineFunctionPassManager
149     : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
150   using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
151 
152 public:
153   MachineFunctionPassManager(bool RequireCodeGenSCCOrder = false,
154                              bool VerifyMachineFunction = false)
155       : RequireCodeGenSCCOrder(RequireCodeGenSCCOrder),
156         VerifyMachineFunction(VerifyMachineFunction) {}
157   MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
158   MachineFunctionPassManager &
159   operator=(MachineFunctionPassManager &&) = default;
160 
161   /// Run machine passes for a Module.
162   ///
163   /// The intended use is to start the codegen pipeline for a Module. The base
164   /// class's `run` method is deliberately hidden by this due to the observation
165   /// that we don't yet have the use cases of compositing two instances of
166   /// machine pass managers, or compositing machine pass managers with other
167   /// types of pass managers.
168   Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
169 
170   template <typename PassT> void addPass(PassT &&Pass) {
171     Base::addPass(std::forward<PassT>(Pass));
172     PassConceptT *P = Passes.back().get();
173     addDoInitialization<PassT>(P);
174     addDoFinalization<PassT>(P);
175 
176     // Add machine module pass.
177     addRunOnModule<PassT>(P);
178   }
179 
180 private:
181   template <typename PassT>
182   using has_init_t = decltype(std::declval<PassT &>().doInitialization(
183       std::declval<Module &>(),
184       std::declval<MachineFunctionAnalysisManager &>()));
185 
186   template <typename PassT>
187   std::enable_if_t<!is_detected<has_init_t, PassT>::value>
188   addDoInitialization(PassConceptT *Pass) {}
189 
190   template <typename PassT>
191   std::enable_if_t<is_detected<has_init_t, PassT>::value>
192   addDoInitialization(PassConceptT *Pass) {
193     using PassModelT =
194         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
195                           MachineFunctionAnalysisManager>;
196     auto *P = static_cast<PassModelT *>(Pass);
197     InitializationFuncs.emplace_back(
198         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
199           return P->Pass.doInitialization(M, MFAM);
200         });
201   }
202 
203   template <typename PassT>
204   using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
205       std::declval<Module &>(),
206       std::declval<MachineFunctionAnalysisManager &>()));
207 
208   template <typename PassT>
209   std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
210   addDoFinalization(PassConceptT *Pass) {}
211 
212   template <typename PassT>
213   std::enable_if_t<is_detected<has_fini_t, PassT>::value>
214   addDoFinalization(PassConceptT *Pass) {
215     using PassModelT =
216         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
217                           MachineFunctionAnalysisManager>;
218     auto *P = static_cast<PassModelT *>(Pass);
219     FinalizationFuncs.emplace_back(
220         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
221           return P->Pass.doFinalization(M, MFAM);
222         });
223   }
224 
225   template <typename PassT>
226   using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
227       std::declval<Module &>(),
228       std::declval<MachineFunctionAnalysisManager &>()));
229 
230   template <typename PassT>
231   using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
232       std::declval<MachineFunction &>(),
233       std::declval<MachineFunctionAnalysisManager &>()));
234 
235   template <typename PassT>
236   std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
237   addRunOnModule(PassConceptT *Pass) {}
238 
239   template <typename PassT>
240   std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
241   addRunOnModule(PassConceptT *Pass) {
242     static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
243                   "machine module pass needs to define machine function pass "
244                   "api. sorry.");
245 
246     using PassModelT =
247         detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
248                           MachineFunctionAnalysisManager>;
249     auto *P = static_cast<PassModelT *>(Pass);
250     MachineModulePasses.emplace(
251         Passes.size() - 1,
252         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
253           return P->Pass.run(M, MFAM);
254         });
255   }
256 
257   using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
258   SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
259   SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
260 
261   using PassIndex = decltype(Passes)::size_type;
262   std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
263 
264   // Run codegen in the SCC order.
265   bool RequireCodeGenSCCOrder;
266 
267   bool VerifyMachineFunction;
268 };
269 
270 } // end namespace llvm
271 
272 #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
273