blob: 1489177d9668d510d9bf4f05ef3a757c32fbcbf9 [file] [log] [blame]
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001//===- 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
33namespace llvm {
34class Module;
35
36extern template class AnalysisManager<MachineFunction>;
37
38/// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
39class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
40public:
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
102extern 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).
131class MachineFunctionPassManager
132 : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
133 using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
134
135public:
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
164private:
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