MachinePassManager.h 9.8 KB

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