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