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