StandardInstrumentations.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- StandardInstrumentations.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 header defines a class that provides bookkeeping for all standard
  16. /// (i.e in-tree) pass instrumentations.
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
  20. #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
  21. #include "llvm/ADT/SmallVector.h"
  22. #include "llvm/ADT/StringRef.h"
  23. #include "llvm/IR/BasicBlock.h"
  24. #include "llvm/IR/OptBisect.h"
  25. #include "llvm/IR/PassTimingInfo.h"
  26. #include "llvm/IR/ValueHandle.h"
  27. #include "llvm/Support/CommandLine.h"
  28. #include "llvm/Transforms/IPO/SampleProfileProbe.h"
  29. #include <string>
  30. #include <utility>
  31. namespace llvm {
  32. class Module;
  33. class Function;
  34. class PassInstrumentationCallbacks;
  35. /// Instrumentation to print IR before/after passes.
  36. ///
  37. /// Needs state to be able to print module after pass that invalidates IR unit
  38. /// (typically Loop or SCC).
  39. class PrintIRInstrumentation {
  40. public:
  41. ~PrintIRInstrumentation();
  42. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  43. private:
  44. void printBeforePass(StringRef PassID, Any IR);
  45. void printAfterPass(StringRef PassID, Any IR);
  46. void printAfterPassInvalidated(StringRef PassID);
  47. bool shouldPrintBeforePass(StringRef PassID);
  48. bool shouldPrintAfterPass(StringRef PassID);
  49. using PrintModuleDesc = std::tuple<const Module *, std::string, StringRef>;
  50. void pushModuleDesc(StringRef PassID, Any IR);
  51. PrintModuleDesc popModuleDesc(StringRef PassID);
  52. PassInstrumentationCallbacks *PIC;
  53. /// Stack of Module description, enough to print the module after a given
  54. /// pass.
  55. SmallVector<PrintModuleDesc, 2> ModuleDescStack;
  56. bool StoreModuleDesc = false;
  57. };
  58. class OptNoneInstrumentation {
  59. public:
  60. OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
  61. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  62. private:
  63. bool DebugLogging;
  64. bool shouldRun(StringRef PassID, Any IR);
  65. };
  66. class OptBisectInstrumentation {
  67. public:
  68. OptBisectInstrumentation() {}
  69. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  70. };
  71. // Debug logging for transformation and analysis passes.
  72. class PrintPassInstrumentation {
  73. public:
  74. PrintPassInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
  75. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  76. private:
  77. bool DebugLogging;
  78. };
  79. class PreservedCFGCheckerInstrumentation {
  80. private:
  81. // CFG is a map BB -> {(Succ, Multiplicity)}, where BB is a non-leaf basic
  82. // block, {(Succ, Multiplicity)} set of all pairs of the block's successors
  83. // and the multiplicity of the edge (BB->Succ). As the mapped sets are
  84. // unordered the order of successors is not tracked by the CFG. In other words
  85. // this allows basic block successors to be swapped by a pass without
  86. // reporting a CFG change. CFG can be guarded by basic block tracking pointers
  87. // in the Graph (BBGuard). That is if any of the block is deleted or RAUWed
  88. // then the CFG is treated poisoned and no block pointer of the Graph is used.
  89. struct CFG {
  90. struct BBGuard final : public CallbackVH {
  91. BBGuard(const BasicBlock *BB) : CallbackVH(BB) {}
  92. void deleted() override { CallbackVH::deleted(); }
  93. void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); }
  94. bool isPoisoned() const { return !getValPtr(); }
  95. };
  96. Optional<DenseMap<intptr_t, BBGuard>> BBGuards;
  97. DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph;
  98. CFG(const Function *F, bool TrackBBLifetime = false);
  99. bool operator==(const CFG &G) const {
  100. return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph;
  101. }
  102. bool isPoisoned() const {
  103. if (BBGuards)
  104. for (auto &BB : *BBGuards) {
  105. if (BB.second.isPoisoned())
  106. return true;
  107. }
  108. return false;
  109. }
  110. static void printDiff(raw_ostream &out, const CFG &Before,
  111. const CFG &After);
  112. };
  113. SmallVector<std::pair<StringRef, Optional<CFG>>, 8> GraphStackBefore;
  114. public:
  115. static cl::opt<bool> VerifyPreservedCFG;
  116. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  117. };
  118. // Base class for classes that report changes to the IR.
  119. // It presents an interface for such classes and provides calls
  120. // on various events as the new pass manager transforms the IR.
  121. // It also provides filtering of information based on hidden options
  122. // specifying which functions are interesting.
  123. // Calls are made for the following events/queries:
  124. // 1. The initial IR processed.
  125. // 2. To get the representation of the IR (of type \p T).
  126. // 3. When a pass does not change the IR.
  127. // 4. When a pass changes the IR (given both before and after representations
  128. // of type \p T).
  129. // 5. When an IR is invalidated.
  130. // 6. When a pass is run on an IR that is not interesting (based on options).
  131. // 7. When a pass is ignored (pass manager or adapter pass).
  132. // 8. To compare two IR representations (of type \p T).
  133. template <typename IRUnitT> class ChangeReporter {
  134. protected:
  135. ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {}
  136. public:
  137. virtual ~ChangeReporter();
  138. // Determine if this pass/IR is interesting and if so, save the IR
  139. // otherwise it is left on the stack without data.
  140. void saveIRBeforePass(Any IR, StringRef PassID);
  141. // Compare the IR from before the pass after the pass.
  142. void handleIRAfterPass(Any IR, StringRef PassID);
  143. // Handle the situation where a pass is invalidated.
  144. void handleInvalidatedPass(StringRef PassID);
  145. protected:
  146. // Register required callbacks.
  147. void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC);
  148. // Return true when this is a defined function for which printing
  149. // of changes is desired.
  150. bool isInterestingFunction(const Function &F);
  151. // Return true when this is a pass for which printing of changes is desired.
  152. bool isInterestingPass(StringRef PassID);
  153. // Return true when this is a pass on IR for which printing
  154. // of changes is desired.
  155. bool isInteresting(Any IR, StringRef PassID);
  156. // Called on the first IR processed.
  157. virtual void handleInitialIR(Any IR) = 0;
  158. // Called before and after a pass to get the representation of the IR.
  159. virtual void generateIRRepresentation(Any IR, StringRef PassID,
  160. IRUnitT &Output) = 0;
  161. // Called when the pass is not iteresting.
  162. virtual void omitAfter(StringRef PassID, std::string &Name) = 0;
  163. // Called when an interesting IR has changed.
  164. virtual void handleAfter(StringRef PassID, std::string &Name,
  165. const IRUnitT &Before, const IRUnitT &After,
  166. Any) = 0;
  167. // Called when an interesting pass is invalidated.
  168. virtual void handleInvalidated(StringRef PassID) = 0;
  169. // Called when the IR or pass is not interesting.
  170. virtual void handleFiltered(StringRef PassID, std::string &Name) = 0;
  171. // Called when an ignored pass is encountered.
  172. virtual void handleIgnored(StringRef PassID, std::string &Name) = 0;
  173. // Called to compare the before and after representations of the IR.
  174. virtual bool same(const IRUnitT &Before, const IRUnitT &After) = 0;
  175. // Stack of IRs before passes.
  176. std::vector<IRUnitT> BeforeStack;
  177. // Is this the first IR seen?
  178. bool InitialIR = true;
  179. // Run in verbose mode, printing everything?
  180. const bool VerboseMode;
  181. };
  182. // An abstract template base class that handles printing banners and
  183. // reporting when things have not changed or are filtered out.
  184. template <typename IRUnitT>
  185. class TextChangeReporter : public ChangeReporter<IRUnitT> {
  186. protected:
  187. TextChangeReporter(bool Verbose);
  188. // Print a module dump of the first IR that is changed.
  189. void handleInitialIR(Any IR) override;
  190. // Report that the IR was omitted because it did not change.
  191. void omitAfter(StringRef PassID, std::string &Name) override;
  192. // Report that the pass was invalidated.
  193. void handleInvalidated(StringRef PassID) override;
  194. // Report that the IR was filtered out.
  195. void handleFiltered(StringRef PassID, std::string &Name) override;
  196. // Report that the pass was ignored.
  197. void handleIgnored(StringRef PassID, std::string &Name) override;
  198. // Make substitutions in \p S suitable for reporting changes
  199. // after the pass and then print it.
  200. raw_ostream &Out;
  201. };
  202. // A change printer based on the string representation of the IR as created
  203. // by unwrapAndPrint. The string representation is stored in a std::string
  204. // to preserve it as the IR changes in each pass. Note that the banner is
  205. // included in this representation but it is massaged before reporting.
  206. class IRChangedPrinter : public TextChangeReporter<std::string> {
  207. public:
  208. IRChangedPrinter(bool VerboseMode)
  209. : TextChangeReporter<std::string>(VerboseMode) {}
  210. ~IRChangedPrinter() override;
  211. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  212. protected:
  213. // Called before and after a pass to get the representation of the IR.
  214. void generateIRRepresentation(Any IR, StringRef PassID,
  215. std::string &Output) override;
  216. // Called when an interesting IR has changed.
  217. void handleAfter(StringRef PassID, std::string &Name,
  218. const std::string &Before, const std::string &After,
  219. Any) override;
  220. // Called to compare the before and after representations of the IR.
  221. bool same(const std::string &Before, const std::string &After) override;
  222. };
  223. class VerifyInstrumentation {
  224. bool DebugLogging;
  225. public:
  226. VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
  227. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  228. };
  229. /// This class provides an interface to register all the standard pass
  230. /// instrumentations and manages their state (if any).
  231. class StandardInstrumentations {
  232. PrintIRInstrumentation PrintIR;
  233. PrintPassInstrumentation PrintPass;
  234. TimePassesHandler TimePasses;
  235. OptNoneInstrumentation OptNone;
  236. OptBisectInstrumentation OptBisect;
  237. PreservedCFGCheckerInstrumentation PreservedCFGChecker;
  238. IRChangedPrinter PrintChangedIR;
  239. PseudoProbeVerifier PseudoProbeVerification;
  240. VerifyInstrumentation Verify;
  241. bool VerifyEach;
  242. public:
  243. StandardInstrumentations(bool DebugLogging, bool VerifyEach = false);
  244. void registerCallbacks(PassInstrumentationCallbacks &PIC);
  245. TimePassesHandler &getTimePasses() { return TimePasses; }
  246. };
  247. extern template class ChangeReporter<std::string>;
  248. extern template class TextChangeReporter<std::string>;
  249. } // namespace llvm
  250. #endif
  251. #ifdef __GNUC__
  252. #pragma GCC diagnostic pop
  253. #endif