File indexing completed on 2026-05-10 08:44:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
0016 #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
0017
0018 #include "llvm/ADT/STLExtras.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/ADT/StringSet.h"
0022 #include "llvm/CodeGen/MachineBasicBlock.h"
0023 #include "llvm/IR/BasicBlock.h"
0024 #include "llvm/IR/DebugInfoMetadata.h"
0025 #include "llvm/IR/OptBisect.h"
0026 #include "llvm/IR/PassTimingInfo.h"
0027 #include "llvm/IR/ValueHandle.h"
0028 #include "llvm/Passes/DroppedVariableStatsIR.h"
0029 #include "llvm/Support/CommandLine.h"
0030 #include "llvm/Support/TimeProfiler.h"
0031 #include "llvm/Transforms/IPO/SampleProfileProbe.h"
0032
0033 #include <string>
0034 #include <utility>
0035
0036 namespace llvm {
0037
0038 class Module;
0039 class Function;
0040 class MachineFunction;
0041 class PassInstrumentationCallbacks;
0042
0043
0044
0045
0046
0047 class PrintIRInstrumentation {
0048 public:
0049 ~PrintIRInstrumentation();
0050
0051 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0052
0053 private:
0054 struct PassRunDescriptor {
0055 const Module *M;
0056 const std::string DumpIRFilename;
0057 const std::string IRName;
0058 const StringRef PassID;
0059
0060 PassRunDescriptor(const Module *M, std::string DumpIRFilename,
0061 std::string IRName, const StringRef PassID)
0062 : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName}, PassID(PassID) {
0063 }
0064 };
0065
0066 void printBeforePass(StringRef PassID, Any IR);
0067 void printAfterPass(StringRef PassID, Any IR);
0068 void printAfterPassInvalidated(StringRef PassID);
0069
0070 bool shouldPrintBeforePass(StringRef PassID);
0071 bool shouldPrintAfterPass(StringRef PassID);
0072 bool shouldPrintBeforeCurrentPassNumber();
0073 bool shouldPrintAfterCurrentPassNumber();
0074 bool shouldPrintPassNumbers();
0075 bool shouldPrintBeforeSomePassNumber();
0076 bool shouldPrintAfterSomePassNumber();
0077
0078 void pushPassRunDescriptor(StringRef PassID, Any IR,
0079 std::string &DumpIRFilename);
0080 PassRunDescriptor popPassRunDescriptor(StringRef PassID);
0081 std::string fetchDumpFilename(StringRef PassId, Any IR);
0082
0083 PassInstrumentationCallbacks *PIC;
0084
0085
0086 SmallVector<PassRunDescriptor, 2> PassRunDescriptorStack;
0087
0088
0089 unsigned CurrentPassNumber = 0;
0090 };
0091
0092 class OptNoneInstrumentation {
0093 public:
0094 OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
0095 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0096
0097 private:
0098 bool DebugLogging;
0099 bool shouldRun(StringRef PassID, Any IR);
0100 };
0101
0102 class OptPassGateInstrumentation {
0103 LLVMContext &Context;
0104 bool HasWrittenIR = false;
0105 public:
0106 OptPassGateInstrumentation(LLVMContext &Context) : Context(Context) {}
0107 bool shouldRun(StringRef PassName, Any IR);
0108 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0109 };
0110
0111 struct PrintPassOptions {
0112
0113 bool Verbose = false;
0114
0115 bool SkipAnalyses = false;
0116
0117 bool Indent = false;
0118 };
0119
0120
0121 class PrintPassInstrumentation {
0122 raw_ostream &print();
0123
0124 public:
0125 PrintPassInstrumentation(bool Enabled, PrintPassOptions Opts)
0126 : Enabled(Enabled), Opts(Opts) {}
0127 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0128
0129 private:
0130 bool Enabled;
0131 PrintPassOptions Opts;
0132 int Indent = 0;
0133 };
0134
0135 class PreservedCFGCheckerInstrumentation {
0136 public:
0137
0138
0139 struct BBGuard final : public CallbackVH {
0140 BBGuard(const BasicBlock *BB) : CallbackVH(BB) {}
0141 void deleted() override { CallbackVH::deleted(); }
0142 void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); }
0143 bool isPoisoned() const { return !getValPtr(); }
0144 };
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 struct CFG {
0155 std::optional<DenseMap<intptr_t, BBGuard>> BBGuards;
0156 DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph;
0157
0158 CFG(const Function *F, bool TrackBBLifetime);
0159
0160 bool operator==(const CFG &G) const {
0161 return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph;
0162 }
0163
0164 bool isPoisoned() const {
0165 return BBGuards && llvm::any_of(*BBGuards, [](const auto &BB) {
0166 return BB.second.isPoisoned();
0167 });
0168 }
0169
0170 static void printDiff(raw_ostream &out, const CFG &Before,
0171 const CFG &After);
0172 bool invalidate(Function &F, const PreservedAnalyses &PA,
0173 FunctionAnalysisManager::Invalidator &);
0174 };
0175
0176 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0177 SmallVector<StringRef, 8> PassStack;
0178 #endif
0179
0180 void registerCallbacks(PassInstrumentationCallbacks &PIC,
0181 ModuleAnalysisManager &MAM);
0182 };
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 template <typename IRUnitT> class ChangeReporter {
0200 protected:
0201 ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {}
0202
0203 public:
0204 virtual ~ChangeReporter();
0205
0206
0207
0208 void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName);
0209
0210 void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName);
0211
0212 void handleInvalidatedPass(StringRef PassID);
0213
0214 protected:
0215
0216 void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC);
0217
0218
0219 virtual void handleInitialIR(Any IR) = 0;
0220
0221 virtual void generateIRRepresentation(Any IR, StringRef PassID,
0222 IRUnitT &Output) = 0;
0223
0224 virtual void omitAfter(StringRef PassID, std::string &Name) = 0;
0225
0226 virtual void handleAfter(StringRef PassID, std::string &Name,
0227 const IRUnitT &Before, const IRUnitT &After,
0228 Any) = 0;
0229
0230 virtual void handleInvalidated(StringRef PassID) = 0;
0231
0232 virtual void handleFiltered(StringRef PassID, std::string &Name) = 0;
0233
0234 virtual void handleIgnored(StringRef PassID, std::string &Name) = 0;
0235
0236
0237 std::vector<IRUnitT> BeforeStack;
0238
0239 bool InitialIR = true;
0240
0241
0242 const bool VerboseMode;
0243 };
0244
0245
0246
0247 template <typename IRUnitT>
0248 class TextChangeReporter : public ChangeReporter<IRUnitT> {
0249 protected:
0250 TextChangeReporter(bool Verbose);
0251
0252
0253 void handleInitialIR(Any IR) override;
0254
0255 void omitAfter(StringRef PassID, std::string &Name) override;
0256
0257 void handleInvalidated(StringRef PassID) override;
0258
0259 void handleFiltered(StringRef PassID, std::string &Name) override;
0260
0261 void handleIgnored(StringRef PassID, std::string &Name) override;
0262
0263
0264
0265 raw_ostream &Out;
0266 };
0267
0268
0269
0270
0271
0272 class IRChangedPrinter : public TextChangeReporter<std::string> {
0273 public:
0274 IRChangedPrinter(bool VerboseMode)
0275 : TextChangeReporter<std::string>(VerboseMode) {}
0276 ~IRChangedPrinter() override;
0277 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0278
0279 protected:
0280
0281 void generateIRRepresentation(Any IR, StringRef PassID,
0282 std::string &Output) override;
0283
0284 void handleAfter(StringRef PassID, std::string &Name,
0285 const std::string &Before, const std::string &After,
0286 Any) override;
0287 };
0288
0289 class IRChangedTester : public IRChangedPrinter {
0290 public:
0291 IRChangedTester() : IRChangedPrinter(true) {}
0292 ~IRChangedTester() override;
0293 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0294
0295 protected:
0296 void handleIR(const std::string &IR, StringRef PassID);
0297
0298
0299 void handleInitialIR(Any IR) override;
0300
0301 void omitAfter(StringRef PassID, std::string &Name) override;
0302
0303 void handleInvalidated(StringRef PassID) override;
0304
0305 void handleFiltered(StringRef PassID, std::string &Name) override;
0306
0307 void handleIgnored(StringRef PassID, std::string &Name) override;
0308
0309
0310 void handleAfter(StringRef PassID, std::string &Name,
0311 const std::string &Before, const std::string &After,
0312 Any) override;
0313 };
0314
0315
0316
0317 template <typename T> class BlockDataT {
0318 public:
0319 BlockDataT(const BasicBlock &B) : Label(B.getName().str()), Data(B) {
0320 raw_string_ostream SS(Body);
0321 B.print(SS, nullptr, true, true);
0322 }
0323
0324 BlockDataT(const MachineBasicBlock &B) : Label(B.getName().str()), Data(B) {
0325 raw_string_ostream SS(Body);
0326 B.print(SS);
0327 }
0328
0329 bool operator==(const BlockDataT &That) const { return Body == That.Body; }
0330 bool operator!=(const BlockDataT &That) const { return Body != That.Body; }
0331
0332
0333 StringRef getLabel() const { return Label; }
0334
0335 StringRef getBody() const { return Body; }
0336
0337
0338 const T &getData() const { return Data; }
0339
0340 protected:
0341 std::string Label;
0342 std::string Body;
0343
0344
0345 T Data;
0346 };
0347
0348 template <typename T> class OrderedChangedData {
0349 public:
0350
0351 std::vector<std::string> &getOrder() { return Order; }
0352 const std::vector<std::string> &getOrder() const { return Order; }
0353
0354
0355 StringMap<T> &getData() { return Data; }
0356 const StringMap<T> &getData() const { return Data; }
0357
0358 bool operator==(const OrderedChangedData<T> &That) const {
0359 return Data == That.getData();
0360 }
0361
0362
0363
0364
0365
0366
0367 static void report(const OrderedChangedData &Before,
0368 const OrderedChangedData &After,
0369 function_ref<void(const T *, const T *)> HandlePair);
0370
0371 protected:
0372 std::vector<std::string> Order;
0373 StringMap<T> Data;
0374 };
0375
0376
0377 class EmptyData {
0378 public:
0379 EmptyData(const BasicBlock &) {}
0380 EmptyData(const MachineBasicBlock &) {}
0381 };
0382
0383
0384 template <typename T>
0385 class FuncDataT : public OrderedChangedData<BlockDataT<T>> {
0386 public:
0387 FuncDataT(std::string S) : EntryBlockName(S) {}
0388
0389
0390 std::string getEntryBlockName() const { return EntryBlockName; }
0391
0392 protected:
0393 std::string EntryBlockName;
0394 };
0395
0396
0397 template <typename T>
0398 class IRDataT : public OrderedChangedData<FuncDataT<T>> {};
0399
0400
0401
0402
0403 template <typename T> class IRComparer {
0404 public:
0405 IRComparer(const IRDataT<T> &Before, const IRDataT<T> &After)
0406 : Before(Before), After(After) {}
0407
0408
0409
0410
0411 void compare(
0412 bool CompareModule,
0413 std::function<void(bool InModule, unsigned Minor,
0414 const FuncDataT<T> &Before, const FuncDataT<T> &After)>
0415 CompareFunc);
0416
0417
0418 static void analyzeIR(Any IR, IRDataT<T> &Data);
0419
0420 protected:
0421
0422 template <typename FunctionT>
0423 static bool generateFunctionData(IRDataT<T> &Data, const FunctionT &F);
0424
0425 const IRDataT<T> &Before;
0426 const IRDataT<T> &After;
0427 };
0428
0429
0430
0431
0432
0433
0434
0435 class InLineChangePrinter : public TextChangeReporter<IRDataT<EmptyData>> {
0436 public:
0437 InLineChangePrinter(bool VerboseMode, bool ColourMode)
0438 : TextChangeReporter<IRDataT<EmptyData>>(VerboseMode),
0439 UseColour(ColourMode) {}
0440 ~InLineChangePrinter() override;
0441 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0442
0443 protected:
0444
0445 void generateIRRepresentation(Any IR, StringRef PassID,
0446 IRDataT<EmptyData> &Output) override;
0447
0448
0449 void handleAfter(StringRef PassID, std::string &Name,
0450 const IRDataT<EmptyData> &Before,
0451 const IRDataT<EmptyData> &After, Any) override;
0452
0453 void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID,
0454 StringRef Divider, bool InModule, unsigned Minor,
0455 const FuncDataT<EmptyData> &Before,
0456 const FuncDataT<EmptyData> &After);
0457
0458 bool UseColour;
0459 };
0460
0461 class VerifyInstrumentation {
0462 bool DebugLogging;
0463
0464 public:
0465 VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
0466 void registerCallbacks(PassInstrumentationCallbacks &PIC,
0467 ModuleAnalysisManager *MAM);
0468 };
0469
0470
0471
0472
0473 class TimeProfilingPassesHandler {
0474 public:
0475 TimeProfilingPassesHandler();
0476
0477 TimeProfilingPassesHandler(const TimeProfilingPassesHandler &) = delete;
0478 void operator=(const TimeProfilingPassesHandler &) = delete;
0479
0480 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0481
0482 private:
0483
0484 void runBeforePass(StringRef PassID, Any IR);
0485 void runAfterPass();
0486 };
0487
0488
0489
0490 class DCData {
0491 public:
0492
0493 DCData(const BasicBlock &B);
0494 DCData(const MachineBasicBlock &B);
0495
0496
0497 StringMap<std::string>::const_iterator begin() const {
0498 return Successors.begin();
0499 }
0500 StringMap<std::string>::const_iterator end() const {
0501 return Successors.end();
0502 }
0503
0504
0505 StringRef getSuccessorLabel(StringRef S) const {
0506 assert(Successors.count(S) == 1 && "Expected to find successor.");
0507 return Successors.find(S)->getValue();
0508 }
0509
0510 protected:
0511
0512 void addSuccessorLabel(StringRef Succ, StringRef Label) {
0513 std::pair<std::string, std::string> SS{Succ.str(), Label.str()};
0514 Successors.insert(SS);
0515 }
0516
0517 StringMap<std::string> Successors;
0518 };
0519
0520
0521
0522 class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> {
0523 public:
0524 DotCfgChangeReporter(bool Verbose);
0525 ~DotCfgChangeReporter() override;
0526 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0527
0528 protected:
0529
0530 bool initializeHTML();
0531
0532
0533 void handleInitialIR(Any IR) override;
0534
0535 void generateIRRepresentation(Any IR, StringRef PassID,
0536 IRDataT<DCData> &Output) override;
0537
0538 void omitAfter(StringRef PassID, std::string &Name) override;
0539
0540 void handleAfter(StringRef PassID, std::string &Name,
0541 const IRDataT<DCData> &Before, const IRDataT<DCData> &After,
0542 Any) override;
0543
0544 void handleInvalidated(StringRef PassID) override;
0545
0546 void handleFiltered(StringRef PassID, std::string &Name) override;
0547
0548 void handleIgnored(StringRef PassID, std::string &Name) override;
0549
0550
0551
0552 static std::string genHTML(StringRef Text, StringRef DotFile,
0553 StringRef PDFFileName);
0554
0555 void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID,
0556 StringRef Divider, bool InModule, unsigned Minor,
0557 const FuncDataT<DCData> &Before,
0558 const FuncDataT<DCData> &After);
0559
0560 unsigned N = 0;
0561 std::unique_ptr<raw_fd_ostream> HTML;
0562 };
0563
0564
0565 class PrintCrashIRInstrumentation {
0566 public:
0567 PrintCrashIRInstrumentation()
0568 : SavedIR("*** Dump of IR Before Last Pass Unknown ***") {}
0569 ~PrintCrashIRInstrumentation();
0570 void registerCallbacks(PassInstrumentationCallbacks &PIC);
0571 void reportCrashIR();
0572
0573 protected:
0574 std::string SavedIR;
0575
0576 private:
0577
0578 static PrintCrashIRInstrumentation *CrashReporter;
0579
0580 static void SignalHandler(void *);
0581 };
0582
0583
0584
0585 class StandardInstrumentations {
0586 PrintIRInstrumentation PrintIR;
0587 PrintPassInstrumentation PrintPass;
0588 TimePassesHandler TimePasses;
0589 TimeProfilingPassesHandler TimeProfilingPasses;
0590 OptNoneInstrumentation OptNone;
0591 OptPassGateInstrumentation OptPassGate;
0592 PreservedCFGCheckerInstrumentation PreservedCFGChecker;
0593 IRChangedPrinter PrintChangedIR;
0594 PseudoProbeVerifier PseudoProbeVerification;
0595 InLineChangePrinter PrintChangedDiff;
0596 DotCfgChangeReporter WebsiteChangeReporter;
0597 PrintCrashIRInstrumentation PrintCrashIR;
0598 IRChangedTester ChangeTester;
0599 VerifyInstrumentation Verify;
0600 DroppedVariableStatsIR DroppedStatsIR;
0601
0602 bool VerifyEach;
0603
0604 public:
0605 StandardInstrumentations(LLVMContext &Context, bool DebugLogging,
0606 bool VerifyEach = false,
0607 PrintPassOptions PrintPassOpts = PrintPassOptions());
0608
0609
0610
0611 void registerCallbacks(PassInstrumentationCallbacks &PIC,
0612 ModuleAnalysisManager *MAM = nullptr);
0613
0614 TimePassesHandler &getTimePasses() { return TimePasses; }
0615 };
0616
0617 extern template class ChangeReporter<std::string>;
0618 extern template class TextChangeReporter<std::string>;
0619
0620 extern template class BlockDataT<EmptyData>;
0621 extern template class FuncDataT<EmptyData>;
0622 extern template class IRDataT<EmptyData>;
0623 extern template class ChangeReporter<IRDataT<EmptyData>>;
0624 extern template class TextChangeReporter<IRDataT<EmptyData>>;
0625 extern template class IRComparer<EmptyData>;
0626
0627 }
0628
0629 #endif