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

source code of llvm/include/llvm/CodeGen/MachinePassManager.h