Index: llvm/lib/Passes/StandardInstrumentations.cpp =================================================================== --- llvm/lib/Passes/StandardInstrumentations.cpp +++ llvm/lib/Passes/StandardInstrumentations.cpp @@ -68,7 +68,8 @@ // 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. +// reported as filtered out. The -also-print-before option will print +// the IR as it was before each pass that changed it. static cl::opt PrintChanged("print-changed", cl::desc("Print changed IRs"), cl::init(false), cl::Hidden); @@ -80,6 +81,13 @@ 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 + AlsoPrintBefore("also-print-before", + cl::desc("Print before passes that change them"), + cl::init(false), cl::Hidden); namespace { @@ -394,6 +402,19 @@ StringRef AfterRef = After; StringRef Banner = AfterRef.take_until([](char C) -> bool { return C == '\n'; }); + + // Report the IR before the changes when requested. + if (AlsoPrintBefore) { + 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()) + Out << Name; + + StringRef BeforeRef = Before; + Out << BeforeRef.substr(Banner.size()); + } + Out << Banner; // LazyCallGraph::SCC already has "(scc:..." in banner so only add Index: llvm/test/Other/change-printer.ll =================================================================== --- llvm/test/Other/change-printer.ll +++ llvm/test/Other/change-printer.ll @@ -34,6 +34,15 @@ ; others (including g) are filtered out. Note that the second time ; instsimplify is run on f, it does not change the IR ; RUN: opt -S -print-changed -passes="instsimplify,instsimplify" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-MULT-PASSES-FILTER-FUNC +; +; Simple -also-print-before functionality check. +; RUN: opt -S -print-changed -also-print-before -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-SIMPLE-BEFORE +; +; Check that -also-print-before obeys the function filtering +; RUN: opt -S -print-changed -also-print-before -passes=instsimplify -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-FUNC-FILTER-BEFORE +; +; Check that the reporting of IRs with -also-print-before respects -print-module-scope +; RUN: opt -S -print-changed -also-print-before -passes=instsimplify -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-PRINT-MOD-SCOPE-BEFORE define i32 @g() { entry: @@ -126,3 +135,40 @@ ; CHECK-MULT-PASSES-FILTER-FUNC: *** IR Dump After InstSimplifyPass *** (function: f) ; CHECK-MULT-PASSES-FILTER-FUNC-NEXT: define i32 @f() ; CHECK-MULT-PASSES-FILTER-FUNC: *** IR Dump After InstSimplifyPass (function: f) omitted because no change *** + +; CHECK-SIMPLE-BEFORE: *** IR Dump At Start: *** +; CHECK-SIMPLE-BEFORE-NEXT: ; ModuleID = {{.+}} +; CHECK-SIMPLE-BEFORE: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK-SIMPLE-BEFORE: *** IR Dump Before InstSimplifyPass *** (function: g) +; CHECK-SIMPLE-BEFORE-NEXT: define i32 @g() +; CHECK-SIMPLE-BEFORE: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-SIMPLE-BEFORE-NEXT: define i32 @g() +; CHECK-SIMPLE-BEFORE: *** IR Pass PassManager{{.*}} (function: g) ignored *** +; CHECK-SIMPLE-BEFORE: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-SIMPLE-BEFORE-NEXT: define i32 @f() +; CHECK-SIMPLE-BEFORE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-SIMPLE-BEFORE-NEXT: define i32 @f() +; CHECK-SIMPLE-BEFORE: *** IR Pass PassManager{{.*}} (function: f) ignored *** +; CHECK-SIMPLE-BEFORE: *** IR Pass ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> (module) ignored *** +; CHECK-SIMPLE-BEFORE: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK-SIMPLE-BEFORE: *** IR Dump After PrintModulePass (module) omitted because no change *** +; CHECK-SIMPLE-BEFORE-NOT: *** IR + +; CHECK-FUNC-FILTER-BEFORE: *** IR Dump At Start: *** +; CHECK-FUNC-FILTER-BEFORE-NEXT: ; ModuleID = {{.+}} +; CHECK-FUNC-FILTER-BEFORE: *** IR Dump After InstSimplifyPass (function: g) filtered out *** +; CHECK-FUNC-FILTER-BEFORE: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-FUNC-FILTER-BEFORE-NEXT: define i32 @f() +; CHECK-FUNC-FILTER-BEFORE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-FUNC-FILTER-BEFORE-NEXT: define i32 @f() + +; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump At Start: *** +; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump Before InstSimplifyPass *** (function: g) +; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}}