diff --git a/llvm/include/llvm/IR/IRPrintingPasses.h b/llvm/include/llvm/IR/IRPrintingPasses.h --- a/llvm/include/llvm/IR/IRPrintingPasses.h +++ b/llvm/include/llvm/IR/IRPrintingPasses.h @@ -45,22 +45,6 @@ /// Return true if a pass is for IR printing. bool isIRPrintingPass(Pass *P); -/// isFunctionInPrintList - returns true if a function should be printed via -// debugging options like -print-after-all/-print-before-all. -// Tells if the function IR should be printed by PrinterPass. -extern bool isFunctionInPrintList(StringRef FunctionName); - -/// forcePrintModuleIR - returns true if IR printing passes should -// be printing module IR (even for local-pass printers e.g. function-pass) -// to provide more context, as enabled by debugging option -print-module-scope -// Tells if IR printer should be printing module IR -extern bool forcePrintModuleIR(); - -extern bool shouldPrintBeforePass(); -extern bool shouldPrintBeforePass(StringRef); -extern bool shouldPrintAfterPass(); -extern bool shouldPrintAfterPass(StringRef); - /// Pass for printing a Module as LLVM's text IR assembly. /// /// Note: This pass is for use with the new pass manager. Use the create...Pass @@ -95,6 +79,6 @@ static bool isRequired() { return true; } }; -} // End llvm namespace +} // namespace llvm #endif diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -52,6 +52,7 @@ #include "llvm/ADT/Any.h" #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" #include namespace llvm { @@ -122,6 +123,13 @@ AfterAnalysisCallbacks.emplace_back(std::move(C)); } + /// Add a class name to pass name mapping for use by pass instrumentation. + void addClassToPassName(StringRef ClassName, StringRef PassName); + /// Get the pass name for a given pass class name. + StringRef getPassNameForClassName(StringRef ClassName); + /// Whether or not the class to pass name map contains the pass name. + bool hasPassName(StringRef PassName); + private: friend class PassInstrumentation; @@ -146,6 +154,8 @@ /// These are run on analyses that have been run. SmallVector, 4> AfterAnalysisCallbacks; + + StringMap ClassToPassName; }; /// This class provides instrumentation entry points for the Pass Manager, diff --git a/llvm/include/llvm/IR/PrintPasses.h b/llvm/include/llvm/IR/PrintPasses.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/IR/PrintPasses.h @@ -0,0 +1,44 @@ +//===- PrintPasses.h - Determining whether/when to print IR ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PRINTPASSES_H +#define LLVM_IR_PRINTPASSES_H + +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +// Returns true if printing before/after some pass is enabled, whether all +// passes or a specific pass. +bool shouldPrintBeforeSomePass(); +bool shouldPrintAfterSomePass(); + +// Returns true if we should print before/after a specific pass. The argument +// should be the pass ID, e.g. "instcombine". +bool shouldPrintBeforePass(StringRef PassID); +bool shouldPrintAfterPass(StringRef PassID); + +// Returns true if we should print before/after all passes. +bool shouldPrintBeforeAll(); +bool shouldPrintAfterAll(); + +// The list of passes to print before/after, if we only want to print +// before/after specific passes. +std::vector printBeforePasses(); +std::vector printAfterPasses(); + +// Returns true if we should always print the entire module. +bool forcePrintModuleIR(); + +// Returns true if we should print the function. +bool isFunctionInPrintList(StringRef FunctionName); + +} // namespace llvm + +#endif // LLVM_IR_PRINTPASSES_H diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -19,7 +19,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/OptBisect.h" -#include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" @@ -31,6 +30,7 @@ class Module; class Function; +class PassInstrumentationCallbacks; /// Instrumentation to print IR before/after passes. /// @@ -47,11 +47,15 @@ void printAfterPass(StringRef PassID, Any IR); void printAfterPassInvalidated(StringRef PassID); + bool shouldPrintBeforePass(StringRef PassID); + bool shouldPrintAfterPass(StringRef PassID); + using PrintModuleDesc = std::tuple; void pushModuleDesc(StringRef PassID, Any IR); PrintModuleDesc popModuleDesc(StringRef PassID); + PassInstrumentationCallbacks *PIC; /// Stack of Module description, enough to print the module after a given /// pass. SmallVector ModuleDescStack; diff --git a/llvm/lib/Analysis/CallGraphSCCPass.cpp b/llvm/lib/Analysis/CallGraphSCCPass.cpp --- a/llvm/lib/Analysis/CallGraphSCCPass.cpp +++ b/llvm/lib/Analysis/CallGraphSCCPass.cpp @@ -21,13 +21,13 @@ #include "llvm/Analysis/CallGraph.h" #include "llvm/IR/AbstractCallSite.h" #include "llvm/IR/Function.h" -#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManagers.h" #include "llvm/IR/Module.h" #include "llvm/IR/OptBisect.h" #include "llvm/IR/PassTimingInfo.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/StructuralHash.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -34,6 +34,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/llvm/lib/Analysis/LoopPass.cpp b/llvm/lib/Analysis/LoopPass.cpp --- a/llvm/lib/Analysis/LoopPass.cpp +++ b/llvm/lib/Analysis/LoopPass.cpp @@ -15,11 +15,11 @@ #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/IR/Dominators.h" -#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/OptBisect.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/PassTimingInfo.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/StructuralHash.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" diff --git a/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp b/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp --- a/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp +++ b/llvm/lib/CodeGen/MachineFunctionPrinterPass.cpp @@ -14,7 +14,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SlotIndexes.h" -#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -44,7 +44,7 @@ } bool runOnMachineFunction(MachineFunction &MF) override { - if (!llvm::isFunctionInPrintList(MF.getName())) + if (!isFunctionInPrintList(MF.getName())) return false; OS << "# " << Banner << ":\n"; MF.print(OS, getAnalysisIfAvailable()); diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -44,6 +44,7 @@ PassManager.cpp PassRegistry.cpp PassTimingInfo.cpp + PrintPasses.cpp SafepointIRVerifier.cpp ProfileSummary.cpp Statepoint.cpp diff --git a/llvm/lib/IR/IRPrintingPasses.cpp b/llvm/lib/IR/IRPrintingPasses.cpp --- a/llvm/lib/IR/IRPrintingPasses.cpp +++ b/llvm/lib/IR/IRPrintingPasses.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/LegacyPassNameParser.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassTimingInfo.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/StructuralHash.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" @@ -49,7 +50,7 @@ enum PassDebugLevel { Disabled, Arguments, Structure, Executions, Details }; -} +} // namespace static cl::opt PassDebugging("debug-pass", cl::Hidden, @@ -61,80 +62,6 @@ clEnumVal(Executions, "print pass name before it is executed"), clEnumVal(Details , "print pass details when it is executed"))); -namespace { -typedef llvm::cl::list -PassOptionList; -} - -// Print IR out before/after specified passes. -static PassOptionList -PrintBefore("print-before", - llvm::cl::desc("Print IR before specified passes"), - cl::Hidden); - -static PassOptionList -PrintAfter("print-after", - llvm::cl::desc("Print IR after specified passes"), - cl::Hidden); - -static cl::opt PrintBeforeAll("print-before-all", - llvm::cl::desc("Print IR before each pass"), - cl::init(false), cl::Hidden); -static cl::opt PrintAfterAll("print-after-all", - llvm::cl::desc("Print IR after each pass"), - cl::init(false), cl::Hidden); - -static cl::opt - PrintModuleScope("print-module-scope", - cl::desc("When printing IR for print-[before|after]{-all} " - "and change reporters, always print a module IR"), - cl::init(false), cl::Hidden); - -static cl::list - PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), - cl::desc("Only print IR for functions whose name " - "match this for all print-[before|after][-all] " - "and change reporter options"), - cl::CommaSeparated, cl::Hidden); - -/// This is a helper to determine whether to print IR before or -/// after a pass. - -bool llvm::shouldPrintBeforePass() { - return PrintBeforeAll || !PrintBefore.empty(); -} - -bool llvm::shouldPrintAfterPass() { - return PrintAfterAll || !PrintAfter.empty(); -} - -static bool ShouldPrintBeforeOrAfterPass(StringRef PassID, - PassOptionList &PassesToPrint) { - for (auto *PassInf : PassesToPrint) { - if (PassInf) - if (PassInf->getPassArgument() == PassID) { - return true; - } - } - return false; -} - -bool llvm::shouldPrintBeforePass(StringRef PassID) { - return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PassID, PrintBefore); -} - -bool llvm::shouldPrintAfterPass(StringRef PassID) { - return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PassID, PrintAfter); -} - -bool llvm::forcePrintModuleIR() { return PrintModuleScope; } - -bool llvm::isFunctionInPrintList(StringRef FunctionName) { - static std::unordered_set PrintFuncNames(PrintFuncsList.begin(), - PrintFuncsList.end()); - return PrintFuncNames.empty() || - PrintFuncNames.count(std::string(FunctionName)); -} /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// or higher is specified. bool PMDataManager::isPassDebuggingExecutionsOrMore() const { diff --git a/llvm/lib/IR/PassInstrumentation.cpp b/llvm/lib/IR/PassInstrumentation.cpp --- a/llvm/lib/IR/PassInstrumentation.cpp +++ b/llvm/lib/IR/PassInstrumentation.cpp @@ -17,6 +17,24 @@ namespace llvm { +void PassInstrumentationCallbacks::addClassToPassName(StringRef ClassName, + StringRef PassName) { + ClassToPassName[ClassName] = PassName.str(); +} + +bool PassInstrumentationCallbacks::hasPassName(StringRef PassName) { + for (const auto &E : ClassToPassName) { + if (E.getValue() == PassName) + return true; + } + return false; +} + +StringRef +PassInstrumentationCallbacks::getPassNameForClassName(StringRef ClassName) { + return ClassToPassName[ClassName]; +} + AnalysisKey PassInstrumentationAnalysis::Key; bool isSpecialPass(StringRef PassID, const std::vector &Specials) { diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/IR/PrintPasses.cpp @@ -0,0 +1,92 @@ +//===- PrintPasses.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/PrintPasses.h" +#include "llvm/Support/CommandLine.h" +#include + +using namespace llvm; + +// Print IR out before/after specified passes. +static cl::list + PrintBefore("print-before", + llvm::cl::desc("Print IR before specified passes"), + cl::CommaSeparated, cl::Hidden); + +static cl::list + PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), + cl::CommaSeparated, cl::Hidden); + +static cl::opt PrintBeforeAll("print-before-all", + llvm::cl::desc("Print IR before each pass"), + cl::init(false), cl::Hidden); +static cl::opt PrintAfterAll("print-after-all", + llvm::cl::desc("Print IR after each pass"), + cl::init(false), cl::Hidden); + +static cl::opt + PrintModuleScope("print-module-scope", + cl::desc("When printing IR for print-[before|after]{-all} " + "always print a module IR"), + cl::init(false), cl::Hidden); + +static cl::list + PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), + cl::desc("Only print IR for functions whose name " + "match this for all print-[before|after][-all] " + "options"), + cl::CommaSeparated, cl::Hidden); + +/// This is a helper to determine whether to print IR before or +/// after a pass. + +bool llvm::shouldPrintBeforeSomePass() { + return PrintBeforeAll || !PrintBefore.empty(); +} + +bool llvm::shouldPrintAfterSomePass() { + return PrintAfterAll || !PrintAfter.empty(); +} + +static bool shouldPrintBeforeOrAfterPass(StringRef PassID, + ArrayRef PassesToPrint) { + for (auto &Pass : PassesToPrint) { + if (Pass == PassID) + return true; + } + return false; +} + +bool llvm::shouldPrintBeforeAll() { return PrintBeforeAll; } + +bool llvm::shouldPrintAfterAll() { return PrintAfterAll; } + +bool llvm::shouldPrintBeforePass(StringRef PassID) { + return PrintBeforeAll || shouldPrintBeforeOrAfterPass(PassID, PrintBefore); +} + +bool llvm::shouldPrintAfterPass(StringRef PassID) { + return PrintAfterAll || shouldPrintBeforeOrAfterPass(PassID, PrintAfter); +} + +std::vector llvm::printBeforePasses() { + return std::vector(PrintBefore); +} + +std::vector llvm::printAfterPasses() { + return std::vector(PrintAfter); +} + +bool llvm::forcePrintModuleIR() { return PrintModuleScope; } + +bool llvm::isFunctionInPrintList(StringRef FunctionName) { + static std::unordered_set PrintFuncNames(PrintFuncsList.begin(), + PrintFuncsList.end()); + return PrintFuncNames.empty() || + PrintFuncNames.count(std::string(FunctionName)); +} diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -70,10 +70,12 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/SafepointIRVerifier.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" @@ -415,6 +417,16 @@ AnalysisKey NoOpFunctionAnalysis::Key; AnalysisKey NoOpLoopAnalysis::Key; +/// Whether or not we should populate a PassInstrumentationCallbacks's class to +/// pass name map. +/// +/// This is for optimization purposes so we don't populate it if we never use +/// it. This should be updated if new pass instrumentation wants to use the map. +/// We currently only use this for --print-before/after. +bool shouldPopulateClassToPassNames() { + return !printBeforePasses().empty() || !printAfterPasses().empty(); +} + } // namespace PassBuilder::PassBuilder(bool DebugLogging, TargetMachine *TM, @@ -423,6 +435,33 @@ : DebugLogging(DebugLogging), TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) { if (TM) TM->registerPassBuilderCallbacks(*this, DebugLogging); + if (PIC && shouldPopulateClassToPassNames()) { +#define MODULE_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define LOOP_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define LOOP_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define CGSCC_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#include "PassRegistry.def" + for (const auto &P : printBeforePasses()) { + if (!PIC->hasPassName(P)) + report_fatal_error("unrecognized pass name: " + P); + } + for (const auto &P : printAfterPasses()) { + if (!PIC->hasPassName(P)) + report_fatal_error("unrecognized pass name: " + P); + } + } } void PassBuilder::invokePeepholeEPCallbacks( diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -15,13 +15,14 @@ #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/ADT/Any.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/Function.h" -#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -94,7 +95,7 @@ if (any_isa(IR)) { const Function *F = any_cast(IR); - if (!Force && !llvm::isFunctionInPrintList(F->getName())) + if (!Force && !isFunctionInPrintList(F->getName())) return None; const Module *M = F->getParent(); @@ -136,7 +137,7 @@ return; } - if (!llvm::isFunctionInPrintList(F->getName())) + if (!isFunctionInPrintList(F->getName())) return; OS << Banner << Extra << "\n" << static_cast(*F); } @@ -149,7 +150,7 @@ return; } - if (llvm::isFunctionInPrintList("*") || llvm::forcePrintModuleIR()) { + if (isFunctionInPrintList("*") || forcePrintModuleIR()) { OS << Banner << Extra << "\n"; M->print(OS, nullptr, ShouldPreserveUseListOrder); } else { @@ -169,7 +170,7 @@ bool BannerPrinted = false; for (const LazyCallGraph::Node &N : *C) { const Function &F = N.getFunction(); - if (!F.isDeclaration() && llvm::isFunctionInPrintList(F.getName())) { + if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { if (!BannerPrinted) { OS << Banner << Extra << "\n"; BannerPrinted = true; @@ -187,9 +188,9 @@ } const Function *F = L->getHeader()->getParent(); - if (!llvm::isFunctionInPrintList(F->getName())) + if (!isFunctionInPrintList(F->getName())) return; - llvm::printLoop(const_cast(*L), OS, std::string(Banner)); + printLoop(const_cast(*L), OS, std::string(Banner)); } /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into @@ -250,7 +251,7 @@ template bool ChangeReporter::isInterestingFunction(const Function &F) { - return llvm::isFunctionInPrintList(F.getName()); + return isFunctionInPrintList(F.getName()); } template @@ -430,7 +431,7 @@ Out << "*** IR Dump Before" << Banner.substr(17); // 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()) + if (Name.substr(0, 6) != " (scc:" && !forcePrintModuleIR()) Out << Name; StringRef BeforeRef = Before; @@ -441,7 +442,7 @@ // 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()) + if (Name.substr(0, 6) != " (scc:" && !forcePrintModuleIR()) Out << Name; Out << After.substr(Banner.size()); @@ -480,14 +481,14 @@ // Note: here we rely on a fact that we do not change modules while // traversing the pipeline, so the latest captured module is good // for all print operations that has not happen yet. - if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID)) + if (StoreModuleDesc && shouldPrintAfterPass(PassID)) pushModuleDesc(PassID, IR); - if (!llvm::shouldPrintBeforePass(PassID)) + if (!shouldPrintBeforePass(PassID)) return; SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID); - unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR()); + unwrapAndPrint(dbgs(), IR, Banner, forcePrintModuleIR()); return; } @@ -495,18 +496,19 @@ if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) return; - if (!llvm::shouldPrintAfterPass(PassID)) + if (!shouldPrintAfterPass(PassID)) return; if (StoreModuleDesc) popModuleDesc(PassID); SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); - unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR()); + unwrapAndPrint(dbgs(), IR, Banner, forcePrintModuleIR()); } void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) { - if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID)) + StringRef PassName = PIC->getPassNameForClassName(PassID); + if (!StoreModuleDesc || !shouldPrintAfterPass(PassName)) return; if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) @@ -526,16 +528,42 @@ printIR(dbgs(), M, Banner, Extra); } +bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) { + if (shouldPrintBeforeAll()) + return true; + + StringRef PassName = PIC->getPassNameForClassName(PassID); + for (const auto &P : printBeforePasses()) { + if (PassName == P) + return true; + } + return false; +} + +bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) { + if (shouldPrintAfterAll()) + return true; + + StringRef PassName = PIC->getPassNameForClassName(PassID); + for (const auto &P : printAfterPasses()) { + if (PassName == P) + return true; + } + return false; +} + void PrintIRInstrumentation::registerCallbacks( PassInstrumentationCallbacks &PIC) { + this->PIC = &PIC; + // BeforePass callback is not just for printing, it also saves a Module // for later use in AfterPassInvalidated. - StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass(); - if (llvm::shouldPrintBeforePass() || StoreModuleDesc) + StoreModuleDesc = forcePrintModuleIR() && shouldPrintAfterSomePass(); + if (shouldPrintBeforeSomePass() || StoreModuleDesc) PIC.registerBeforeNonSkippedPassCallback( [this](StringRef P, Any IR) { this->printBeforePass(P, IR); }); - if (llvm::shouldPrintAfterPass()) { + if (shouldPrintAfterSomePass()) { PIC.registerAfterPassCallback( [this](StringRef P, Any IR, const PreservedAnalyses &) { this->printAfterPass(P, IR); diff --git a/llvm/test/CodeGen/Generic/print-after.ll b/llvm/test/CodeGen/Generic/print-after.ll deleted file mode 100644 --- a/llvm/test/CodeGen/Generic/print-after.ll +++ /dev/null @@ -1,6 +0,0 @@ -; RUN: llc --help-hidden 2>&1 | FileCheck %s - -; CHECK: -print-after -; CHECK-NOT: -print-after-all -; CHECK: =simple-register-coalescing -; CHECK: -print-after-all diff --git a/llvm/test/Other/loop-pass-printer.ll b/llvm/test/Other/loop-pass-printer.ll --- a/llvm/test/Other/loop-pass-printer.ll +++ b/llvm/test/Other/loop-pass-printer.ll @@ -1,23 +1,23 @@ ; This test checks -print-after/before on loop passes ; Besides of the loop itself it should be dumping loop pre-header and exits. ; -; RUN: opt -enable-new-pm=0 < %s 2>&1 -disable-output \ +; RUN: opt < %s 2>&1 -disable-output \ ; RUN: -loop-deletion -print-before=loop-deletion \ ; RUN: | FileCheck %s -check-prefix=DEL ; RUN: opt < %s 2>&1 -disable-output \ -; RUN: -passes='loop(loop-deletion)' -print-before-all \ +; RUN: -passes='loop(loop-deletion)' -print-before=loop-deletion \ ; RUN: | FileCheck %s -check-prefix=DEL ; RUN: opt -enable-new-pm=0 < %s 2>&1 -disable-output \ ; RUN: -loop-unroll -print-after=loop-unroll -filter-print-funcs=bar \ ; RUN: | FileCheck %s -check-prefix=BAR -check-prefix=BAR-OLD ; RUN: opt < %s 2>&1 -disable-output \ -; RUN: -passes='require,loop(loop-unroll-full)' -print-after-all -filter-print-funcs=bar \ +; RUN: -passes='require,loop(loop-unroll-full)' -print-after=loop-unroll-full -filter-print-funcs=bar \ ; RUN: | FileCheck %s -check-prefix=BAR ; RUN: opt -enable-new-pm=0 < %s 2>&1 -disable-output \ ; RUN: -loop-unroll -print-after=loop-unroll -filter-print-funcs=foo -print-module-scope \ ; RUN: | FileCheck %s -check-prefix=FOO-MODULE -check-prefix=FOO-MODULE-OLD ; RUN: opt < %s 2>&1 -disable-output \ -; RUN: -passes='require,loop(loop-unroll-full)' -print-after-all -filter-print-funcs=foo -print-module-scope \ +; RUN: -passes='require,loop(loop-unroll-full)' -print-after=loop-unroll-full -filter-print-funcs=foo -print-module-scope \ ; RUN: | FileCheck %s -check-prefix=FOO-MODULE ; DEL: IR Dump Before {{Delete dead loops|LoopDeletionPass}} diff --git a/llvm/test/Other/print-before-after.ll b/llvm/test/Other/print-before-after.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Other/print-before-after.ll @@ -0,0 +1,33 @@ +; RUN: not --crash opt < %s -disable-output -passes='no-op-module' -print-before=bleh 2>&1 | FileCheck %s --check-prefix=NONE --allow-empty +; RUN: not --crash opt < %s -disable-output -passes='no-op-module' -print-after=bleh 2>&1 | FileCheck %s --check-prefix=NONE --allow-empty +; RUN: opt < %s -disable-output -passes='no-op-module' -print-before=no-op-function 2>&1 | FileCheck %s --check-prefix=NONE --allow-empty +; RUN: opt < %s -disable-output -passes='no-op-module' -print-after=no-op-function 2>&1 | FileCheck %s --check-prefix=NONE --allow-empty +; RUN: opt < %s -disable-output -passes='no-op-module,no-op-function' -print-before=no-op-module 2>&1 | FileCheck %s --check-prefix=ONCE +; RUN: opt < %s -disable-output -passes='no-op-module,no-op-function' -print-after=no-op-module 2>&1 | FileCheck %s --check-prefix=ONCE +; RUN: opt < %s -disable-output -passes='no-op-function' -print-before=no-op-function 2>&1 | FileCheck %s --check-prefix=ONCE +; RUN: opt < %s -disable-output -passes='no-op-function' -print-after=no-op-function 2>&1 | FileCheck %s --check-prefix=ONCE +; RUN: opt < %s -disable-output -passes='no-op-module,no-op-function' -print-before=no-op-function --print-module-scope 2>&1 | FileCheck %s --check-prefix=TWICE +; RUN: opt < %s -disable-output -passes='no-op-module,no-op-function' -print-after=no-op-function --print-module-scope 2>&1 | FileCheck %s --check-prefix=TWICE + +; NONE-NOT: @foo +; NONE-NOT: @bar + +; ONCE: @foo +; ONCE: @bar +; ONCE-NOT: @foo +; ONCE-NOT: @bar + +; TWICE: @foo +; TWICE: @bar +; TWICE: @foo +; TWICE: @bar +; TWICE-NOT: @foo +; TWICE-NOT: @bar + +define void @foo() { + ret void +} + +define void @bar() { + ret void +} diff --git a/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/IR/BUILD.gn @@ -59,6 +59,7 @@ "PassManager.cpp", "PassRegistry.cpp", "PassTimingInfo.cpp", + "PrintPasses.cpp", "ProfileSummary.cpp", "SafepointIRVerifier.cpp", "Statepoint.cpp",