diff --git a/llvm/include/llvm/IR/PrintPasses.h b/llvm/include/llvm/IR/PrintPasses.h --- a/llvm/include/llvm/IR/PrintPasses.h +++ b/llvm/include/llvm/IR/PrintPasses.h @@ -51,6 +51,9 @@ // Returns true if we should always print the entire module. bool forcePrintModuleIR(); +// Return true if -filter-passes is empty or contains the pass name. +bool isPassInPrintList(StringRef PassName); + // Returns true if we should print the function. bool isFunctionInPrintList(StringRef FunctionName); diff --git a/llvm/lib/CodeGen/MachineFunctionPass.cpp b/llvm/lib/CodeGen/MachineFunctionPass.cpp --- a/llvm/lib/CodeGen/MachineFunctionPass.cpp +++ b/llvm/lib/CodeGen/MachineFunctionPass.cpp @@ -73,10 +73,14 @@ // For --print-changed, if the function name is a candidate, save the // serialized MF to be compared later. - // TODO Implement --filter-passes. SmallString<0> BeforeStr, AfterStr; - bool ShouldPrintChanged = PrintChanged != ChangePrinter::None && - isFunctionInPrintList(MF.getName()); + StringRef PassID; + if (const PassInfo *PI = Pass::lookupPassInfo(getPassID())) + PassID = PI->getPassArgument(); + const bool IsInterestingPass = isPassInPrintList(PassID); + const bool ShouldPrintChanged = PrintChanged != ChangePrinter::None && + IsInterestingPass && + isFunctionInPrintList(MF.getName()); if (ShouldPrintChanged) { raw_svector_ostream OS(BeforeStr); MF.print(OS); @@ -112,15 +116,14 @@ // For --print-changed, print if the serialized MF has changed. Modes other // than quiet/verbose are unimplemented and treated the same as 'quiet'. - if (ShouldPrintChanged) { - raw_svector_ostream OS(AfterStr); - MF.print(OS); - if (BeforeStr != AfterStr) { - StringRef Arg; - if (const PassInfo *PI = Pass::lookupPassInfo(getPassID())) - Arg = PI->getPassArgument(); - errs() << ("*** IR Dump After " + getPassName() + " (" + Arg + ") on " + - MF.getName() + " ***\n"); + if (ShouldPrintChanged || !IsInterestingPass) { + if (ShouldPrintChanged) { + raw_svector_ostream OS(AfterStr); + MF.print(OS); + } + if (IsInterestingPass && BeforeStr != AfterStr) { + errs() << ("*** IR Dump After " + getPassName() + " (" + PassID + + ") on " + MF.getName() + " ***\n"); switch (PrintChanged) { case ChangePrinter::None: llvm_unreachable(""); @@ -148,8 +151,12 @@ ChangePrinter::DiffVerbose, ChangePrinter::ColourDiffVerbose}, PrintChanged.getValue())) { - errs() << ("*** IR Dump After " + getPassName() + " on " + MF.getName() + - " omitted because no change ***\n"); + const char *Reason = + IsInterestingPass ? " omitted because no change" : " filtered out"; + errs() << "*** IR Dump After " << getPassName(); + if (!PassID.empty()) + errs() << " (" << PassID << ")"; + errs() << " on " << MF.getName() + Reason + " ***\n"; } } return RV; diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp --- a/llvm/lib/IR/PrintPasses.cpp +++ b/llvm/lib/IR/PrintPasses.cpp @@ -87,6 +87,14 @@ "always print a module IR"), cl::init(false), cl::Hidden); +// See the description for -print-changed. This option has no effect without +// -print-changed. +static cl::list FilterPasses( + "filter-passes", cl::value_desc("pass names"), + cl::desc("Only consider IR changes for passes whose names " + "match the specified value. No-op without -print-changed"), + cl::CommaSeparated, cl::Hidden); + static cl::list PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), cl::desc("Only print IR for functions whose name " @@ -132,6 +140,12 @@ bool llvm::forcePrintModuleIR() { return PrintModuleScope; } +bool llvm::isPassInPrintList(StringRef PassName) { + static std::unordered_set Set(FilterPasses.begin(), + FilterPasses.end()); + return Set.empty() || Set.count(std::string(PassName)); +} + bool llvm::isFunctionInPrintList(StringRef FunctionName) { static std::unordered_set PrintFuncNames(PrintFuncsList.begin(), PrintFuncsList.end()); 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 @@ -56,14 +56,6 @@ // An option that supports the -print-changed option. See // the description for -print-changed for an explanation of the use // of this option. Note that this option has no effect without -print-changed. -static cl::list - PrintPassesList("filter-passes", cl::value_desc("pass names"), - cl::desc("Only consider IR changes for passes whose names " - "match for the print-changed option"), - cl::CommaSeparated, cl::Hidden); -// An option that supports the -print-changed option. See -// the description for -print-changed for an explanation of the use -// of this option. Note that this option has no effect without -print-changed. static cl::opt PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), @@ -321,19 +313,10 @@ return isFunctionInPrintList(F.getName()); } -bool isInterestingPass(StringRef PassID) { - if (isIgnored(PassID)) - return false; - - static std::unordered_set PrintPassNames(PrintPassesList.begin(), - PrintPassesList.end()); - return PrintPassNames.empty() || PrintPassNames.count(PassID.str()); -} - // Return true when this is a pass on IR for which printing // of changes is desired. bool isInteresting(Any IR, StringRef PassID) { - if (!isInterestingPass(PassID)) + if (isIgnored(PassID) || !isPassInPrintList(PassID)) return false; if (any_isa(IR)) return isInterestingFunction(*any_cast(IR)); diff --git a/llvm/test/Other/print-changed-machine.ll b/llvm/test/Other/print-changed-machine.ll --- a/llvm/test/Other/print-changed-machine.ll +++ b/llvm/test/Other/print-changed-machine.ll @@ -7,8 +7,8 @@ ; VERBOSE-NEXT: Function Live Ins: $w0 ; VERBOSE-EMPTY: ; VERBOSE-NEXT: bb.1.entry: -; VERBOSE: *** IR Dump After Analysis for ComputingKnownBits on foo omitted because no change *** -; VERBOSE-NEXT: *** IR Dump After AArch64O0PreLegalizerCombiner on foo omitted because no change *** +; VERBOSE: *** IR Dump After Analysis for ComputingKnownBits (gisel-known-bits) on foo omitted because no change *** +; VERBOSE-NEXT: *** IR Dump After AArch64O0PreLegalizerCombiner (aarch64-O0-prelegalizer-combiner) on foo omitted because no change *** ; VERBOSE: *** IR Dump After Legalizer (legalizer) on foo *** ; VERBOSE-NEXT: # Machine code for function foo: IsSSA, TracksLiveness, Legalized ; VERBOSE-NEXT: Function Live Ins: $w0 @@ -24,6 +24,19 @@ ; QUIET-NOT: *** ; QUIET: *** IR Dump After Legalizer (legalizer) on foo *** +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed -filter-passes=irtranslator,legalizer %s 2>&1 | \ +; RUN: FileCheck %s --check-prefixes=VERBOSE-FILTER +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=quiet -filter-passes=irtranslator %s 2>&1 | \ +; RUN: FileCheck %s --check-prefixes=QUIET-FILTER --implicit-check-not='IR Dump' + +; VERBOSE-FILTER: *** IR Dump After IRTranslator (irtranslator) on foo *** +; VERBOSE-FILTER: *** IR Dump After AArch64O0PreLegalizerCombiner (aarch64-O0-prelegalizer-combiner) on foo filtered out *** +; VERBOSE-FILTER: *** IR Dump After Legalizer (legalizer) on foo *** +; VERBOSE-FILTER-NOT: *** IR Dump After {{.*}} () on + +; QUIET-FILTER: *** IR Dump After IRTranslator (irtranslator) on foo *** +; QUIET-FILTER: *** IR Dump After IRTranslator (irtranslator) on bar *** + ;; dot-cfg/dot-cfg-quiet are unimplemented. Currently they behave like 'quiet'. ; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=dot-cfg %s 2>&1 | FileCheck %s --check-prefix=QUIET