MachinePassManager.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This header defines the pass manager interface for codegen. The codegen
  15. // pipeline consists of only machine function passes. There is no container
  16. // relationship between IR module/function and machine function in terms of pass
  17. // manager organization. So there is no need for adaptor classes (for example
  18. // ModuleToMachineFunctionAdaptor). Since invalidation could only happen among
  19. // machine function passes, there is no proxy classes to handle cross-IR-unit
  20. // invalidation. IR analysis results are provided for machine function passes by
  21. // their respective analysis managers such as ModuleAnalysisManager and
  22. // FunctionAnalysisManager.
  23. //
  24. // TODO: Add MachineFunctionProperties support.
  25. //
  26. //===----------------------------------------------------------------------===//
  27. #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
  28. #define LLVM_CODEGEN_MACHINEPASSMANAGER_H
  29. #include "llvm/ADT/FunctionExtras.h"
  30. #include "llvm/ADT/SmallVector.h"
  31. #include "llvm/CodeGen/MachineFunction.h"
  32. #include "llvm/IR/PassManager.h"
  33. #include "llvm/Support/Error.h"
  34. #include "llvm/Support/type_traits.h"
  35. namespace llvm {
  36. class Module;
  37. extern template class AnalysisManager<MachineFunction>;
  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() : FAM(nullptr), MAM(nullptr) {}
  43. MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
  44. ModuleAnalysisManager &MAM)
  45. : FAM(&FAM), MAM(&MAM) {}
  46. MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
  47. MachineFunctionAnalysisManager &
  48. operator=(MachineFunctionAnalysisManager &&) = default;
  49. /// Get the result of an analysis pass for a Function.
  50. ///
  51. /// Runs the analysis if a cached result is not available.
  52. template <typename PassT> typename PassT::Result &getResult(Function &F) {
  53. return FAM->getResult<PassT>(F);
  54. }
  55. /// Get the cached result of an analysis pass for a Function.
  56. ///
  57. /// This method never runs the analysis.
  58. ///
  59. /// \returns null if there is no cached result.
  60. template <typename PassT>
  61. typename PassT::Result *getCachedResult(Function &F) {
  62. return FAM->getCachedResult<PassT>(F);
  63. }
  64. /// Get the result of an analysis pass for a Module.
  65. ///
  66. /// Runs the analysis if a cached result is not available.
  67. template <typename PassT> typename PassT::Result &getResult(Module &M) {
  68. return MAM->getResult<PassT>(M);
  69. }
  70. /// Get the cached result of an analysis pass for a Module.
  71. ///
  72. /// This method never runs the analysis.
  73. ///
  74. /// \returns null if there is no cached result.
  75. template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
  76. return MAM->getCachedResult<PassT>(M);
  77. }
  78. /// Get the result of an analysis pass for a MachineFunction.
  79. ///
  80. /// Runs the analysis if a cached result is not available.
  81. using Base::getResult;
  82. /// Get the cached result of an analysis pass for a MachineFunction.
  83. ///
  84. /// This method never runs the analysis.
  85. ///
  86. /// returns null if there is no cached result.
  87. using Base::getCachedResult;
  88. // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
  89. FunctionAnalysisManager *FAM;
  90. ModuleAnalysisManager *MAM;
  91. };
  92. extern template class PassManager<MachineFunction>;
  93. /// MachineFunctionPassManager adds/removes below features to/from the base
  94. /// PassManager template instantiation.
  95. ///
  96. /// - Support passes that implement doInitialization/doFinalization. This is for
  97. /// machine function passes to work on module level constructs. One such pass
  98. /// is AsmPrinter.
  99. ///
  100. /// - Support machine module pass which runs over the module (for example,
  101. /// MachineOutliner). A machine module pass needs to define the method:
  102. ///
  103. /// ```Error run(Module &, MachineFunctionAnalysisManager &)```
  104. ///
  105. /// FIXME: machine module passes still need to define the usual machine
  106. /// function pass interface, namely,
  107. /// `PreservedAnalyses run(MachineFunction &,
  108. /// MachineFunctionAnalysisManager &)`
  109. /// But this interface wouldn't be executed. It is just a placeholder
  110. /// to satisfy the pass manager type-erased inteface. This
  111. /// special-casing of machine module pass is due to its limited use
  112. /// cases and the unnecessary complexity it may bring to the machine
  113. /// pass manager.
  114. ///
  115. /// - The base class `run` method is replaced by an alternative `run` method.
  116. /// See details below.
  117. ///
  118. /// - Support codegening in the SCC order. Users include interprocedural
  119. /// register allocation (IPRA).
  120. class MachineFunctionPassManager
  121. : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
  122. using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
  123. public:
  124. MachineFunctionPassManager(bool DebugLogging = false,
  125. bool RequireCodeGenSCCOrder = false,
  126. bool VerifyMachineFunction = false)
  127. : RequireCodeGenSCCOrder(RequireCodeGenSCCOrder),
  128. VerifyMachineFunction(VerifyMachineFunction) {}
  129. MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
  130. MachineFunctionPassManager &
  131. operator=(MachineFunctionPassManager &&) = default;
  132. /// Run machine passes for a Module.
  133. ///
  134. /// The intended use is to start the codegen pipeline for a Module. The base
  135. /// class's `run` method is deliberately hidden by this due to the observation
  136. /// that we don't yet have the use cases of compositing two instances of
  137. /// machine pass managers, or compositing machine pass managers with other
  138. /// types of pass managers.
  139. Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
  140. template <typename PassT> void addPass(PassT &&Pass) {
  141. Base::addPass(std::forward<PassT>(Pass));
  142. PassConceptT *P = Passes.back().get();
  143. addDoInitialization<PassT>(P);
  144. addDoFinalization<PassT>(P);
  145. // Add machine module pass.
  146. addRunOnModule<PassT>(P);
  147. }
  148. private:
  149. template <typename PassT>
  150. using has_init_t = decltype(std::declval<PassT &>().doInitialization(
  151. std::declval<Module &>(),
  152. std::declval<MachineFunctionAnalysisManager &>()));
  153. template <typename PassT>
  154. std::enable_if_t<!is_detected<has_init_t, PassT>::value>
  155. addDoInitialization(PassConceptT *Pass) {}
  156. template <typename PassT>
  157. std::enable_if_t<is_detected<has_init_t, PassT>::value>
  158. addDoInitialization(PassConceptT *Pass) {
  159. using PassModelT =
  160. detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
  161. MachineFunctionAnalysisManager>;
  162. auto *P = static_cast<PassModelT *>(Pass);
  163. InitializationFuncs.emplace_back(
  164. [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
  165. return P->Pass.doInitialization(M, MFAM);
  166. });
  167. }
  168. template <typename PassT>
  169. using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
  170. std::declval<Module &>(),
  171. std::declval<MachineFunctionAnalysisManager &>()));
  172. template <typename PassT>
  173. std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
  174. addDoFinalization(PassConceptT *Pass) {}
  175. template <typename PassT>
  176. std::enable_if_t<is_detected<has_fini_t, PassT>::value>
  177. addDoFinalization(PassConceptT *Pass) {
  178. using PassModelT =
  179. detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
  180. MachineFunctionAnalysisManager>;
  181. auto *P = static_cast<PassModelT *>(Pass);
  182. FinalizationFuncs.emplace_back(
  183. [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
  184. return P->Pass.doFinalization(M, MFAM);
  185. });
  186. }
  187. template <typename PassT>
  188. using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
  189. std::declval<Module &>(),
  190. std::declval<MachineFunctionAnalysisManager &>()));
  191. template <typename PassT>
  192. using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
  193. std::declval<MachineFunction &>(),
  194. std::declval<MachineFunctionAnalysisManager &>()));
  195. template <typename PassT>
  196. std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
  197. addRunOnModule(PassConceptT *Pass) {}
  198. template <typename PassT>
  199. std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
  200. addRunOnModule(PassConceptT *Pass) {
  201. static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
  202. "machine module pass needs to define machine function pass "
  203. "api. sorry.");
  204. using PassModelT =
  205. detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
  206. MachineFunctionAnalysisManager>;
  207. auto *P = static_cast<PassModelT *>(Pass);
  208. MachineModulePasses.emplace(
  209. Passes.size() - 1,
  210. [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
  211. return P->Pass.run(M, MFAM);
  212. });
  213. }
  214. using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
  215. SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
  216. SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
  217. using PassIndex = decltype(Passes)::size_type;
  218. std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
  219. // Run codegen in the SCC order.
  220. bool RequireCodeGenSCCOrder;
  221. bool VerifyMachineFunction;
  222. };
  223. } // end namespace llvm
  224. #endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
  225. #ifdef __GNUC__
  226. #pragma GCC diagnostic pop
  227. #endif