| 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: |
| 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 | |
| 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: |
| 134 | explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} |
| 135 | |
| 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. |
| 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 | |
| 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. |
| 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 | |
| 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 | |
| 207 | static bool isRequired() { return true; } |
| 208 | |
| 209 | private: |
| 210 | std::unique_ptr<PassConceptT> Pass; |
| 211 | }; |
| 212 | |
| 213 | template <typename MachineFunctionPassT> |
| 214 | FunctionToMachineFunctionPassAdaptor |
| 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 | |