PassManagerInternal.h 13 KB

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