PassManagerInternal.h 13 KB

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