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 // TODO: Add MachineFunctionProperties support. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H 24 #define LLVM_CODEGEN_MACHINEPASSMANAGER_H 25 26 #include "llvm/ADT/FunctionExtras.h" 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/IR/PassManager.h" 29 #include "llvm/Support/Error.h" 30 31 #include <map> 32 33 namespace llvm { 34 class Module; 35 class Function; 36 class MachineFunction; 37 38 extern template class AnalysisManager<MachineFunction>; 39 40 /// Like \c AnalysisKey, but only for machine passes. 41 struct alignas(8) MachinePassKey {}; 42 43 /// A CRTP mix-in that provides informational APIs needed for machine passes. 44 /// 45 /// This provides some boilerplate for types that are machine passes. It 46 /// automatically mixes in \c PassInfoMixin. 47 template <typename DerivedT> 48 struct MachinePassInfoMixin : public PassInfoMixin<DerivedT> { IDMachinePassInfoMixin49 static MachinePassKey *ID() { 50 static_assert(std::is_base_of<MachinePassInfoMixin, DerivedT>::value, 51 "Must pass the derived type as the template argument!"); 52 return &DerivedT::Key; 53 } 54 }; 55 56 /// An AnalysisManager<MachineFunction> that also exposes IR analysis results. 57 class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> { 58 public: 59 using Base = AnalysisManager<MachineFunction>; 60 MachineFunctionAnalysisManager()61 MachineFunctionAnalysisManager() : FAM(nullptr), MAM(nullptr) {} MachineFunctionAnalysisManager(FunctionAnalysisManager & FAM,ModuleAnalysisManager & MAM)62 MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM, 63 ModuleAnalysisManager &MAM) 64 : FAM(&FAM), MAM(&MAM) {} 65 MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default; 66 MachineFunctionAnalysisManager & 67 operator=(MachineFunctionAnalysisManager &&) = default; 68 69 /// Get the result of an analysis pass for a Function. 70 /// 71 /// Runs the analysis if a cached result is not available. getResult(Function & F)72 template <typename PassT> typename PassT::Result &getResult(Function &F) { 73 return FAM->getResult<PassT>(F); 74 } 75 76 /// Get the cached result of an analysis pass for a Function. 77 /// 78 /// This method never runs the analysis. 79 /// 80 /// \returns null if there is no cached result. 81 template <typename PassT> getCachedResult(Function & F)82 typename PassT::Result *getCachedResult(Function &F) { 83 return FAM->getCachedResult<PassT>(F); 84 } 85 86 /// Get the result of an analysis pass for a Module. 87 /// 88 /// Runs the analysis if a cached result is not available. getResult(Module & M)89 template <typename PassT> typename PassT::Result &getResult(Module &M) { 90 return MAM->getResult<PassT>(M); 91 } 92 93 /// Get the cached result of an analysis pass for a Module. 94 /// 95 /// This method never runs the analysis. 96 /// 97 /// \returns null if there is no cached result. getCachedResult(Module & M)98 template <typename PassT> typename PassT::Result *getCachedResult(Module &M) { 99 return MAM->getCachedResult<PassT>(M); 100 } 101 102 /// Get the result of an analysis pass for a MachineFunction. 103 /// 104 /// Runs the analysis if a cached result is not available. 105 using Base::getResult; 106 107 /// Get the cached result of an analysis pass for a MachineFunction. 108 /// 109 /// This method never runs the analysis. 110 /// 111 /// returns null if there is no cached result. 112 using Base::getCachedResult; 113 114 // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed. 115 FunctionAnalysisManager *FAM; 116 ModuleAnalysisManager *MAM; 117 }; 118 119 extern template class PassManager<MachineFunction>; 120 121 /// MachineFunctionPassManager adds/removes below features to/from the base 122 /// PassManager template instantiation. 123 /// 124 /// - Support passes that implement doInitialization/doFinalization. This is for 125 /// machine function passes to work on module level constructs. One such pass 126 /// is AsmPrinter. 127 /// 128 /// - Support machine module pass which runs over the module (for example, 129 /// MachineOutliner). A machine module pass needs to define the method: 130 /// 131 /// ```Error run(Module &, MachineFunctionAnalysisManager &)``` 132 /// 133 /// FIXME: machine module passes still need to define the usual machine 134 /// function pass interface, namely, 135 /// `PreservedAnalyses run(MachineFunction &, 136 /// MachineFunctionAnalysisManager &)` 137 /// But this interface wouldn't be executed. It is just a placeholder 138 /// to satisfy the pass manager type-erased inteface. This 139 /// special-casing of machine module pass is due to its limited use 140 /// cases and the unnecessary complexity it may bring to the machine 141 /// pass manager. 142 /// 143 /// - The base class `run` method is replaced by an alternative `run` method. 144 /// See details below. 145 /// 146 /// - Support codegening in the SCC order. Users include interprocedural 147 /// register allocation (IPRA). 148 class MachineFunctionPassManager 149 : public PassManager<MachineFunction, MachineFunctionAnalysisManager> { 150 using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>; 151 152 public: 153 MachineFunctionPassManager(bool RequireCodeGenSCCOrder = false, 154 bool VerifyMachineFunction = false) RequireCodeGenSCCOrder(RequireCodeGenSCCOrder)155 : RequireCodeGenSCCOrder(RequireCodeGenSCCOrder), 156 VerifyMachineFunction(VerifyMachineFunction) {} 157 MachineFunctionPassManager(MachineFunctionPassManager &&) = default; 158 MachineFunctionPassManager & 159 operator=(MachineFunctionPassManager &&) = default; 160 161 /// Run machine passes for a Module. 162 /// 163 /// The intended use is to start the codegen pipeline for a Module. The base 164 /// class's `run` method is deliberately hidden by this due to the observation 165 /// that we don't yet have the use cases of compositing two instances of 166 /// machine pass managers, or compositing machine pass managers with other 167 /// types of pass managers. 168 Error run(Module &M, MachineFunctionAnalysisManager &MFAM); 169 addPass(PassT && Pass)170 template <typename PassT> void addPass(PassT &&Pass) { 171 Base::addPass(std::forward<PassT>(Pass)); 172 PassConceptT *P = Passes.back().get(); 173 addDoInitialization<PassT>(P); 174 addDoFinalization<PassT>(P); 175 176 // Add machine module pass. 177 addRunOnModule<PassT>(P); 178 } 179 180 private: 181 template <typename PassT> 182 using has_init_t = decltype(std::declval<PassT &>().doInitialization( 183 std::declval<Module &>(), 184 std::declval<MachineFunctionAnalysisManager &>())); 185 186 template <typename PassT> 187 std::enable_if_t<!is_detected<has_init_t, PassT>::value> addDoInitialization(PassConceptT * Pass)188 addDoInitialization(PassConceptT *Pass) {} 189 190 template <typename PassT> 191 std::enable_if_t<is_detected<has_init_t, PassT>::value> addDoInitialization(PassConceptT * Pass)192 addDoInitialization(PassConceptT *Pass) { 193 using PassModelT = 194 detail::PassModel<MachineFunction, PassT, PreservedAnalyses, 195 MachineFunctionAnalysisManager>; 196 auto *P = static_cast<PassModelT *>(Pass); 197 InitializationFuncs.emplace_back( 198 [=](Module &M, MachineFunctionAnalysisManager &MFAM) { 199 return P->Pass.doInitialization(M, MFAM); 200 }); 201 } 202 203 template <typename PassT> 204 using has_fini_t = decltype(std::declval<PassT &>().doFinalization( 205 std::declval<Module &>(), 206 std::declval<MachineFunctionAnalysisManager &>())); 207 208 template <typename PassT> 209 std::enable_if_t<!is_detected<has_fini_t, PassT>::value> addDoFinalization(PassConceptT * Pass)210 addDoFinalization(PassConceptT *Pass) {} 211 212 template <typename PassT> 213 std::enable_if_t<is_detected<has_fini_t, PassT>::value> addDoFinalization(PassConceptT * Pass)214 addDoFinalization(PassConceptT *Pass) { 215 using PassModelT = 216 detail::PassModel<MachineFunction, PassT, PreservedAnalyses, 217 MachineFunctionAnalysisManager>; 218 auto *P = static_cast<PassModelT *>(Pass); 219 FinalizationFuncs.emplace_back( 220 [=](Module &M, MachineFunctionAnalysisManager &MFAM) { 221 return P->Pass.doFinalization(M, MFAM); 222 }); 223 } 224 225 template <typename PassT> 226 using is_machine_module_pass_t = decltype(std::declval<PassT &>().run( 227 std::declval<Module &>(), 228 std::declval<MachineFunctionAnalysisManager &>())); 229 230 template <typename PassT> 231 using is_machine_function_pass_t = decltype(std::declval<PassT &>().run( 232 std::declval<MachineFunction &>(), 233 std::declval<MachineFunctionAnalysisManager &>())); 234 235 template <typename PassT> 236 std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value> addRunOnModule(PassConceptT * Pass)237 addRunOnModule(PassConceptT *Pass) {} 238 239 template <typename PassT> 240 std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value> addRunOnModule(PassConceptT * Pass)241 addRunOnModule(PassConceptT *Pass) { 242 static_assert(is_detected<is_machine_function_pass_t, PassT>::value, 243 "machine module pass needs to define machine function pass " 244 "api. sorry."); 245 246 using PassModelT = 247 detail::PassModel<MachineFunction, PassT, PreservedAnalyses, 248 MachineFunctionAnalysisManager>; 249 auto *P = static_cast<PassModelT *>(Pass); 250 MachineModulePasses.emplace( 251 Passes.size() - 1, 252 [=](Module &M, MachineFunctionAnalysisManager &MFAM) { 253 return P->Pass.run(M, MFAM); 254 }); 255 } 256 257 using FuncTy = Error(Module &, MachineFunctionAnalysisManager &); 258 SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs; 259 SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs; 260 261 using PassIndex = decltype(Passes)::size_type; 262 std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses; 263 264 // Run codegen in the SCC order. 265 bool RequireCodeGenSCCOrder; 266 267 bool VerifyMachineFunction; 268 }; 269 270 } // end namespace llvm 271 272 #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H 273