PassInstrumentation.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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>
  105. void registerAfterPassCallback(CallableT C, bool ToFront = false) {
  106. if (ToFront)
  107. AfterPassCallbacks.insert(AfterPassCallbacks.begin(), std::move(C));
  108. else
  109. AfterPassCallbacks.emplace_back(std::move(C));
  110. }
  111. template <typename CallableT>
  112. void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront = false) {
  113. if (ToFront)
  114. AfterPassInvalidatedCallbacks.insert(
  115. AfterPassInvalidatedCallbacks.begin(), std::move(C));
  116. else
  117. AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
  118. }
  119. template <typename CallableT>
  120. void registerBeforeAnalysisCallback(CallableT C) {
  121. BeforeAnalysisCallbacks.emplace_back(std::move(C));
  122. }
  123. template <typename CallableT>
  124. void registerAfterAnalysisCallback(CallableT C, bool ToFront = false) {
  125. if (ToFront)
  126. AfterAnalysisCallbacks.insert(AfterAnalysisCallbacks.begin(),
  127. std::move(C));
  128. else
  129. AfterAnalysisCallbacks.emplace_back(std::move(C));
  130. }
  131. template <typename CallableT>
  132. void registerAnalysisInvalidatedCallback(CallableT C) {
  133. AnalysisInvalidatedCallbacks.emplace_back(std::move(C));
  134. }
  135. template <typename CallableT>
  136. void registerAnalysesClearedCallback(CallableT C) {
  137. AnalysesClearedCallbacks.emplace_back(std::move(C));
  138. }
  139. /// Add a class name to pass name mapping for use by pass instrumentation.
  140. void addClassToPassName(StringRef ClassName, StringRef PassName);
  141. /// Get the pass name for a given pass class name.
  142. StringRef getPassNameForClassName(StringRef ClassName);
  143. private:
  144. friend class PassInstrumentation;
  145. /// These are only run on passes that are not required. They return false when
  146. /// an optional pass should be skipped.
  147. SmallVector<llvm::unique_function<BeforePassFunc>, 4>
  148. ShouldRunOptionalPassCallbacks;
  149. /// These are run on passes that are skipped.
  150. SmallVector<llvm::unique_function<BeforeSkippedPassFunc>, 4>
  151. BeforeSkippedPassCallbacks;
  152. /// These are run on passes that are about to be run.
  153. SmallVector<llvm::unique_function<BeforeNonSkippedPassFunc>, 4>
  154. BeforeNonSkippedPassCallbacks;
  155. /// These are run on passes that have just run.
  156. SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
  157. /// These are run passes that have just run on invalidated IR.
  158. SmallVector<llvm::unique_function<AfterPassInvalidatedFunc>, 4>
  159. AfterPassInvalidatedCallbacks;
  160. /// These are run on analyses that are about to be run.
  161. SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
  162. BeforeAnalysisCallbacks;
  163. /// These are run on analyses that have been run.
  164. SmallVector<llvm::unique_function<AfterAnalysisFunc>, 4>
  165. AfterAnalysisCallbacks;
  166. /// These are run on analyses that have been invalidated.
  167. SmallVector<llvm::unique_function<AnalysisInvalidatedFunc>, 4>
  168. AnalysisInvalidatedCallbacks;
  169. /// These are run on analyses that have been cleared.
  170. SmallVector<llvm::unique_function<AnalysesClearedFunc>, 4>
  171. AnalysesClearedCallbacks;
  172. StringMap<std::string> ClassToPassName;
  173. };
  174. /// This class provides instrumentation entry points for the Pass Manager,
  175. /// doing calls to callbacks registered in PassInstrumentationCallbacks.
  176. class PassInstrumentation {
  177. PassInstrumentationCallbacks *Callbacks;
  178. // Template argument PassT of PassInstrumentation::runBeforePass could be two
  179. // kinds: (1) a regular pass inherited from PassInfoMixin (happen when
  180. // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept
  181. // created from (1). Here we want to make case (1) skippable unconditionally
  182. // since they are regular passes. We call PassConcept::isRequired to decide
  183. // for case (2).
  184. template <typename PassT>
  185. using has_required_t = decltype(std::declval<PassT &>().isRequired());
  186. template <typename PassT>
  187. static std::enable_if_t<is_detected<has_required_t, PassT>::value, bool>
  188. isRequired(const PassT &Pass) {
  189. return Pass.isRequired();
  190. }
  191. template <typename PassT>
  192. static std::enable_if_t<!is_detected<has_required_t, PassT>::value, bool>
  193. isRequired(const PassT &Pass) {
  194. return false;
  195. }
  196. public:
  197. /// Callbacks object is not owned by PassInstrumentation, its life-time
  198. /// should at least match the life-time of corresponding
  199. /// PassInstrumentationAnalysis (which usually is till the end of current
  200. /// compilation).
  201. PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr)
  202. : Callbacks(CB) {}
  203. /// BeforePass instrumentation point - takes \p Pass instance to be executed
  204. /// and constant reference to IR it operates on. \Returns true if pass is
  205. /// allowed to be executed. These are only run on optional pass since required
  206. /// passes must always be run. This allows these callbacks to print info when
  207. /// they want to skip a pass.
  208. template <typename IRUnitT, typename PassT>
  209. bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
  210. if (!Callbacks)
  211. return true;
  212. bool ShouldRun = true;
  213. if (!isRequired(Pass)) {
  214. for (auto &C : Callbacks->ShouldRunOptionalPassCallbacks)
  215. ShouldRun &= C(Pass.name(), llvm::Any(&IR));
  216. }
  217. if (ShouldRun) {
  218. for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
  219. C(Pass.name(), llvm::Any(&IR));
  220. } else {
  221. for (auto &C : Callbacks->BeforeSkippedPassCallbacks)
  222. C(Pass.name(), llvm::Any(&IR));
  223. }
  224. return ShouldRun;
  225. }
  226. /// AfterPass instrumentation point - takes \p Pass instance that has
  227. /// just been executed and constant reference to \p IR it operates on.
  228. /// \p IR is guaranteed to be valid at this point.
  229. template <typename IRUnitT, typename PassT>
  230. void runAfterPass(const PassT &Pass, const IRUnitT &IR,
  231. const PreservedAnalyses &PA) const {
  232. if (Callbacks)
  233. for (auto &C : Callbacks->AfterPassCallbacks)
  234. C(Pass.name(), llvm::Any(&IR), PA);
  235. }
  236. /// AfterPassInvalidated instrumentation point - takes \p Pass instance
  237. /// that has just been executed. For use when IR has been invalidated
  238. /// by \p Pass execution.
  239. template <typename IRUnitT, typename PassT>
  240. void runAfterPassInvalidated(const PassT &Pass,
  241. const PreservedAnalyses &PA) const {
  242. if (Callbacks)
  243. for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
  244. C(Pass.name(), PA);
  245. }
  246. /// BeforeAnalysis instrumentation point - takes \p Analysis instance
  247. /// to be executed and constant reference to IR it operates on.
  248. template <typename IRUnitT, typename PassT>
  249. void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
  250. if (Callbacks)
  251. for (auto &C : Callbacks->BeforeAnalysisCallbacks)
  252. C(Analysis.name(), llvm::Any(&IR));
  253. }
  254. /// AfterAnalysis instrumentation point - takes \p Analysis instance
  255. /// that has just been executed and constant reference to IR it operated on.
  256. template <typename IRUnitT, typename PassT>
  257. void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
  258. if (Callbacks)
  259. for (auto &C : Callbacks->AfterAnalysisCallbacks)
  260. C(Analysis.name(), llvm::Any(&IR));
  261. }
  262. /// AnalysisInvalidated instrumentation point - takes \p Analysis instance
  263. /// that has just been invalidated and constant reference to IR it operated
  264. /// on.
  265. template <typename IRUnitT, typename PassT>
  266. void runAnalysisInvalidated(const PassT &Analysis, const IRUnitT &IR) const {
  267. if (Callbacks)
  268. for (auto &C : Callbacks->AnalysisInvalidatedCallbacks)
  269. C(Analysis.name(), llvm::Any(&IR));
  270. }
  271. /// AnalysesCleared instrumentation point - takes name of IR that analyses
  272. /// operated on.
  273. void runAnalysesCleared(StringRef Name) const {
  274. if (Callbacks)
  275. for (auto &C : Callbacks->AnalysesClearedCallbacks)
  276. C(Name);
  277. }
  278. /// Handle invalidation from the pass manager when PassInstrumentation
  279. /// is used as the result of PassInstrumentationAnalysis.
  280. ///
  281. /// On attempt to invalidate just return false. There is nothing to become
  282. /// invalid here.
  283. template <typename IRUnitT, typename... ExtraArgsT>
  284. bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
  285. ExtraArgsT...) {
  286. return false;
  287. }
  288. template <typename CallableT>
  289. void pushBeforeNonSkippedPassCallback(CallableT C) {
  290. if (Callbacks)
  291. Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
  292. }
  293. void popBeforeNonSkippedPassCallback() {
  294. if (Callbacks)
  295. Callbacks->BeforeNonSkippedPassCallbacks.pop_back();
  296. }
  297. };
  298. bool isSpecialPass(StringRef PassID, const std::vector<StringRef> &Specials);
  299. } // namespace llvm
  300. #endif
  301. #ifdef __GNUC__
  302. #pragma GCC diagnostic pop
  303. #endif