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