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