PassManagerInternal.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- PassManager internal APIs and implementation details -----*- 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. /// \file
  14. ///
  15. /// This header provides internal APIs and implementation details used by the
  16. /// pass management interfaces exposed in PassManager.h. To understand more
  17. /// context of why these particular interfaces are needed, see that header
  18. /// file. None of these APIs should be used elsewhere.
  19. ///
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
  22. #define LLVM_IR_PASSMANAGERINTERNAL_H
  23. #include "llvm/ADT/STLExtras.h"
  24. #include "llvm/ADT/StringRef.h"
  25. #include <memory>
  26. #include <utility>
  27. namespace llvm {
  28. template <typename IRUnitT> class AllAnalysesOn;
  29. template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
  30. class PreservedAnalyses;
  31. // Implementation details of the pass manager interfaces.
  32. namespace detail {
  33. /// Template for the abstract base class used to dispatch
  34. /// polymorphically over pass objects.
  35. template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
  36. struct PassConcept {
  37. // Boiler plate necessary for the container of derived classes.
  38. virtual ~PassConcept() = default;
  39. /// The polymorphic API which runs the pass over a given IR entity.
  40. ///
  41. /// Note that actual pass object can omit the analysis manager argument if
  42. /// desired. Also that the analysis manager may be null if there is no
  43. /// analysis manager in the pass pipeline.
  44. virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
  45. ExtraArgTs... ExtraArgs) = 0;
  46. virtual void
  47. printPipeline(raw_ostream &OS,
  48. function_ref<StringRef(StringRef)> MapClassName2PassName) = 0;
  49. /// Polymorphic method to access the name of a pass.
  50. virtual StringRef name() const = 0;
  51. /// Polymorphic method to to let a pass optionally exempted from skipping by
  52. /// PassInstrumentation.
  53. /// To opt-in, pass should implement `static bool isRequired()`. It's no-op
  54. /// to have `isRequired` always return false since that is the default.
  55. virtual bool isRequired() const = 0;
  56. };
  57. /// A template wrapper used to implement the polymorphic API.
  58. ///
  59. /// Can be instantiated for any object which provides a \c run method accepting
  60. /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
  61. /// be a copyable object.
  62. template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
  63. typename AnalysisManagerT, typename... ExtraArgTs>
  64. struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
  65. explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
  66. // We have to explicitly define all the special member functions because MSVC
  67. // refuses to generate them.
  68. PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
  69. PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
  70. friend void swap(PassModel &LHS, PassModel &RHS) {
  71. using std::swap;
  72. swap(LHS.Pass, RHS.Pass);
  73. }
  74. PassModel &operator=(PassModel RHS) {
  75. swap(*this, RHS);
  76. return *this;
  77. }
  78. PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
  79. ExtraArgTs... ExtraArgs) override {
  80. return Pass.run(IR, AM, ExtraArgs...);
  81. }
  82. void printPipeline(
  83. raw_ostream &OS,
  84. function_ref<StringRef(StringRef)> MapClassName2PassName) override {
  85. Pass.printPipeline(OS, MapClassName2PassName);
  86. }
  87. StringRef name() const override { return PassT::name(); }
  88. template <typename T>
  89. using has_required_t = decltype(std::declval<T &>().isRequired());
  90. template <typename T>
  91. static std::enable_if_t<is_detected<has_required_t, T>::value, bool>
  92. passIsRequiredImpl() {
  93. return T::isRequired();
  94. }
  95. template <typename T>
  96. static std::enable_if_t<!is_detected<has_required_t, T>::value, bool>
  97. passIsRequiredImpl() {
  98. return false;
  99. }
  100. bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
  101. PassT Pass;
  102. };
  103. /// Abstract concept of an analysis result.
  104. ///
  105. /// This concept is parameterized over the IR unit that this result pertains
  106. /// to.
  107. template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
  108. struct AnalysisResultConcept {
  109. virtual ~AnalysisResultConcept() = default;
  110. /// Method to try and mark a result as invalid.
  111. ///
  112. /// When the outer analysis manager detects a change in some underlying
  113. /// unit of the IR, it will call this method on all of the results cached.
  114. ///
  115. /// \p PA is a set of preserved analyses which can be used to avoid
  116. /// invalidation because the pass which changed the underlying IR took care
  117. /// to update or preserve the analysis result in some way.
  118. ///
  119. /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be
  120. /// used by a particular analysis result to discover if other analyses
  121. /// results are also invalidated in the event that this result depends on
  122. /// them. See the documentation in the \c AnalysisManager for more details.
  123. ///
  124. /// \returns true if the result is indeed invalid (the default).
  125. virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
  126. InvalidatorT &Inv) = 0;
  127. };
  128. /// SFINAE metafunction for computing whether \c ResultT provides an
  129. /// \c invalidate member function.
  130. template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
  131. using EnabledType = char;
  132. struct DisabledType {
  133. char a, b;
  134. };
  135. // Purely to help out MSVC which fails to disable the below specialization,
  136. // explicitly enable using the result type's invalidate routine if we can
  137. // successfully call that routine.
  138. template <typename T> struct Nonce { using Type = EnabledType; };
  139. template <typename T>
  140. static typename Nonce<decltype(std::declval<T>().invalidate(
  141. std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
  142. check(rank<2>);
  143. // First we define an overload that can only be taken if there is no
  144. // invalidate member. We do this by taking the address of an invalidate
  145. // member in an adjacent base class of a derived class. This would be
  146. // ambiguous if there were an invalidate member in the result type.
  147. template <typename T, typename U> static DisabledType NonceFunction(T U::*);
  148. struct CheckerBase { int invalidate; };
  149. template <typename T> struct Checker : CheckerBase, T {};
  150. template <typename T>
  151. static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
  152. // Now we have the fallback that will only be reached when there is an
  153. // invalidate member, and enables the trait.
  154. template <typename T>
  155. static EnabledType check(rank<0>);
  156. public:
  157. enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
  158. };
  159. /// Wrapper to model the analysis result concept.
  160. ///
  161. /// By default, this will implement the invalidate method with a trivial
  162. /// implementation so that the actual analysis result doesn't need to provide
  163. /// an invalidation handler. It is only selected when the invalidation handler
  164. /// is not part of the ResultT's interface.
  165. template <typename IRUnitT, typename PassT, typename ResultT,
  166. typename PreservedAnalysesT, typename InvalidatorT,
  167. bool HasInvalidateHandler =
  168. ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
  169. struct AnalysisResultModel;
  170. /// Specialization of \c AnalysisResultModel which provides the default
  171. /// invalidate functionality.
  172. template <typename IRUnitT, typename PassT, typename ResultT,
  173. typename PreservedAnalysesT, typename InvalidatorT>
  174. struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
  175. InvalidatorT, false>
  176. : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
  177. explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
  178. // We have to explicitly define all the special member functions because MSVC
  179. // refuses to generate them.
  180. AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
  181. AnalysisResultModel(AnalysisResultModel &&Arg)
  182. : Result(std::move(Arg.Result)) {}
  183. friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
  184. using std::swap;
  185. swap(LHS.Result, RHS.Result);
  186. }
  187. AnalysisResultModel &operator=(AnalysisResultModel RHS) {
  188. swap(*this, RHS);
  189. return *this;
  190. }
  191. /// The model bases invalidation solely on being in the preserved set.
  192. //
  193. // FIXME: We should actually use two different concepts for analysis results
  194. // rather than two different models, and avoid the indirect function call for
  195. // ones that use the trivial behavior.
  196. bool invalidate(IRUnitT &, const PreservedAnalysesT &PA,
  197. InvalidatorT &) override {
  198. auto PAC = PA.template getChecker<PassT>();
  199. return !PAC.preserved() &&
  200. !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
  201. }
  202. ResultT Result;
  203. };
  204. /// Specialization of \c AnalysisResultModel which delegates invalidate
  205. /// handling to \c ResultT.
  206. template <typename IRUnitT, typename PassT, typename ResultT,
  207. typename PreservedAnalysesT, typename InvalidatorT>
  208. struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
  209. InvalidatorT, true>
  210. : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
  211. explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
  212. // We have to explicitly define all the special member functions because MSVC
  213. // refuses to generate them.
  214. AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
  215. AnalysisResultModel(AnalysisResultModel &&Arg)
  216. : Result(std::move(Arg.Result)) {}
  217. friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
  218. using std::swap;
  219. swap(LHS.Result, RHS.Result);
  220. }
  221. AnalysisResultModel &operator=(AnalysisResultModel RHS) {
  222. swap(*this, RHS);
  223. return *this;
  224. }
  225. /// The model delegates to the \c ResultT method.
  226. bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
  227. InvalidatorT &Inv) override {
  228. return Result.invalidate(IR, PA, Inv);
  229. }
  230. ResultT Result;
  231. };
  232. /// Abstract concept of an analysis pass.
  233. ///
  234. /// This concept is parameterized over the IR unit that it can run over and
  235. /// produce an analysis result.
  236. template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
  237. typename... ExtraArgTs>
  238. struct AnalysisPassConcept {
  239. virtual ~AnalysisPassConcept() = default;
  240. /// Method to run this analysis over a unit of IR.
  241. /// \returns A unique_ptr to the analysis result object to be queried by
  242. /// users.
  243. virtual std::unique_ptr<
  244. AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
  245. run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
  246. ExtraArgTs... ExtraArgs) = 0;
  247. /// Polymorphic method to access the name of a pass.
  248. virtual StringRef name() const = 0;
  249. };
  250. /// Wrapper to model the analysis pass concept.
  251. ///
  252. /// Can wrap any type which implements a suitable \c run method. The method
  253. /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
  254. /// and produce an object which can be wrapped in a \c AnalysisResultModel.
  255. template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
  256. typename InvalidatorT, typename... ExtraArgTs>
  257. struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
  258. InvalidatorT, ExtraArgTs...> {
  259. explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
  260. // We have to explicitly define all the special member functions because MSVC
  261. // refuses to generate them.
  262. AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
  263. AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
  264. friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
  265. using std::swap;
  266. swap(LHS.Pass, RHS.Pass);
  267. }
  268. AnalysisPassModel &operator=(AnalysisPassModel RHS) {
  269. swap(*this, RHS);
  270. return *this;
  271. }
  272. // FIXME: Replace PassT::Result with type traits when we use C++11.
  273. using ResultModelT =
  274. AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
  275. PreservedAnalysesT, InvalidatorT>;
  276. /// The model delegates to the \c PassT::run method.
  277. ///
  278. /// The return is wrapped in an \c AnalysisResultModel.
  279. std::unique_ptr<
  280. AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
  281. run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
  282. ExtraArgTs... ExtraArgs) override {
  283. return std::make_unique<ResultModelT>(
  284. Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
  285. }
  286. /// The model delegates to a static \c PassT::name method.
  287. ///
  288. /// The returned string ref must point to constant immutable data!
  289. StringRef name() const override { return PassT::name(); }
  290. PassT Pass;
  291. };
  292. } // end namespace detail
  293. } // end namespace llvm
  294. #endif // LLVM_IR_PASSMANAGERINTERNAL_H
  295. #ifdef __GNUC__
  296. #pragma GCC diagnostic pop
  297. #endif