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 //===----------------------------------------------------------------------===//
20
21 #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
22 #define LLVM_CODEGEN_MACHINEPASSMANAGER_H
23
24 #include "llvm/ADT/FunctionExtras.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/CodeGen/MachineFunction.h"
27 #include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
28 #include "llvm/IR/PassManager.h"
29 #include "llvm/IR/PassManagerInternal.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Error.h"
32
33 namespace llvm {
34 class Module;
35 class Function;
36
37 /// An RAII based helper class to modify MachineFunctionProperties when running
38 /// pass. Define a MFPropsModifier in PassT::run to set
39 /// MachineFunctionProperties properly.
40 template <typename PassT> class MFPropsModifier {
41 public:
MFPropsModifier(const PassT & P_,MachineFunction & MF_)42 MFPropsModifier(const PassT &P_, MachineFunction &MF_) : P(P_), MF(MF_) {
43 auto &MFProps = MF.getProperties();
44 #ifndef NDEBUG
45 if constexpr (has_get_required_properties_v<PassT>) {
46 auto &MFProps = MF.getProperties();
47 auto RequiredProperties = P.getRequiredProperties();
48 if (!MFProps.verifyRequiredProperties(RequiredProperties)) {
49 errs() << "MachineFunctionProperties required by " << PassT::name()
50 << " pass are not met by function " << MF.getName() << ".\n"
51 << "Required properties: ";
52 RequiredProperties.print(errs());
53 errs() << "\nCurrent properties: ";
54 MFProps.print(errs());
55 errs() << '\n';
56 report_fatal_error("MachineFunctionProperties check failed");
57 }
58 }
59 #endif // NDEBUG
60 if constexpr (has_get_cleared_properties_v<PassT>)
61 MFProps.reset(P.getClearedProperties());
62 }
63
~MFPropsModifier()64 ~MFPropsModifier() {
65 if constexpr (has_get_set_properties_v<PassT>) {
66 auto &MFProps = MF.getProperties();
67 MFProps.set(P.getSetProperties());
68 }
69 }
70
71 private:
72 const PassT &P;
73 MachineFunction &MF;
74
75 template <typename T>
76 using has_get_required_properties_t =
77 decltype(std::declval<T &>().getRequiredProperties());
78
79 template <typename T>
80 using has_get_set_properties_t =
81 decltype(std::declval<T &>().getSetProperties());
82
83 template <typename T>
84 using has_get_cleared_properties_t =
85 decltype(std::declval<T &>().getClearedProperties());
86
87 template <typename T>
88 static constexpr bool has_get_required_properties_v =
89 is_detected<has_get_required_properties_t, T>::value;
90
91 template <typename T>
92 static constexpr bool has_get_set_properties_v =
93 is_detected<has_get_set_properties_t, T>::value;
94
95 template <typename T>
96 static constexpr bool has_get_cleared_properties_v =
97 is_detected<has_get_cleared_properties_t, T>::value;
98 };
99
100 // Additional deduction guide to suppress warning.
101 template <typename PassT>
102 MFPropsModifier(PassT &P, MachineFunction &MF) -> MFPropsModifier<PassT>;
103
104 using MachineFunctionAnalysisManagerModuleProxy =
105 InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Module>;
106
107 template <>
108 LLVM_ABI bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
109 Module &M, const PreservedAnalyses &PA,
110 ModuleAnalysisManager::Invalidator &Inv);
111 extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
112 Module>;
113 using MachineFunctionAnalysisManagerFunctionProxy =
114 InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Function>;
115
116 template <>
117 LLVM_ABI bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate(
118 Function &F, const PreservedAnalyses &PA,
119 FunctionAnalysisManager::Invalidator &Inv);
120 extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
121 Function>;
122
123 extern template class LLVM_TEMPLATE_ABI
124 OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
125 /// Provide the \c ModuleAnalysisManager to \c Function proxy.
126 using ModuleAnalysisManagerMachineFunctionProxy =
127 OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
128
129 class FunctionAnalysisManagerMachineFunctionProxy
130 : public AnalysisInfoMixin<FunctionAnalysisManagerMachineFunctionProxy> {
131 public:
132 class Result {
133 public:
Result(FunctionAnalysisManager & FAM)134 explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
135
Result(Result && Arg)136 Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
137 // We have to null out the analysis manager in the moved-from state
138 // because we are taking ownership of the responsibilty to clear the
139 // analysis state.
140 Arg.FAM = nullptr;
141 }
142
143 Result &operator=(Result &&RHS) {
144 FAM = RHS.FAM;
145 // We have to null out the analysis manager in the moved-from state
146 // because we are taking ownership of the responsibilty to clear the
147 // analysis state.
148 RHS.FAM = nullptr;
149 return *this;
150 }
151
152 /// Accessor for the analysis manager.
getManager()153 FunctionAnalysisManager &getManager() { return *FAM; }
154
155 /// Handler for invalidation of the outer IR unit, \c IRUnitT.
156 ///
157 /// If the proxy analysis itself is not preserved, we assume that the set of
158 /// inner IR objects contained in IRUnit may have changed. In this case,
159 /// we have to call \c clear() on the inner analysis manager, as it may now
160 /// have stale pointers to its inner IR objects.
161 ///
162 /// Regardless of whether the proxy analysis is marked as preserved, all of
163 /// the analyses in the inner analysis manager are potentially invalidated
164 /// based on the set of preserved analyses.
165 LLVM_ABI bool invalidate(MachineFunction &IR, const PreservedAnalyses &PA,
166 MachineFunctionAnalysisManager::Invalidator &Inv);
167
168 private:
169 FunctionAnalysisManager *FAM;
170 };
171
FunctionAnalysisManagerMachineFunctionProxy(FunctionAnalysisManager & FAM)172 explicit FunctionAnalysisManagerMachineFunctionProxy(
173 FunctionAnalysisManager &FAM)
174 : FAM(&FAM) {}
175
176 /// Run the analysis pass and create our proxy result object.
177 ///
178 /// This doesn't do any interesting work; it is primarily used to insert our
179 /// proxy result object into the outer analysis cache so that we can proxy
180 /// invalidation to the inner analysis manager.
run(MachineFunction &,MachineFunctionAnalysisManager &)181 Result run(MachineFunction &, MachineFunctionAnalysisManager &) {
182 return Result(*FAM);
183 }
184
185 LLVM_ABI static AnalysisKey Key;
186
187 private:
188 FunctionAnalysisManager *FAM;
189 };
190
191 class FunctionToMachineFunctionPassAdaptor
192 : public PassInfoMixin<FunctionToMachineFunctionPassAdaptor> {
193 public:
194 using PassConceptT =
195 detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
196
FunctionToMachineFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass)197 explicit FunctionToMachineFunctionPassAdaptor(
198 std::unique_ptr<PassConceptT> Pass)
199 : Pass(std::move(Pass)) {}
200
201 /// Runs the function pass across every function in the function.
202 LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
203 LLVM_ABI void
204 printPipeline(raw_ostream &OS,
205 function_ref<StringRef(StringRef)> MapClassName2PassName);
206
isRequired()207 static bool isRequired() { return true; }
208
209 private:
210 std::unique_ptr<PassConceptT> Pass;
211 };
212
213 template <typename MachineFunctionPassT>
214 FunctionToMachineFunctionPassAdaptor
createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT && Pass)215 createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
216 using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT,
217 MachineFunctionAnalysisManager>;
218 // Do not use make_unique, it causes too many template instantiations,
219 // causing terrible compile times.
220 return FunctionToMachineFunctionPassAdaptor(
221 std::unique_ptr<FunctionToMachineFunctionPassAdaptor::PassConceptT>(
222 new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
223 }
224
225 template <>
226 LLVM_ABI PreservedAnalyses PassManager<MachineFunction>::run(
227 MachineFunction &, AnalysisManager<MachineFunction> &);
228 extern template class PassManager<MachineFunction>;
229
230 /// Convenience typedef for a pass manager over functions.
231 using MachineFunctionPassManager = PassManager<MachineFunction>;
232
233 /// Returns the minimum set of Analyses that all machine function passes must
234 /// preserve.
235 LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses();
236
237 } // end namespace llvm
238
239 #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
240