PassInstrumentation.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/IR/PassInstrumentation.h ----------------------*- 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 file defines the Pass Instrumentation classes that provide
  16. /// instrumentation points into the pass execution by PassManager.
  17. ///
  18. /// There are two main classes:
  19. /// - PassInstrumentation provides a set of instrumentation points for
  20. /// pass managers to call on.
  21. ///
  22. /// - PassInstrumentationCallbacks registers callbacks and provides access
  23. /// to them for PassInstrumentation.
  24. ///
  25. /// PassInstrumentation object is being used as a result of
  26. /// PassInstrumentationAnalysis (so it is intended to be easily copyable).
  27. ///
  28. /// Intended scheme of use for Pass Instrumentation is as follows:
  29. /// - register instrumentation callbacks in PassInstrumentationCallbacks
  30. /// instance. PassBuilder provides helper for that.
  31. ///
  32. /// - register PassInstrumentationAnalysis with all the PassManagers.
  33. /// PassBuilder handles that automatically when registering analyses.
  34. ///
  35. /// - Pass Manager requests PassInstrumentationAnalysis from analysis manager
  36. /// and gets PassInstrumentation as its result.
  37. ///
  38. /// - Pass Manager invokes PassInstrumentation entry points appropriately,
  39. /// passing StringRef identification ("name") of the pass currently being
  40. /// executed and IRUnit it works on. There can be different schemes of
  41. /// providing names in future, currently it is just a name() of the pass.
  42. ///
  43. /// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes
  44. /// control to all the registered callbacks. Note that we specifically wrap
  45. /// 'const IRUnitT*' so as to avoid any accidental changes to IR in
  46. /// instrumenting callbacks.
  47. ///
  48. /// - Some instrumentation points (BeforePass) allow to control execution
  49. /// of a pass. For those callbacks returning false means pass will not be
  50. /// executed.
  51. ///
  52. //===----------------------------------------------------------------------===//
  53. #ifndef LLVM_IR_PASSINSTRUMENTATION_H
  54. #define LLVM_IR_PASSINSTRUMENTATION_H
  55. #include "llvm/ADT/Any.h"
  56. #include "llvm/ADT/FunctionExtras.h"
  57. #include "llvm/ADT/SmallVector.h"
  58. #include "llvm/ADT/StringMap.h"
  59. #include <type_traits>
  60. #include <vector>
  61. namespace llvm {
  62. class PreservedAnalyses;
  63. class StringRef;
  64. /// This class manages callbacks registration, as well as provides a way for
  65. /// PassInstrumentation to pass control to the registered callbacks.
  66. class PassInstrumentationCallbacks {
  67. public:
  68. // Before/After callbacks accept IRUnits whenever appropriate, so they need
  69. // to take them as constant pointers, wrapped with llvm::Any.
  70. // For the case when IRUnit has been invalidated there is a different
  71. // callback to use - AfterPassInvalidated.
  72. // We call all BeforePassFuncs to determine if a pass should run or not.
  73. // BeforeNonSkippedPassFuncs are called only if the pass should run.
  74. // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing
  75. // already invalidated IRUnit is unsafe. There are ways to handle invalidated
  76. // IRUnits in a safe way, and we might pursue that as soon as there is a
  77. // useful instrumentation that needs it.
  78. using BeforePassFunc = bool(StringRef, Any);
  79. using BeforeSkippedPassFunc = void(StringRef, Any);
  80. using BeforeNonSkippedPassFunc = void(StringRef, Any);
  81. using AfterPassFunc = void(StringRef, Any, const PreservedAnalyses &);
  82. using AfterPassInvalidatedFunc = void(StringRef, const PreservedAnalyses &);
  83. using BeforeAnalysisFunc = void(StringRef, Any);
  84. using AfterAnalysisFunc = void(StringRef, Any);
  85. using AnalysisInvalidatedFunc = void(StringRef, Any);
  86. using AnalysesClearedFunc = void(StringRef);
  87. public:
  88. PassInstrumentationCallbacks() = default;
  89. /// Copying PassInstrumentationCallbacks is not intended.
  90. PassInstrumentationCallbacks(const PassInstrumentationCallbacks &) = delete;
  91. void operator=(const PassInstrumentationCallbacks &) = delete;
  92. template <typename CallableT>
  93. void registerShouldRunOptionalPassCallback(CallableT C) {
  94. ShouldRunOptionalPassCallbacks.emplace_back(std::move(C));
  95. }
  96. template <typename CallableT>
  97. void registerBeforeSkippedPassCallback(CallableT C) {
  98. BeforeSkippedPassCallbacks.emplace_back(std::move(C));
  99. }
  100. template <typename CallableT>
  101. void registerBeforeNonSkippedPassCallback(CallableT C) {
  102. BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
  103. }
  104. template <typename CallableT> void registerAfterPassCallback(CallableT C) {
  105. AfterPassCallbacks.emplace_back(std::move(C));
  106. }
  107. template <typename CallableT>
  108. void registerAfterPassInvalidatedCallback(CallableT C) {
  109. AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
  110. }
  111. template <typename CallableT>
  112. void registerBeforeAnalysisCallback(CallableT C) {
  113. BeforeAnalysisCallbacks.emplace_back(std::move(C));
  114. }
  115. template <typename CallableT>
  116. void registerAfterAnalysisCallback(CallableT C) {
  117. AfterAnalysisCallbacks.emplace_back(std::move(C));
  118. }
  119. template <typename CallableT>
  120. void registerAnalysisInvalidatedCallback(CallableT C) {
  121. AnalysisInvalidatedCallbacks.emplace_back(std::move(C));
  122. }
  123. template <typename CallableT>
  124. void registerAnalysesClearedCallback(CallableT C) {
  125. AnalysesClearedCallbacks.emplace_back(std::move(C));
  126. }
  127. /// Add a class name to pass name mapping for use by pass instrumentation.
  128. void addClassToPassName(StringRef ClassName, StringRef PassName);
  129. /// Get the pass name for a given pass class name.
  130. StringRef getPassNameForClassName(StringRef ClassName);
  131. private:
  132. friend class PassInstrumentation;
  133. /// These are only run on passes that are not required. They return false when
  134. /// an optional pass should be skipped.
  135. SmallVector<llvm::unique_function<BeforePassFunc>, 4>
  136. ShouldRunOptionalPassCallbacks;
  137. /// These are run on passes that are skipped.
  138. SmallVector<llvm::unique_function<BeforeSkippedPassFunc>, 4>
  139. BeforeSkippedPassCallbacks;
  140. /// These are run on passes that are about to be run.
  141. SmallVector<llvm::unique_function<BeforeNonSkippedPassFunc>, 4>
  142. BeforeNonSkippedPassCallbacks;
  143. /// These are run on passes that have just run.
  144. SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
  145. /// These are run passes that have just run on invalidated IR.
  146. SmallVector<llvm::unique_function<AfterPassInvalidatedFunc>, 4>
  147. AfterPassInvalidatedCallbacks;
  148. /// These are run on analyses that are about to be run.
  149. SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
  150. BeforeAnalysisCallbacks;
  151. /// These are run on analyses that have been run.
  152. SmallVector<llvm::unique_function<AfterAnalysisFunc>, 4>
  153. AfterAnalysisCallbacks;
  154. /// These are run on analyses that have been invalidated.
  155. SmallVector<llvm::unique_function<AnalysisInvalidatedFunc>, 4>
  156. AnalysisInvalidatedCallbacks;
  157. /// These are run on analyses that have been cleared.
  158. SmallVector<llvm::unique_function<AnalysesClearedFunc>, 4>
  159. AnalysesClearedCallbacks;
  160. StringMap<std::string> ClassToPassName;
  161. };
  162. /// This class provides instrumentation entry points for the Pass Manager,
  163. /// doing calls to callbacks registered in PassInstrumentationCallbacks.
  164. class PassInstrumentation {
  165. PassInstrumentationCallbacks *Callbacks;
  166. // Template argument PassT of PassInstrumentation::runBeforePass could be two
  167. // kinds: (1) a regular pass inherited from PassInfoMixin (happen when
  168. // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept
  169. // created from (1). Here we want to make case (1) skippable unconditionally
  170. // since they are regular passes. We call PassConcept::isRequired to decide
  171. // for case (2).
  172. template <typename PassT>
  173. using has_required_t = decltype(std::declval<PassT &>().isRequired());
  174. template <typename PassT>
  175. static std::enable_if_t<is_detected<has_required_t, PassT>::value, bool>
  176. isRequired(const PassT &Pass) {
  177. return Pass.isRequired();
  178. }
  179. template <typename PassT>
  180. static std::enable_if_t<!is_detected<has_required_t, PassT>::value, bool>
  181. isRequired(const PassT &Pass) {
  182. return false;
  183. }
  184. public:
  185. /// Callbacks object is not owned by PassInstrumentation, its life-time
  186. /// should at least match the life-time of corresponding
  187. /// PassInstrumentationAnalysis (which usually is till the end of current
  188. /// compilation).
  189. PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr)
  190. : Callbacks(CB) {}
  191. /// BeforePass instrumentation point - takes \p Pass instance to be executed
  192. /// and constant reference to IR it operates on. \Returns true if pass is
  193. /// allowed to be executed. These are only run on optional pass since required
  194. /// passes must always be run. This allows these callbacks to print info when
  195. /// they want to skip a pass.
  196. template <typename IRUnitT, typename PassT>
  197. bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
  198. if (!Callbacks)
  199. return true;
  200. bool ShouldRun = true;
  201. if (!isRequired(Pass)) {
  202. for (auto &C : Callbacks->ShouldRunOptionalPassCallbacks)
  203. ShouldRun &= C(Pass.name(), llvm::Any(&IR));
  204. }
  205. if (ShouldRun) {
  206. for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
  207. C(Pass.name(), llvm::Any(&IR));
  208. } else {
  209. for (auto &C : Callbacks->BeforeSkippedPassCallbacks)
  210. C(Pass.name(), llvm::Any(&IR));
  211. }
  212. return ShouldRun;
  213. }
  214. /// AfterPass instrumentation point - takes \p Pass instance that has
  215. /// just been executed and constant reference to \p IR it operates on.
  216. /// \p IR is guaranteed to be valid at this point.
  217. template <typename IRUnitT, typename PassT>
  218. void runAfterPass(const PassT &Pass, const IRUnitT &IR,
  219. const PreservedAnalyses &PA) const {
  220. if (Callbacks)
  221. for (auto &C : Callbacks->AfterPassCallbacks)
  222. C(Pass.name(), llvm::Any(&IR), PA);
  223. }
  224. /// AfterPassInvalidated instrumentation point - takes \p Pass instance
  225. /// that has just been executed. For use when IR has been invalidated
  226. /// by \p Pass execution.
  227. template <typename IRUnitT, typename PassT>
  228. void runAfterPassInvalidated(const PassT &Pass,
  229. const PreservedAnalyses &PA) const {
  230. if (Callbacks)
  231. for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
  232. C(Pass.name(), PA);
  233. }
  234. /// BeforeAnalysis instrumentation point - takes \p Analysis instance
  235. /// to be executed and constant reference to IR it operates on.
  236. template <typename IRUnitT, typename PassT>
  237. void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
  238. if (Callbacks)
  239. for (auto &C : Callbacks->BeforeAnalysisCallbacks)
  240. C(Analysis.name(), llvm::Any(&IR));
  241. }
  242. /// AfterAnalysis instrumentation point - takes \p Analysis instance
  243. /// that has just been executed and constant reference to IR it operated on.
  244. template <typename IRUnitT, typename PassT>
  245. void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
  246. if (Callbacks)
  247. for (auto &C : Callbacks->AfterAnalysisCallbacks)
  248. C(Analysis.name(), llvm::Any(&IR));
  249. }
  250. /// AnalysisInvalidated instrumentation point - takes \p Analysis instance
  251. /// that has just been invalidated and constant reference to IR it operated
  252. /// on.
  253. template <typename IRUnitT, typename PassT>
  254. void runAnalysisInvalidated(const PassT &Analysis, const IRUnitT &IR) const {
  255. if (Callbacks)
  256. for (auto &C : Callbacks->AnalysisInvalidatedCallbacks)
  257. C(Analysis.name(), llvm::Any(&IR));
  258. }
  259. /// AnalysesCleared instrumentation point - takes name of IR that analyses
  260. /// operated on.
  261. void runAnalysesCleared(StringRef Name) const {
  262. if (Callbacks)
  263. for (auto &C : Callbacks->AnalysesClearedCallbacks)
  264. C(Name);
  265. }
  266. /// Handle invalidation from the pass manager when PassInstrumentation
  267. /// is used as the result of PassInstrumentationAnalysis.
  268. ///
  269. /// On attempt to invalidate just return false. There is nothing to become
  270. /// invalid here.
  271. template <typename IRUnitT, typename... ExtraArgsT>
  272. bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
  273. ExtraArgsT...) {
  274. return false;
  275. }
  276. template <typename CallableT>
  277. void pushBeforeNonSkippedPassCallback(CallableT C) {
  278. if (Callbacks)
  279. Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
  280. }
  281. void popBeforeNonSkippedPassCallback() {
  282. if (Callbacks)
  283. Callbacks->BeforeNonSkippedPassCallbacks.pop_back();
  284. }
  285. };
  286. bool isSpecialPass(StringRef PassID, const std::vector<StringRef> &Specials);
  287. } // namespace llvm
  288. #endif
  289. #ifdef __GNUC__
  290. #pragma GCC diagnostic pop
  291. #endif