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