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 @@ -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 -print-before-changed 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 + PrintChangedBefore("print-before-changed", + cl::desc("Print before passes that change them"), + cl::init(false), cl::Hidden); namespace { @@ -392,6 +400,19 @@ StringRef AfterRef = After; StringRef Banner = AfterRef.take_until([](char C) -> bool { return C == '\n'; }); + + // Report the IR before the changes when requested. + if (PrintChangedBefore) { + 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 diff --git a/llvm/test/Other/change-printer.ll b/llvm/test/Other/change-printer.ll --- a/llvm/test/Other/change-printer.ll +++ b/llvm/test/Other/change-printer.ll @@ -34,6 +34,16 @@ ; 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 print-before-changed functionality check. +; RUN: opt -S -print-changed -print-before-changed -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-SIMPLE-BEFORE +; +; Check print-before-changed obeys the function filtering +; RUN: opt -S -print-changed -print-before-changed -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 -print-before-changed respects -print-module-scope +; RUN: opt -S -print-changed -print-before-changed -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 +136,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 = {{.+}}