Index: llvm/include/llvm/Passes/StandardInstrumentations.h =================================================================== --- llvm/include/llvm/Passes/StandardInstrumentations.h +++ llvm/include/llvm/Passes/StandardInstrumentations.h @@ -137,12 +137,12 @@ // 6. When a pass is run on an IR that is not interesting (based on options). // 7. When a pass is ignored (pass manager or adapter pass). // 8. To compare two IR representations (of type \p T). -template class ChangePrinter { +template class ChangeReporter { protected: - ChangePrinter() {} + ChangeReporter() {} public: - virtual ~ChangePrinter(); + virtual ~ChangeReporter(); // Determine if this pass/IR is interesting and if so, save the IR // otherwise it is left on the stack without data. @@ -153,6 +153,33 @@ void handleInvalidatedPass(StringRef PassID); protected: + // Register required callbacks. + void registerRequiredCallbacks(llvm::PassInstrumentationCallbacks &PIC) { + PIC.registerBeforePassCallback([this](llvm::StringRef P, llvm::Any IR) { + saveIRBeforePass(IR, P); + return true; + }); + + PIC.registerAfterPassCallback( + [this](llvm::StringRef P, llvm::Any IR, + const llvm::PreservedAnalyses &) { handleIRAfterPass(IR, P); }); + PIC.registerAfterPassInvalidatedCallback( + [this](llvm::StringRef P, const llvm::PreservedAnalyses &) { + handleInvalidatedPass(P); + }); + } + + // Return true when this is a defined function for which printing + // of changes is desired. + inline bool isInterestingFunction(const llvm::Function &F); + + // Return true when this is a pass for which printing of changes is desired. + inline bool isInterestingPass(llvm::StringRef PassID); + + // Return true when this is a pass on IR for which printing + // of changes is desired. + inline bool isInteresting(llvm::Any IR, llvm::StringRef PassID); + // Called on the first IR processed. virtual void handleInitialIR(Any IR) = 0; // Called before and after a pass to get the representation of the IR. @@ -179,38 +206,49 @@ bool InitialIR = true; }; +// An abstract template base class that handles printing banners and +// reporting when things have not changed or are filtered out. +template +class TextChangeReporter : public ChangeReporter { +protected: + TextChangeReporter(); + + // Print a module dump of the first IR that is changed. + void handleInitialIR(llvm::Any IR) override; + // Report that the IR was omitted because it did not change. + void omitAfter(llvm::StringRef PassID, std::string &Name) override; + // Report that the pass was invalidated. + void handleInvalidated(llvm::StringRef PassID) override; + // Report that the IR was filtered out. + void handleFiltered(llvm::StringRef PassID, std::string &Name) override; + // Report that the pass was ignored. + void handleIgnored(llvm::StringRef PassID, std::string &Name) override; + // Make substitutions in \p S suitable for reporting changes + // after the pass and then print it. + + llvm::raw_ostream &Out; +}; + // A change printer based on the string representation of the IR as created // by unwrapAndPrint. The string representation is stored in a std::string // to preserve it as the IR changes in each pass. Note that the banner is // included in this representation but it is massaged before reporting. -class IRChangePrinter : public ChangePrinter { +class IRChangedPrinter : public TextChangeReporter { public: - IRChangePrinter(); - ~IRChangePrinter() override; + IRChangedPrinter() {} + ~IRChangedPrinter() override; void registerCallbacks(PassInstrumentationCallbacks &PIC); protected: - // Called on the first IR processed. - void handleInitialIR(Any IR) override; // Called before and after a pass to get the representation of the IR. void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override; - // Called when the pass is not iteresting. - void omitAfter(StringRef PassID, std::string &Name) override; // Called when an interesting IR has changed. void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override; - // Called when an interesting pass is invalidated. - void handleInvalidated(StringRef PassID) override; - // Called when the IR or pass is not interesting. - void handleFiltered(StringRef PassID, std::string &Name) override; - // Called when an ignored pass is encountered. - void handleIgnored(StringRef PassID, std::string &Name) override; // Called to compare the before and after representations of the IR. bool same(const std::string &Before, const std::string &After) override; - - raw_ostream &Out; }; class VerifyInstrumentation { @@ -229,7 +267,7 @@ TimePassesHandler TimePasses; OptNoneInstrumentation OptNone; PreservedCFGCheckerInstrumentation PreservedCFGChecker; - IRChangePrinter PrintChangedIR; + IRChangedPrinter PrintChangedIR; VerifyInstrumentation Verify; bool VerifyEach; @@ -242,6 +280,10 @@ TimePassesHandler &getTimePasses() { return TimePasses; } }; + +extern template class ChangeReporter; +extern template class TextChangeReporter; + } // namespace llvm #endif Index: llvm/lib/Passes/StandardInstrumentations.cpp =================================================================== --- llvm/lib/Passes/StandardInstrumentations.cpp +++ llvm/lib/Passes/StandardInstrumentations.cpp @@ -239,14 +239,20 @@ {"PassManager", "PassAdaptor", "AnalysisManagerProxy"}); } -// Return true when this is a defined function for which printing -// of changes is desired. -bool isInterestingFunction(const Function &F) { +} // namespace + +template +ChangeReporter::~ChangeReporter() { + assert(BeforeStack.empty() && "Problem with Change Printer stack."); +} + +template +bool ChangeReporter::isInterestingFunction(const Function &F) { return llvm::isFunctionInPrintList(F.getName()); } -// Return true when this is a pass for which printing of changes is desired. -bool isInterestingPass(StringRef PassID) { +template +bool ChangeReporter::isInterestingPass(StringRef PassID) { if (isIgnored(PassID)) return false; @@ -257,7 +263,8 @@ // Return true when this is a pass on IR for which printing // of changes is desired. -bool isInteresting(Any IR, StringRef PassID) { +template +bool ChangeReporter::isInteresting(Any IR, StringRef PassID) { if (!isInterestingPass(PassID)) return false; if (any_isa(IR)) @@ -265,10 +272,8 @@ return true; } -} // namespace - template -void ChangePrinter::saveIRBeforePass(Any IR, StringRef PassID) { +void ChangeReporter::saveIRBeforePass(Any IR, StringRef PassID) { // Always need to place something on the stack because invalidated passes // are not given the IR so it cannot be determined whether the pass was for // something that was filtered out. @@ -288,7 +293,7 @@ } template -void ChangePrinter::handleIRAfterPass(Any IR, StringRef PassID) { +void ChangeReporter::handleIRAfterPass(Any IR, StringRef PassID) { assert(!BeforeStack.empty() && "Unexpected empty stack encountered."); std::string Name; @@ -300,7 +305,7 @@ if (auto UM = unwrapModule(IR)) Name = UM->second; } - if (Name.empty()) + if (Name == "") Name = " (module)"; if (isIgnored(PassID)) @@ -324,7 +329,7 @@ } template -void ChangePrinter::handleInvalidatedPass(StringRef PassID) { +void ChangeReporter::handleInvalidatedPass(StringRef PassID) { assert(!BeforeStack.empty() && "Unexpected empty stack encountered."); // Always flag it as invalidated as we cannot determine when @@ -335,34 +340,12 @@ BeforeStack.pop_back(); } -template ChangePrinter::~ChangePrinter() { - assert(BeforeStack.empty() && "Problem with Change Printer stack."); -} - -IRChangePrinter::IRChangePrinter() : Out(dbgs()) {} - -IRChangePrinter::~IRChangePrinter() {} - -void IRChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) { - if (!PrintChanged) - return; - - PIC.registerBeforePassCallback([this](StringRef P, Any IR) { - saveIRBeforePass(IR, P); - return true; - }); - - PIC.registerAfterPassCallback( - [this](StringRef P, Any IR, const PreservedAnalyses &) { - handleIRAfterPass(IR, P); - }); - PIC.registerAfterPassInvalidatedCallback( - [this](StringRef P, const PreservedAnalyses &) { - handleInvalidatedPass(P); - }); -} +template +TextChangeReporter::TextChangeReporter() + : ChangeReporter(), Out(dbgs()) {} -void IRChangePrinter::handleInitialIR(Any IR) { +template +void TextChangeReporter::handleInitialIR(Any IR) { // Always print the module. // Unwrap and print directly to avoid filtering problems in general routines. auto UnwrappedModule = unwrapModule(IR, /*Force=*/true); @@ -372,55 +355,67 @@ /*ShouldPreserveUseListOrder=*/true); } -void IRChangePrinter::generateIRRepresentation(Any IR, StringRef PassID, - std::string &Output) { - raw_string_ostream OS(Output); - // use the after banner for all cases so it will match - SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); - unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR(), - /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true); - OS.str(); -} - -void IRChangePrinter::omitAfter(StringRef PassID, std::string &Name) { +template +void TextChangeReporter::omitAfter(StringRef PassID, + std::string &Name) { Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n", PassID, Name); } -void IRChangePrinter::handleAfter(StringRef PassID, std::string &Name, - const std::string &Before, - const std::string &After, Any) { - assert(After.find("*** IR Dump") == 0 && "Unexpected banner format."); - StringRef AfterRef = After; - StringRef Banner = - AfterRef.take_until([](char C) -> bool { return C == '\n'; }); - Out << Banner; - - // LazyCallGraph::SCC already has "(scc:..." in banner so only add - // in the name if it isn't already there. - if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR()) - Out << Name; - - Out << After.substr(Banner.size()); -} - -void IRChangePrinter::handleInvalidated(StringRef PassID) { +template +void TextChangeReporter::handleInvalidated(StringRef PassID) { Out << formatv("*** IR Pass {0} invalidated ***\n", PassID); } -void IRChangePrinter::handleFiltered(StringRef PassID, std::string &Name) { +template +void TextChangeReporter::handleFiltered(StringRef PassID, + std::string &Name) { SmallString<20> Banner = formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name); Out << Banner; } -void IRChangePrinter::handleIgnored(StringRef PassID, std::string &Name) { +template +void TextChangeReporter::handleIgnored(StringRef PassID, + std::string &Name) { Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name); } -bool IRChangePrinter::same(const std::string &Before, - const std::string &After) { - return Before == After; +IRChangedPrinter::~IRChangedPrinter() {} + +void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) { + if (PrintChanged) + TextChangeReporter::registerRequiredCallbacks(PIC); +} + +void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID, + std::string &Output) { + raw_string_ostream OS(Output); + // use the after banner for all cases so it will match + SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); + unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR(), + /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true); + + OS.str(); +} + +void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name, + const std::string &Before, + const std::string &After, Any IR) { + assert(After.find("*** IR Dump") == 0 && "Unexpected banner format."); + StringRef S = After; + StringRef Banner = S.take_until([](char C) -> bool { return C == '\n'; }); + Out << Banner; + + // LazyCallGraph::SCC already has "(scc:..." in banner so only + // add in the name if it isn't already there. + if (Name.substr(0, 6).compare(" (scc:") != 0 && !llvm::forcePrintModuleIR()) + Out << Name; + Out << S.substr(Banner.size()); +} + +bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) { + return S1.compare(S2) == 0; } PrintIRInstrumentation::~PrintIRInstrumentation() { @@ -772,3 +767,10 @@ if (VerifyEach) Verify.registerCallbacks(PIC); } + +namespace llvm { + +template class ChangeReporter; +template class TextChangeReporter; + +} // namespace llvm