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