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