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 
31 namespace llvm {
32 class Module;
33 class Function;
34 class MachineFunction;
35 
36 extern template class AnalysisManager<MachineFunction>;
37 using MachineFunctionAnalysisManager = AnalysisManager<MachineFunction>;
38 
39 namespace detail {
40 
41 template <typename PassT>
42 struct MachinePassModel
43     : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager> {
MachinePassModelMachinePassModel44   explicit MachinePassModel(PassT &&Pass)
45       : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>(
46             std::move(Pass)) {}
47 
swapMachinePassModel48   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;
runMachinePassModel59   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(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(errs());
72         errs() << '\n';
73         report_fatal_error("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 
87 private:
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 
102 using MachineFunctionAnalysisManagerModuleProxy =
103     InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Module>;
104 
105 template <>
106 bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
107     Module &M, const PreservedAnalyses &PA,
108     ModuleAnalysisManager::Invalidator &Inv);
109 extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
110                                                 Module>;
111 using MachineFunctionAnalysisManagerFunctionProxy =
112     InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Function>;
113 
114 template <>
115 bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate(
116     Function &F, const PreservedAnalyses &PA,
117     FunctionAnalysisManager::Invalidator &Inv);
118 extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
119                                                 Function>;
120 
121 extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
122                                                 MachineFunction>;
123 /// Provide the \c ModuleAnalysisManager to \c Function proxy.
124 using ModuleAnalysisManagerMachineFunctionProxy =
125     OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
126 
127 class FunctionAnalysisManagerMachineFunctionProxy
128     : public AnalysisInfoMixin<FunctionAnalysisManagerMachineFunctionProxy> {
129 public:
130   class Result {
131   public:
Result(FunctionAnalysisManager & FAM)132     explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
133 
Result(Result && Arg)134     Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
135       // We have to null out the analysis manager in the moved-from state
136       // because we are taking ownership of the responsibilty to clear the
137       // analysis state.
138       Arg.FAM = nullptr;
139     }
140 
141     Result &operator=(Result &&RHS) {
142       FAM = RHS.FAM;
143       // We have to null out the analysis manager in the moved-from state
144       // because we are taking ownership of the responsibilty to clear the
145       // analysis state.
146       RHS.FAM = nullptr;
147       return *this;
148     }
149 
150     /// Accessor for the analysis manager.
getManager()151     FunctionAnalysisManager &getManager() { return *FAM; }
152 
153     /// Handler for invalidation of the outer IR unit, \c IRUnitT.
154     ///
155     /// If the proxy analysis itself is not preserved, we assume that the set of
156     /// inner IR objects contained in IRUnit may have changed.  In this case,
157     /// we have to call \c clear() on the inner analysis manager, as it may now
158     /// have stale pointers to its inner IR objects.
159     ///
160     /// Regardless of whether the proxy analysis is marked as preserved, all of
161     /// the analyses in the inner analysis manager are potentially invalidated
162     /// based on the set of preserved analyses.
163     bool invalidate(MachineFunction &IR, const PreservedAnalyses &PA,
164                     MachineFunctionAnalysisManager::Invalidator &Inv);
165 
166   private:
167     FunctionAnalysisManager *FAM;
168   };
169 
FunctionAnalysisManagerMachineFunctionProxy(FunctionAnalysisManager & FAM)170   explicit FunctionAnalysisManagerMachineFunctionProxy(
171       FunctionAnalysisManager &FAM)
172       : FAM(&FAM) {}
173 
174   /// Run the analysis pass and create our proxy result object.
175   ///
176   /// This doesn't do any interesting work; it is primarily used to insert our
177   /// proxy result object into the outer analysis cache so that we can proxy
178   /// invalidation to the inner analysis manager.
run(MachineFunction &,MachineFunctionAnalysisManager &)179   Result run(MachineFunction &, MachineFunctionAnalysisManager &) {
180     return Result(*FAM);
181   }
182 
183   static AnalysisKey Key;
184 
185 private:
186   FunctionAnalysisManager *FAM;
187 };
188 
189 class FunctionToMachineFunctionPassAdaptor
190     : public PassInfoMixin<FunctionToMachineFunctionPassAdaptor> {
191 public:
192   using PassConceptT =
193       detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
194 
FunctionToMachineFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass)195   explicit FunctionToMachineFunctionPassAdaptor(
196       std::unique_ptr<PassConceptT> Pass)
197       : Pass(std::move(Pass)) {}
198 
199   /// Runs the function pass across every function in the function.
200   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
201   void printPipeline(raw_ostream &OS,
202                      function_ref<StringRef(StringRef)> MapClassName2PassName);
203 
isRequired()204   static bool isRequired() { return true; }
205 
206 private:
207   std::unique_ptr<PassConceptT> Pass;
208 };
209 
210 template <typename MachineFunctionPassT>
211 FunctionToMachineFunctionPassAdaptor
createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT && Pass)212 createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
213   using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT,
214                                        MachineFunctionAnalysisManager>;
215   // Do not use make_unique, it causes too many template instantiations,
216   // causing terrible compile times.
217   return FunctionToMachineFunctionPassAdaptor(
218       std::unique_ptr<FunctionToMachineFunctionPassAdaptor::PassConceptT>(
219           new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
220 }
221 
222 template <>
223 template <typename PassT>
addPass(PassT && Pass)224 void PassManager<MachineFunction>::addPass(PassT &&Pass) {
225   using MachinePassModelT = detail::MachinePassModel<PassT>;
226   // Do not use make_unique or emplace_back, they cause too many template
227   // instantiations, causing terrible compile times.
228   if constexpr (std::is_same_v<PassT, PassManager<MachineFunction>>) {
229     for (auto &P : Pass.Passes)
230       Passes.push_back(std::move(P));
231   } else {
232     Passes.push_back(std::unique_ptr<MachinePassModelT>(
233         new MachinePassModelT(std::forward<PassT>(Pass))));
234   }
235 }
236 
237 template <>
238 PreservedAnalyses
239 PassManager<MachineFunction>::run(MachineFunction &,
240                                   AnalysisManager<MachineFunction> &);
241 extern template class PassManager<MachineFunction>;
242 
243 /// Convenience typedef for a pass manager over functions.
244 using MachineFunctionPassManager = PassManager<MachineFunction>;
245 
246 /// Returns the minimum set of Analyses that all machine function passes must
247 /// preserve.
248 PreservedAnalyses getMachineFunctionPassPreservedAnalyses();
249 
250 } // end namespace llvm
251 
252 #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
253