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