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/STLExtras.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/ADT/StringSet.h" |
22 | #include "llvm/CodeGen/MachineBasicBlock.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/Support/TimeProfiler.h" |
29 | #include "llvm/Transforms/IPO/SampleProfileProbe.h" |
30 | |
31 | #include <string> |
32 | #include <utility> |
33 | |
34 | namespace llvm { |
35 | |
36 | class Module; |
37 | class Function; |
38 | class MachineFunction; |
39 | class PassInstrumentationCallbacks; |
40 | |
41 | /// Instrumentation to print IR before/after passes. |
42 | /// |
43 | /// Needs state to be able to print module after pass that invalidates IR unit |
44 | /// (typically Loop or SCC). |
45 | class PrintIRInstrumentation { |
46 | public: |
47 | ~PrintIRInstrumentation(); |
48 | |
49 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
50 | |
51 | private: |
52 | struct PassRunDescriptor { |
53 | const Module *M; |
54 | const std::string DumpIRFilename; |
55 | const std::string IRName; |
56 | const StringRef PassID; |
57 | |
58 | PassRunDescriptor(const Module *M, std::string DumpIRFilename, |
59 | std::string IRName, const StringRef PassID) |
60 | : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName}, PassID(PassID) { |
61 | } |
62 | }; |
63 | |
64 | void printBeforePass(StringRef PassID, Any IR); |
65 | void printAfterPass(StringRef PassID, Any IR); |
66 | void printAfterPassInvalidated(StringRef PassID); |
67 | |
68 | bool shouldPrintBeforePass(StringRef PassID); |
69 | bool shouldPrintAfterPass(StringRef PassID); |
70 | bool shouldPrintBeforeCurrentPassNumber(); |
71 | bool shouldPrintAfterCurrentPassNumber(); |
72 | bool shouldPrintPassNumbers(); |
73 | bool shouldPrintBeforeSomePassNumber(); |
74 | bool shouldPrintAfterSomePassNumber(); |
75 | |
76 | void pushPassRunDescriptor(StringRef PassID, Any IR, |
77 | std::string &DumpIRFilename); |
78 | PassRunDescriptor popPassRunDescriptor(StringRef PassID); |
79 | std::string fetchDumpFilename(StringRef PassId, Any IR); |
80 | |
81 | PassInstrumentationCallbacks *PIC; |
82 | /// Stack of Pass Run descriptions, enough to print the IR unit after a given |
83 | /// pass. |
84 | SmallVector<PassRunDescriptor, 2> PassRunDescriptorStack; |
85 | |
86 | /// Used for print-at-pass-number |
87 | unsigned CurrentPassNumber = 0; |
88 | }; |
89 | |
90 | class OptNoneInstrumentation { |
91 | public: |
92 | OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} |
93 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
94 | |
95 | private: |
96 | bool DebugLogging; |
97 | bool shouldRun(StringRef PassID, Any IR); |
98 | }; |
99 | |
100 | class OptPassGateInstrumentation { |
101 | LLVMContext &Context; |
102 | bool HasWrittenIR = false; |
103 | public: |
104 | OptPassGateInstrumentation(LLVMContext &Context) : Context(Context) {} |
105 | bool shouldRun(StringRef PassName, Any IR); |
106 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
107 | }; |
108 | |
109 | struct PrintPassOptions { |
110 | /// Print adaptors and pass managers. |
111 | bool Verbose = false; |
112 | /// Don't print information for analyses. |
113 | bool SkipAnalyses = false; |
114 | /// Indent based on hierarchy. |
115 | bool Indent = false; |
116 | }; |
117 | |
118 | // Debug logging for transformation and analysis passes. |
119 | class PrintPassInstrumentation { |
120 | raw_ostream &print(); |
121 | |
122 | public: |
123 | PrintPassInstrumentation(bool Enabled, PrintPassOptions Opts) |
124 | : Enabled(Enabled), Opts(Opts) {} |
125 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
126 | |
127 | private: |
128 | bool Enabled; |
129 | PrintPassOptions Opts; |
130 | int Indent = 0; |
131 | }; |
132 | |
133 | class PreservedCFGCheckerInstrumentation { |
134 | public: |
135 | // Keeps sticky poisoned flag for the given basic block once it has been |
136 | // deleted or RAUWed. |
137 | struct BBGuard final : public CallbackVH { |
138 | BBGuard(const BasicBlock *BB) : CallbackVH(BB) {} |
139 | void deleted() override { CallbackVH::deleted(); } |
140 | void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); } |
141 | bool isPoisoned() const { return !getValPtr(); } |
142 | }; |
143 | |
144 | // CFG is a map BB -> {(Succ, Multiplicity)}, where BB is a non-leaf basic |
145 | // block, {(Succ, Multiplicity)} set of all pairs of the block's successors |
146 | // and the multiplicity of the edge (BB->Succ). As the mapped sets are |
147 | // unordered the order of successors is not tracked by the CFG. In other words |
148 | // this allows basic block successors to be swapped by a pass without |
149 | // reporting a CFG change. CFG can be guarded by basic block tracking pointers |
150 | // in the Graph (BBGuard). That is if any of the block is deleted or RAUWed |
151 | // then the CFG is treated poisoned and no block pointer of the Graph is used. |
152 | struct CFG { |
153 | std::optional<DenseMap<intptr_t, BBGuard>> BBGuards; |
154 | DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph; |
155 | |
156 | CFG(const Function *F, bool TrackBBLifetime); |
157 | |
158 | bool operator==(const CFG &G) const { |
159 | return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph; |
160 | } |
161 | |
162 | bool isPoisoned() const { |
163 | return BBGuards && llvm::any_of(Range: *BBGuards, P: [](const auto &BB) { |
164 | return BB.second.isPoisoned(); |
165 | }); |
166 | } |
167 | |
168 | static void printDiff(raw_ostream &out, const CFG &Before, |
169 | const CFG &After); |
170 | bool invalidate(Function &F, const PreservedAnalyses &PA, |
171 | FunctionAnalysisManager::Invalidator &); |
172 | }; |
173 | |
174 | #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS |
175 | SmallVector<StringRef, 8> PassStack; |
176 | #endif |
177 | |
178 | void registerCallbacks(PassInstrumentationCallbacks &PIC, |
179 | ModuleAnalysisManager &MAM); |
180 | }; |
181 | |
182 | // Base class for classes that report changes to the IR. |
183 | // It presents an interface for such classes and provides calls |
184 | // on various events as the new pass manager transforms the IR. |
185 | // It also provides filtering of information based on hidden options |
186 | // specifying which functions are interesting. |
187 | // Calls are made for the following events/queries: |
188 | // 1. The initial IR processed. |
189 | // 2. To get the representation of the IR (of type \p T). |
190 | // 3. When a pass does not change the IR. |
191 | // 4. When a pass changes the IR (given both before and after representations |
192 | // of type \p T). |
193 | // 5. When an IR is invalidated. |
194 | // 6. When a pass is run on an IR that is not interesting (based on options). |
195 | // 7. When a pass is ignored (pass manager or adapter pass). |
196 | // 8. To compare two IR representations (of type \p T). |
197 | template <typename IRUnitT> class ChangeReporter { |
198 | protected: |
199 | ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {} |
200 | |
201 | public: |
202 | virtual ~ChangeReporter(); |
203 | |
204 | // Determine if this pass/IR is interesting and if so, save the IR |
205 | // otherwise it is left on the stack without data. |
206 | void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName); |
207 | // Compare the IR from before the pass after the pass. |
208 | void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName); |
209 | // Handle the situation where a pass is invalidated. |
210 | void handleInvalidatedPass(StringRef PassID); |
211 | |
212 | protected: |
213 | // Register required callbacks. |
214 | void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC); |
215 | |
216 | // Called on the first IR processed. |
217 | virtual void handleInitialIR(Any IR) = 0; |
218 | // Called before and after a pass to get the representation of the IR. |
219 | virtual void generateIRRepresentation(Any IR, StringRef PassID, |
220 | IRUnitT &Output) = 0; |
221 | // Called when the pass is not iteresting. |
222 | virtual void omitAfter(StringRef PassID, std::string &Name) = 0; |
223 | // Called when an interesting IR has changed. |
224 | virtual void handleAfter(StringRef PassID, std::string &Name, |
225 | const IRUnitT &Before, const IRUnitT &After, |
226 | Any) = 0; |
227 | // Called when an interesting pass is invalidated. |
228 | virtual void handleInvalidated(StringRef PassID) = 0; |
229 | // Called when the IR or pass is not interesting. |
230 | virtual void handleFiltered(StringRef PassID, std::string &Name) = 0; |
231 | // Called when an ignored pass is encountered. |
232 | virtual void handleIgnored(StringRef PassID, std::string &Name) = 0; |
233 | |
234 | // Stack of IRs before passes. |
235 | std::vector<IRUnitT> BeforeStack; |
236 | // Is this the first IR seen? |
237 | bool InitialIR = true; |
238 | |
239 | // Run in verbose mode, printing everything? |
240 | const bool VerboseMode; |
241 | }; |
242 | |
243 | // An abstract template base class that handles printing banners and |
244 | // reporting when things have not changed or are filtered out. |
245 | template <typename IRUnitT> |
246 | class TextChangeReporter : public ChangeReporter<IRUnitT> { |
247 | protected: |
248 | TextChangeReporter(bool Verbose); |
249 | |
250 | // Print a module dump of the first IR that is changed. |
251 | void handleInitialIR(Any IR) override; |
252 | // Report that the IR was omitted because it did not change. |
253 | void omitAfter(StringRef PassID, std::string &Name) override; |
254 | // Report that the pass was invalidated. |
255 | void handleInvalidated(StringRef PassID) override; |
256 | // Report that the IR was filtered out. |
257 | void handleFiltered(StringRef PassID, std::string &Name) override; |
258 | // Report that the pass was ignored. |
259 | void handleIgnored(StringRef PassID, std::string &Name) override; |
260 | // Make substitutions in \p S suitable for reporting changes |
261 | // after the pass and then print it. |
262 | |
263 | raw_ostream &Out; |
264 | }; |
265 | |
266 | // A change printer based on the string representation of the IR as created |
267 | // by unwrapAndPrint. The string representation is stored in a std::string |
268 | // to preserve it as the IR changes in each pass. Note that the banner is |
269 | // included in this representation but it is massaged before reporting. |
270 | class IRChangedPrinter : public TextChangeReporter<std::string> { |
271 | public: |
272 | IRChangedPrinter(bool VerboseMode) |
273 | : TextChangeReporter<std::string>(VerboseMode) {} |
274 | ~IRChangedPrinter() override; |
275 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
276 | |
277 | protected: |
278 | // Called before and after a pass to get the representation of the IR. |
279 | void generateIRRepresentation(Any IR, StringRef PassID, |
280 | std::string &Output) override; |
281 | // Called when an interesting IR has changed. |
282 | void handleAfter(StringRef PassID, std::string &Name, |
283 | const std::string &Before, const std::string &After, |
284 | Any) override; |
285 | }; |
286 | |
287 | class IRChangedTester : public IRChangedPrinter { |
288 | public: |
289 | IRChangedTester() : IRChangedPrinter(true) {} |
290 | ~IRChangedTester() override; |
291 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
292 | |
293 | protected: |
294 | void handleIR(const std::string &IR, StringRef PassID); |
295 | |
296 | // Check initial IR |
297 | void handleInitialIR(Any IR) override; |
298 | // Do nothing. |
299 | void omitAfter(StringRef PassID, std::string &Name) override; |
300 | // Do nothing. |
301 | void handleInvalidated(StringRef PassID) override; |
302 | // Do nothing. |
303 | void handleFiltered(StringRef PassID, std::string &Name) override; |
304 | // Do nothing. |
305 | void handleIgnored(StringRef PassID, std::string &Name) override; |
306 | |
307 | // Call test as interesting IR has changed. |
308 | void handleAfter(StringRef PassID, std::string &Name, |
309 | const std::string &Before, const std::string &After, |
310 | Any) override; |
311 | }; |
312 | |
313 | // Information that needs to be saved for a basic block in order to compare |
314 | // before and after the pass to determine if it was changed by a pass. |
315 | template <typename T> class BlockDataT { |
316 | public: |
317 | BlockDataT(const BasicBlock &B) : Label(B.getName().str()), Data(B) { |
318 | raw_string_ostream SS(Body); |
319 | B.print(OS&: SS, AAW: nullptr, ShouldPreserveUseListOrder: true, IsForDebug: true); |
320 | } |
321 | |
322 | BlockDataT(const MachineBasicBlock &B) : Label(B.getName().str()), Data(B) { |
323 | raw_string_ostream SS(Body); |
324 | B.print(OS&: SS); |
325 | } |
326 | |
327 | bool operator==(const BlockDataT &That) const { return Body == That.Body; } |
328 | bool operator!=(const BlockDataT &That) const { return Body != That.Body; } |
329 | |
330 | // Return the label of the represented basic block. |
331 | StringRef getLabel() const { return Label; } |
332 | // Return the string representation of the basic block. |
333 | StringRef getBody() const { return Body; } |
334 | |
335 | // Return the associated data |
336 | const T &getData() const { return Data; } |
337 | |
338 | protected: |
339 | std::string Label; |
340 | std::string Body; |
341 | |
342 | // Extra data associated with a basic block |
343 | T Data; |
344 | }; |
345 | |
346 | template <typename T> class OrderedChangedData { |
347 | public: |
348 | // Return the names in the order they were saved |
349 | std::vector<std::string> &getOrder() { return Order; } |
350 | const std::vector<std::string> &getOrder() const { return Order; } |
351 | |
352 | // Return a map of names to saved representations |
353 | StringMap<T> &getData() { return Data; } |
354 | const StringMap<T> &getData() const { return Data; } |
355 | |
356 | bool operator==(const OrderedChangedData<T> &That) const { |
357 | return Data == That.getData(); |
358 | } |
359 | |
360 | // Call the lambda \p HandlePair on each corresponding pair of data from |
361 | // \p Before and \p After. The order is based on the order in \p After |
362 | // with ones that are only in \p Before interspersed based on where they |
363 | // occur in \p Before. This is used to present the output in an order |
364 | // based on how the data is ordered in LLVM. |
365 | static void report(const OrderedChangedData &Before, |
366 | const OrderedChangedData &After, |
367 | function_ref<void(const T *, const T *)> HandlePair); |
368 | |
369 | protected: |
370 | std::vector<std::string> Order; |
371 | StringMap<T> Data; |
372 | }; |
373 | |
374 | // Do not need extra information for patch-style change reporter. |
375 | class EmptyData { |
376 | public: |
377 | EmptyData(const BasicBlock &) {} |
378 | EmptyData(const MachineBasicBlock &) {} |
379 | }; |
380 | |
381 | // The data saved for comparing functions. |
382 | template <typename T> |
383 | class FuncDataT : public OrderedChangedData<BlockDataT<T>> { |
384 | public: |
385 | FuncDataT(std::string S) : EntryBlockName(S) {} |
386 | |
387 | // Return the name of the entry block |
388 | std::string getEntryBlockName() const { return EntryBlockName; } |
389 | |
390 | protected: |
391 | std::string EntryBlockName; |
392 | }; |
393 | |
394 | // The data saved for comparing IRs. |
395 | template <typename T> |
396 | class IRDataT : public OrderedChangedData<FuncDataT<T>> {}; |
397 | |
398 | // Abstract template base class for a class that compares two IRs. The |
399 | // class is created with the 2 IRs to compare and then compare is called. |
400 | // The static function analyzeIR is used to build up the IR representation. |
401 | template <typename T> class IRComparer { |
402 | public: |
403 | IRComparer(const IRDataT<T> &Before, const IRDataT<T> &After) |
404 | : Before(Before), After(After) {} |
405 | |
406 | // Compare the 2 IRs. \p handleFunctionCompare is called to handle the |
407 | // compare of a function. When \p InModule is set, |
408 | // this function is being handled as part of comparing a module. |
409 | void compare( |
410 | bool CompareModule, |
411 | std::function<void(bool InModule, unsigned Minor, |
412 | const FuncDataT<T> &Before, const FuncDataT<T> &After)> |
413 | CompareFunc); |
414 | |
415 | // Analyze \p IR and build the IR representation in \p Data. |
416 | static void analyzeIR(Any IR, IRDataT<T> &Data); |
417 | |
418 | protected: |
419 | // Generate the data for \p F into \p Data. |
420 | template <typename FunctionT> |
421 | static bool generateFunctionData(IRDataT<T> &Data, const FunctionT &F); |
422 | |
423 | const IRDataT<T> &Before; |
424 | const IRDataT<T> &After; |
425 | }; |
426 | |
427 | // A change printer that prints out in-line differences in the basic |
428 | // blocks. It uses an InlineComparer to do the comparison so it shows |
429 | // the differences prefixed with '-' and '+' for code that is removed |
430 | // and added, respectively. Changes to the IR that do not affect basic |
431 | // blocks are not reported as having changed the IR. The option |
432 | // -print-module-scope does not affect this change reporter. |
433 | class InLineChangePrinter : public TextChangeReporter<IRDataT<EmptyData>> { |
434 | public: |
435 | InLineChangePrinter(bool VerboseMode, bool ColourMode) |
436 | : TextChangeReporter<IRDataT<EmptyData>>(VerboseMode), |
437 | UseColour(ColourMode) {} |
438 | ~InLineChangePrinter() override; |
439 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
440 | |
441 | protected: |
442 | // Create a representation of the IR. |
443 | void generateIRRepresentation(Any IR, StringRef PassID, |
444 | IRDataT<EmptyData> &Output) override; |
445 | |
446 | // Called when an interesting IR has changed. |
447 | void handleAfter(StringRef PassID, std::string &Name, |
448 | const IRDataT<EmptyData> &Before, |
449 | const IRDataT<EmptyData> &After, Any) override; |
450 | |
451 | void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, |
452 | StringRef Divider, bool InModule, unsigned Minor, |
453 | const FuncDataT<EmptyData> &Before, |
454 | const FuncDataT<EmptyData> &After); |
455 | |
456 | bool UseColour; |
457 | }; |
458 | |
459 | class VerifyInstrumentation { |
460 | bool DebugLogging; |
461 | |
462 | public: |
463 | VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} |
464 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
465 | }; |
466 | |
467 | /// This class implements --time-trace functionality for new pass manager. |
468 | /// It provides the pass-instrumentation callbacks that measure the pass |
469 | /// execution time. They collect time tracing info by TimeProfiler. |
470 | class TimeProfilingPassesHandler { |
471 | public: |
472 | TimeProfilingPassesHandler(); |
473 | // We intend this to be unique per-compilation, thus no copies. |
474 | TimeProfilingPassesHandler(const TimeProfilingPassesHandler &) = delete; |
475 | void operator=(const TimeProfilingPassesHandler &) = delete; |
476 | |
477 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
478 | |
479 | private: |
480 | // Implementation of pass instrumentation callbacks. |
481 | void runBeforePass(StringRef PassID, Any IR); |
482 | void runAfterPass(); |
483 | }; |
484 | |
485 | // Class that holds transitions between basic blocks. The transitions |
486 | // are contained in a map of values to names of basic blocks. |
487 | class DCData { |
488 | public: |
489 | // Fill the map with the transitions from basic block \p B. |
490 | DCData(const BasicBlock &B); |
491 | DCData(const MachineBasicBlock &B); |
492 | |
493 | // Return an iterator to the names of the successor blocks. |
494 | StringMap<std::string>::const_iterator begin() const { |
495 | return Successors.begin(); |
496 | } |
497 | StringMap<std::string>::const_iterator end() const { |
498 | return Successors.end(); |
499 | } |
500 | |
501 | // Return the label of the basic block reached on a transition on \p S. |
502 | StringRef getSuccessorLabel(StringRef S) const { |
503 | assert(Successors.count(S) == 1 && "Expected to find successor." ); |
504 | return Successors.find(Key: S)->getValue(); |
505 | } |
506 | |
507 | protected: |
508 | // Add a transition to \p Succ on \p Label |
509 | void addSuccessorLabel(StringRef Succ, StringRef Label) { |
510 | std::pair<std::string, std::string> SS{Succ.str(), Label.str()}; |
511 | Successors.insert(KV: SS); |
512 | } |
513 | |
514 | StringMap<std::string> Successors; |
515 | }; |
516 | |
517 | // A change reporter that builds a website with links to pdf files showing |
518 | // dot control flow graphs with changed instructions shown in colour. |
519 | class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> { |
520 | public: |
521 | DotCfgChangeReporter(bool Verbose); |
522 | ~DotCfgChangeReporter() override; |
523 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
524 | |
525 | protected: |
526 | // Initialize the HTML file and output the header. |
527 | bool initializeHTML(); |
528 | |
529 | // Called on the first IR processed. |
530 | void handleInitialIR(Any IR) override; |
531 | // Called before and after a pass to get the representation of the IR. |
532 | void generateIRRepresentation(Any IR, StringRef PassID, |
533 | IRDataT<DCData> &Output) override; |
534 | // Called when the pass is not iteresting. |
535 | void omitAfter(StringRef PassID, std::string &Name) override; |
536 | // Called when an interesting IR has changed. |
537 | void handleAfter(StringRef PassID, std::string &Name, |
538 | const IRDataT<DCData> &Before, const IRDataT<DCData> &After, |
539 | Any) override; |
540 | // Called when an interesting pass is invalidated. |
541 | void handleInvalidated(StringRef PassID) override; |
542 | // Called when the IR or pass is not interesting. |
543 | void handleFiltered(StringRef PassID, std::string &Name) override; |
544 | // Called when an ignored pass is encountered. |
545 | void handleIgnored(StringRef PassID, std::string &Name) override; |
546 | |
547 | // Generate the pdf file into \p Dir / \p PDFFileName using \p DotFile as |
548 | // input and return the html <a> tag with \Text as the content. |
549 | static std::string genHTML(StringRef Text, StringRef DotFile, |
550 | StringRef PDFFileName); |
551 | |
552 | void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, |
553 | StringRef Divider, bool InModule, unsigned Minor, |
554 | const FuncDataT<DCData> &Before, |
555 | const FuncDataT<DCData> &After); |
556 | |
557 | unsigned N = 0; |
558 | std::unique_ptr<raw_fd_ostream> HTML; |
559 | }; |
560 | |
561 | // Print IR on crash. |
562 | class PrintCrashIRInstrumentation { |
563 | public: |
564 | PrintCrashIRInstrumentation() |
565 | : SavedIR("*** Dump of IR Before Last Pass Unknown ***" ) {} |
566 | ~PrintCrashIRInstrumentation(); |
567 | void registerCallbacks(PassInstrumentationCallbacks &PIC); |
568 | void reportCrashIR(); |
569 | |
570 | protected: |
571 | std::string SavedIR; |
572 | |
573 | private: |
574 | // The crash reporter that will report on a crash. |
575 | static PrintCrashIRInstrumentation *CrashReporter; |
576 | // Crash handler registered when print-on-crash is specified. |
577 | static void SignalHandler(void *); |
578 | }; |
579 | |
580 | /// This class provides an interface to register all the standard pass |
581 | /// instrumentations and manages their state (if any). |
582 | class StandardInstrumentations { |
583 | PrintIRInstrumentation PrintIR; |
584 | PrintPassInstrumentation PrintPass; |
585 | TimePassesHandler TimePasses; |
586 | TimeProfilingPassesHandler TimeProfilingPasses; |
587 | OptNoneInstrumentation OptNone; |
588 | OptPassGateInstrumentation OptPassGate; |
589 | PreservedCFGCheckerInstrumentation PreservedCFGChecker; |
590 | IRChangedPrinter PrintChangedIR; |
591 | PseudoProbeVerifier PseudoProbeVerification; |
592 | InLineChangePrinter PrintChangedDiff; |
593 | DotCfgChangeReporter WebsiteChangeReporter; |
594 | PrintCrashIRInstrumentation PrintCrashIR; |
595 | IRChangedTester ChangeTester; |
596 | VerifyInstrumentation Verify; |
597 | |
598 | bool VerifyEach; |
599 | |
600 | public: |
601 | StandardInstrumentations(LLVMContext &Context, bool DebugLogging, |
602 | bool VerifyEach = false, |
603 | PrintPassOptions PrintPassOpts = PrintPassOptions()); |
604 | |
605 | // Register all the standard instrumentation callbacks. If \p FAM is nullptr |
606 | // then PreservedCFGChecker is not enabled. |
607 | void registerCallbacks(PassInstrumentationCallbacks &PIC, |
608 | ModuleAnalysisManager *MAM = nullptr); |
609 | |
610 | TimePassesHandler &getTimePasses() { return TimePasses; } |
611 | }; |
612 | |
613 | extern template class ChangeReporter<std::string>; |
614 | extern template class TextChangeReporter<std::string>; |
615 | |
616 | extern template class BlockDataT<EmptyData>; |
617 | extern template class FuncDataT<EmptyData>; |
618 | extern template class IRDataT<EmptyData>; |
619 | extern template class ChangeReporter<IRDataT<EmptyData>>; |
620 | extern template class TextChangeReporter<IRDataT<EmptyData>>; |
621 | extern template class IRComparer<EmptyData>; |
622 | |
623 | } // namespace llvm |
624 | |
625 | #endif |
626 | |