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 RequireCodeGenSCCOrder = false,
138                              bool VerifyMachineFunction = false)
139       : 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