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 @@ -10,10 +10,25 @@ #define LLVM_IR_PRINTPASSES_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" #include namespace llvm { +enum class ChangePrinter { + None, + Verbose, + Quiet, + DiffVerbose, + DiffQuiet, + ColourDiffVerbose, + ColourDiffQuiet, + DotCfgVerbose, + DotCfgQuiet +}; + +extern cl::opt PrintChanged; + // Returns true if printing before/after some pass is enabled, whether all // passes or a specific pass. bool shouldPrintBeforeSomePass(); 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 @@ -26,6 +26,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/PrintPasses.h" using namespace llvm; using namespace ore; @@ -70,6 +71,16 @@ if (ShouldEmitSizeRemarks) CountBefore = MF.getInstructionCount(); + // For --print-changed, if the function name is a candidate, save the + // serialized MF to be compared later. + SmallString<0> BeforeStr, AfterStr; + bool ShouldPrintChanged = PrintChanged != ChangePrinter::None && + isFunctionInPrintList(MF.getName()); + if (ShouldPrintChanged) { + raw_svector_ostream OS(BeforeStr); + MF.print(OS); + } + bool RV = runOnMachineFunction(MF); if (ShouldEmitSizeRemarks) { @@ -97,6 +108,23 @@ MFProps.set(SetProperties); MFProps.reset(ClearedProperties); + + // 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" + AfterStr); + } else if (PrintChanged == ChangePrinter::Verbose) { + errs() << ("*** IR Dump After " + getPassName() + " on " + MF.getName() + + " omitted because no change ***\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 @@ -29,6 +29,50 @@ llvm::cl::desc("Print IR after each pass"), cl::init(false), cl::Hidden); +// Print out the IR after passes, similar to -print-after-all except that it +// only prints the IR after passes that change the IR. Those passes that do not +// make changes to the IR are reported as not making any changes. In addition, +// the initial IR is also reported. Other hidden options affect the output from +// this option. -filter-passes will limit the output to the named passes that +// actually change the IR and other passes are reported as filtered out. The +// specified passes will either be reported as making no changes (with no IR +// reported) or the changed IR will be reported. Also, the -filter-print-funcs +// and -print-module-scope options will do similar filtering based on function +// name, reporting changed IRs as functions(or modules if -print-module-scope is +// specified) for a particular function or indicating that the IR has been +// filtered out. The extra options can be combined, allowing only changed IRs +// for certain passes on certain functions to be reported in different formats, +// with the rest being reported as filtered out. The -print-before-changed +// option will print the IR as it was before each pass that changed it. The +// optional value of quiet will only report when the IR changes, suppressing all +// other messages, including the initial IR. The values "diff" and "diff-quiet" +// will present the changes in a form similar to a patch, in either verbose or +// quiet mode, respectively. The lines that are removed and added are prefixed +// with '-' and '+', respectively. The -filter-print-funcs and -filter-passes +// can be used to filter the output. This reporter relies on the linux diff +// utility to do comparisons and insert the prefixes. For systems that do not +// have the necessary facilities, the error message will be shown in place of +// the expected output. +cl::opt llvm::PrintChanged( + "print-changed", cl::desc("Print changed IRs"), cl::Hidden, + cl::ValueOptional, cl::init(ChangePrinter::None), + cl::values( + clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"), + clEnumValN(ChangePrinter::DiffVerbose, "diff", + "Display patch-like changes"), + clEnumValN(ChangePrinter::DiffQuiet, "diff-quiet", + "Display patch-like changes in quiet mode"), + clEnumValN(ChangePrinter::ColourDiffVerbose, "cdiff", + "Display patch-like changes with color"), + clEnumValN(ChangePrinter::ColourDiffQuiet, "cdiff-quiet", + "Display patch-like changes in quiet mode with color"), + clEnumValN(ChangePrinter::DotCfgVerbose, "dot-cfg", + "Create a website with graphical changes"), + clEnumValN(ChangePrinter::DotCfgQuiet, "dot-cfg-quiet", + "Create a website with graphical changes in quiet mode"), + // Sentinel value for unspecified option. + clEnumValN(ChangePrinter::Verbose, "", ""))); + static cl::opt PrintModuleScope("print-module-scope", cl::desc("When printing IR for print-[before|after]{-all} " 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 @@ -53,64 +53,6 @@ #endif ); -// An option that prints out the IR after passes, similar to -// -print-after-all except that it only prints the IR after passes that -// change the IR. Those passes that do not make changes to the IR are -// reported as not making any changes. In addition, the initial IR is -// also reported. Other hidden options affect the output from this -// option. -filter-passes will limit the output to the named passes -// that actually change the IR and other passes are reported as filtered out. -// The specified passes will either be reported as making no changes (with -// no IR reported) or the changed IR will be reported. Also, the -// -filter-print-funcs and -print-module-scope options will do similar -// filtering based on function name, reporting changed IRs as functions(or -// modules if -print-module-scope is specified) for a particular function -// or indicating that the IR has been filtered out. The extra options -// can be combined, allowing only changed IRs for certain passes on certain -// functions to be reported in different formats, with the rest being -// reported as filtered out. The -print-before-changed option will print -// the IR as it was before each pass that changed it. The optional -// value of quiet will only report when the IR changes, suppressing -// all other messages, including the initial IR. The values "diff" and -// "diff-quiet" will present the changes in a form similar to a patch, in -// either verbose or quiet mode, respectively. The lines that are removed -// and added are prefixed with '-' and '+', respectively. The -// -filter-print-funcs and -filter-passes can be used to filter the output. -// This reporter relies on the linux diff utility to do comparisons and -// insert the prefixes. For systems that do not have the necessary -// facilities, the error message will be shown in place of the expected output. -// -enum class ChangePrinter { - None, - Verbose, - Quiet, - DiffVerbose, - DiffQuiet, - ColourDiffVerbose, - ColourDiffQuiet, - DotCfgVerbose, - DotCfgQuiet, -}; -static cl::opt PrintChanged( - "print-changed", cl::desc("Print changed IRs"), cl::Hidden, - cl::ValueOptional, cl::init(ChangePrinter::None), - cl::values( - clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"), - clEnumValN(ChangePrinter::DiffVerbose, "diff", - "Display patch-like changes"), - clEnumValN(ChangePrinter::DiffQuiet, "diff-quiet", - "Display patch-like changes in quiet mode"), - clEnumValN(ChangePrinter::ColourDiffVerbose, "cdiff", - "Display patch-like changes with color"), - clEnumValN(ChangePrinter::ColourDiffQuiet, "cdiff-quiet", - "Display patch-like changes in quiet mode with color"), - clEnumValN(ChangePrinter::DotCfgVerbose, "dot-cfg", - "Create a website with graphical changes"), - clEnumValN(ChangePrinter::DotCfgQuiet, "dot-cfg-quiet", - "Create a website with graphical changes in quiet mode"), - // Sentinel value for unspecified option. - clEnumValN(ChangePrinter::Verbose, "", ""))); - // 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. diff --git a/llvm/test/Other/print-changed-machine.ll b/llvm/test/Other/print-changed-machine.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Other/print-changed-machine.ll @@ -0,0 +1,44 @@ +; REQUIRES: aarch64-registered-target +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed %s 2>&1 | FileCheck %s --check-prefixes=VERBOSE,VERBOSE-BAR +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed -filter-print-funcs=foo %s 2>&1 | FileCheck %s --check-prefixes=VERBOSE,NO-BAR + +; VERBOSE: *** IR Dump After IRTranslator (irtranslator) on foo *** +; VERBOSE-NEXT: # Machine code for function foo: IsSSA, TracksLiveness{{$}} +; 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 Legalizer (legalizer) on foo *** +; VERBOSE-NEXT: # Machine code for function foo: IsSSA, TracksLiveness, Legalized +; VERBOSE-NEXT: Function Live Ins: $w0 +; VERBOSE-EMPTY: +; VERBOSE-NEXT: bb.1.entry: + +; VERBOSE-BAR: *** IR Dump After IRTranslator (irtranslator) on bar *** +; NO-BAR-NOT: on bar *** + +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=quiet %s 2>&1 | FileCheck %s --check-prefix=QUIET + +; QUIET: *** IR Dump After IRTranslator (irtranslator) on foo *** +; QUIET-NOT: *** +; QUIET: *** IR Dump After Legalizer (legalizer) on foo *** + +;; Other modes are unimplemented. Currently they behave like 'quiet'. +; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=diff %s 2>&1 | FileCheck %s --check-prefix=QUIET + +@var = global i32 0 + +define void @foo(i32 %a) { +entry: + %b = add i32 %a, 1 + store i32 %b, ptr @var + ret void +} + +define void @bar(i32 %a) { +entry: + %b = add i32 %a, 2 + store i32 %b, ptr @var + ret void +}