xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/MachinePassManager.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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