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

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