Index: llvm/lib/IR/LegacyPassManager.cpp =================================================================== --- llvm/lib/IR/LegacyPassManager.cpp +++ llvm/lib/IR/LegacyPassManager.cpp @@ -86,14 +86,14 @@ static cl::opt PrintModuleScope("print-module-scope", cl::desc("When printing IR for print-[before|after]{-all} " - "always print a module IR"), + "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] " - "options"), + "and change reporter options"), cl::CommaSeparated, cl::Hidden); /// This is a helper to determine whether to print IR before or Index: llvm/lib/Passes/StandardInstrumentations.cpp =================================================================== --- llvm/lib/Passes/StandardInstrumentations.cpp +++ llvm/lib/Passes/StandardInstrumentations.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" +#include #include using namespace llvm; @@ -43,6 +44,34 @@ cl::desc("Print all pass management debugging information. " "`-debug-pass-manager` must also be specified")); +// A hidden 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 exta 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. +static cl::opt PrintChanged("print-changed", + cl::desc("Print changed IRs"), + cl::init(false), cl::Hidden); +// A hidden 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); + namespace { /// Extracting Module out of \p IR unit. Also fills a textual description @@ -189,6 +218,262 @@ llvm_unreachable("Unknown wrapped IR type"); } +// Base class for classes that report changes to the IR. +// It presents an interface for such classes and provides callbacks +// on various events as the new pass manager transforms the IR. +// It also provides filtering of information based on hidden options +// specifying which functions are interesting. +// Callbacks are made for the following events/queries: +// 1. The initial IR processed. +// 2. To get the representation of the IR (of type \p T). +// 3. When a pass does not change the IR. +// 4. When a pass changes the IR (given both before and after representations +// of type \p T). +// 5. When an IR is invalidated. +// 6. When a pass is run on an IR that is not interesting (based on options). +// 7. When a pass is ignored (pass manager or adapter pass). +// 8. To compare two IR representations (of type \p T). +template class ChangePrinter { +public: + // Not virtual as classes are expected to be referenced as derived classes. + ~ChangePrinter() { + assert(BeforeStack.empty() && "Problem with Change Printer stack."); + } + + // Determine if this pass/IR is interesting and if so, save the IR + void saveIRBeforePass(Any IR, StringRef PassID) { + if (!isInteresting(IR, PassID)) + return; + // Is this the initial IR? + if (InitialIR) { + InitialIR = false; + HandleInitialIR(IR); + } + + // Save the IR representation on the stack. + BeforeStack.emplace_back(); + auto &Data = BeforeStack.back(); + GenerateIRRepresentation(IR, PassID, Data); + } + // Compare the IR from before the pass after the pass. + void handleIRAfterPass(Any IR, StringRef PassID) { + std::string Name; + + // unwrapModule has inconsistent handling of names for function IRs. + if (any_isa(IR)) { + const Function *F = any_cast(IR); + Name = formatv(" (function: {0})", F->getName()).str(); + } else { + if (auto UM = unwrapModule(IR)) + Name = UM->second; + } + if (Name == "") + Name = " (module)"; + + if (isIgnored(PassID)) { + HandleIgnored(PassID, Name); + return; + } + + if (!isInteresting(IR, PassID)) { + HandleFiltered(PassID, Name); + return; + } + + assert(!BeforeStack.empty() && "Unexpected empty stack for printing."); + + // Get the before rep from the stack + T &Before = BeforeStack.back(); + // Create the after rep + T After; + GenerateIRRepresentation(IR, PassID, After); + + // was there a change in IR? + if (Same(Before, After)) + OmitAfter(PassID, Name); + else + HandleAfter(Name, PassID, Before, After, IR); + + // Now remove the before IR as it is no longer needed. + BeforeStack.pop_back(); + } + // Handle the situation where a pass is invalidated. + void handleInvalidatedPass(StringRef PassID) { + assert(!BeforeStack.empty() && "Unexpected empty stack for printing."); + HandleInvalidated(PassID); + BeforeStack.pop_back(); + } + +protected: + ChangePrinter(std::function F1, + std::function F2, + std::function F3, + std::function + F4, + std::function F5, + std::function F6, + std::function F7, + std::function F8) + : HandleInitialIR(F1), GenerateIRRepresentation(F2), OmitAfter(F3), + HandleAfter(F4), HandleInvalidated(F5), HandleFiltered(F6), + HandleIgnored(F7), Same(F8), InitialIR(true) {} + +private: + // Return true when this is a pass on IR for which printing + // of changes is desired. + static bool isInteresting(Any IR, StringRef PassID) { + if (!isInterestingPass(PassID)) + return false; + if (any_isa(IR)) + return isInterestingFunction(*any_cast(IR)); + return true; + } + + // Return true when this is a pass for which printing of changes is desired. + static bool isIgnored(StringRef PassID) { + return PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"); + } + + // Return true when this is a defined function for which printing + // of changes is desired. + static bool isInterestingFunction(const Function &F) { + return !F.isDeclaration() && llvm::isFunctionInPrintList(F.getName()); + } + + // Return true when this is a pass for which printing of changes is desired. + static 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()); + } + + // callback on the first IR processed + std::function HandleInitialIR; + // callback before and after a pass to get the representation of the IR + std::function + GenerateIRRepresentation; + // callback when the pass is not iteresting + std::function OmitAfter; + // callback when interesting IR has changed + std::function + HandleAfter; + // callback when an interesting pass is invalidated + std::function HandleInvalidated; + // callback when the IR or pass is not interesting + std::function HandleFiltered; + // callback when an ignored pass is encountered + std::function HandleIgnored; + // callback to compare the before and after representations of the IR + std::function Same; + + // stack of IRs before passes + std::vector BeforeStack; + // Is this the first IR seen? + bool InitialIR; +}; + +void HandleInitialIR(Any IR, raw_ostream &Out) { + StringRef Banner("*** IR Dump At Start: ***"); + unwrapAndPrint(Out, IR, Banner, true); +} + +void GenerateOutput(Any IR, StringRef PassID, std::string &Output) { + raw_string_ostream OS(Output); + // use the after banner for all cases so it will match + SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); + unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR()); + OS.str(); +} + +void OmitAfter(StringRef PassID, std::string &Name, raw_ostream &Out) { + Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n", + PassID, Name); +} + +void handleAfter(std::string &Name, StringRef After, raw_ostream &Out) { + assert(After.find("*** IR Dump") == 0 && "Unexpected banner format."); + StringRef Banner = After.take_until([](char C) -> bool { return C == '\n'; }); + Out << Banner; + + // LazyCallGraph::SCC already has "(scc:..." in banner so only add + // in the name if it isn't already there. + if (Name.substr(0, 6).compare(" (scc:") != 0 && !llvm::forcePrintModuleIR()) + Out << Name; + + Out << After.substr(Banner.size()); +} + +void HandleInvalidated(StringRef PassID, raw_ostream &Out) { + Out << formatv("*** IR Pass {0} invalidated ***\n", PassID); +} + +void HandleFiltered(StringRef PassID, std::string &Name, raw_ostream &Out) { + SmallString<20> Banner = + formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name); + Out << Banner; +} + +void HandleIgnored(StringRef PassID, std::string &Name, raw_ostream &Out) { + Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name); +} + +bool Same(std::string &S1, std::string &S2) { return S1.compare(S2) == 0; } + +// A change printer based on the string representation of the IR as created +// by unwrapAndPrint. The string representation is stored in a std::string +// to preserve it as the IR changes in each pass. Note that the banner is +// included in this representation but it is massaged before reporting. +class IRChangePrinter : public ChangePrinter { +public: + IRChangePrinter(raw_ostream &OS) + : ChangePrinter( + [this](Any IR) -> void { ::HandleInitialIR(IR, Out); }, + ::GenerateOutput, + [this](StringRef PassID, std::string &Name) -> void { + ::OmitAfter(PassID, Name, Out); + }, + [this](std::string &Name, StringRef PassID, std::string &Before, + std::string &After, + Any IR) -> void { ::handleAfter(Name, After, Out); }, + [this](StringRef PassID) -> void { + ::HandleInvalidated(PassID, Out); + }, + [this](StringRef PassID, std::string &Name) -> void { + ::HandleFiltered(PassID, Name, Out); + }, + [this](StringRef PassID, std::string &Name) -> void { + ::HandleIgnored(PassID, Name, Out); + }, + ::Same), + Out(OS) {} + +protected: + raw_ostream &Out; +}; + +void registerChangePrinters(PassInstrumentationCallbacks &PIC) { + if (PrintChanged) { + static IRChangePrinter ICP(dbgs()); + PIC.registerBeforePassCallback([](StringRef P, Any IR) { + ICP.saveIRBeforePass(IR, P); + return true; + }); + PIC.registerAfterPassCallback( + [](StringRef P, Any IR, const PreservedAnalyses &) { + ICP.handleIRAfterPass(IR, P); + }); + PIC.registerAfterPassInvalidatedCallback( + [](StringRef P, const PreservedAnalyses &) { + ICP.handleInvalidatedPass(P); + }); + } +} + } // namespace PrintIRInstrumentation::~PrintIRInstrumentation() { @@ -344,4 +629,5 @@ PrintPass.registerCallbacks(PIC); TimePasses.registerCallbacks(PIC); OptNone.registerCallbacks(PIC); + registerChangePrinters(PIC); } Index: llvm/test/Other/change-printer.ll =================================================================== --- /dev/null +++ llvm/test/Other/change-printer.ll @@ -0,0 +1,281 @@ +; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; ! This test may need altering if simplify-cfg is changed. It reports +; ! the passes that make changes to the IR so if simplify-cfg is changed +; ! such that it no longer makes changes to this source, then the test +; ! will need to be changed. simplify-cfg was chosen as it was guessed +; ! that it would likely continue to change this input. +; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; +; Simple functionality check. +; +; RUN: opt -S -print-changed -passes=simplify-cfg 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK0 +; +; Check that only the passes that change the IR are printed and that the +; others (including g) are filtered out. Note that only the headings +; are checked. +; N.B. As passes change functionality, this test may fail because it reports +; whether a pass made a change or not, which can change as pass functionality +; changes. +; +; RUN: opt -S -print-changed -passes=simplify-cfg -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK1 +; +; Check that the reporting of IRs respects -print-module-scope +; RUN: opt -S -print-changed -passes=simplify-cfg -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK2 +; +; Check that the reporting of IRs respects -print-module-scope +; RUN: opt -S -print-changed -passes=simplify-cfg -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK3 +; +; Check that reporting of multiple functions happens +; RUN: opt -S -print-changed -passes=simplify-cfg -filter-print-funcs="f,g" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK4 +; +; Check that the reporting of IRs respects -filter-passes +; RUN: opt -S -print-changed -passes="simplify-cfg,instcombine" -filter-passes="InstCombinePass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK5 +; +; Check that the reporting of IRs respects -filter-passes with multiple passes +; RUN: opt -S -print-changed -passes="simplify-cfg,instcombine" -filter-passes="InstCombinePass,SimplifyCFGPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK6 +; +; Check that the reporting of IRs respects both -filter-passes and -filter-print-funcs +; RUN: opt -S -print-changed -passes="simplify-cfg,instcombine" -filter-passes="InstCombinePass,SimplifyCFGPass" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK7 +; +; Check that the reporting of IRs respects -filter-passes, -filter-print-funcs and -print-module-scope +; RUN: opt -S -print-changed -passes="simplify-cfg,instcombine" -filter-passes="InstCombinePass,SimplifyCFGPass" -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK8 +; +; Simple checks of -print-changed functionality using the approximate +; equivalent of the following C file. +; +; int g(int upper) { +; int i; +; for (i = 0; i < upper; ++i) +; i = i + 1; +; return i; +; } +; int f(int upper) { +; int i; +; for (i = 0; i < upper; ++i) +; i = i + 1; +; return i; +; } +; int main() { +; int i = f(10) + g(5); +; return i; +; } +; + +define dso_local signext i32 @g(i32 signext %upper) { +entry: + %upper.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 %upper, i32* %upper.addr, align 4 + %0 = bitcast i32* %i to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: + %1 = load i32, i32* %i, align 4 + %2 = load i32, i32* %upper.addr, align 4 + %cmp = icmp slt i32 %1, %2 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %3 = load i32, i32* %i, align 4 + %add = add nsw i32 %3, 1 + store i32 %add, i32* %i, align 4 + br label %for.inc + +for.inc: + %4 = load i32, i32* %i, align 4 + %inc = add nsw i32 %4, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: + %5 = load i32, i32* %i, align 4 + %6 = bitcast i32* %i to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) + ret i32 %5 +} + +define dso_local signext i32 @f(i32 signext %upper) { +entry: + %upper.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 %upper, i32* %upper.addr, align 4 + %0 = bitcast i32* %i to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: + %1 = load i32, i32* %i, align 4 + %2 = load i32, i32* %upper.addr, align 4 + %cmp = icmp slt i32 %1, %2 + br i1 %cmp, label %for.body, label %for.end + +for.body: + %3 = load i32, i32* %i, align 4 + %add = add nsw i32 %3, 1 + store i32 %add, i32* %i, align 4 + br label %for.inc + +for.inc: + %4 = load i32, i32* %i, align 4 + %inc = add nsw i32 %4, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: + %5 = load i32, i32* %i, align 4 + %6 = bitcast i32* %i to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) + ret i32 %5 +} + +; Function Attrs: +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) + +; Function Attrs: +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) + +; Function Attrs: +define dso_local signext i32 @main() { +entry: + %retval = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 0, i32* %retval, align 4 + %0 = bitcast i32* %i to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) + %call = call signext i32 @f(i32 signext 10) + %call1 = call signext i32 @g(i32 signext 5) + %add = add nsw i32 %call, %call1 + store i32 %add, i32* %i, align 4 + %1 = load i32, i32* %i, align 4 + %2 = bitcast i32* %i to i8* + call void @llvm.lifetime.end.p0i8(i64 4, i8* %2) + ret i32 %1 +} + +; CHECK0: *** IR Dump At Start: *** +; CHECK0: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK0: *** IR Dump After SimplifyCFGPass *** (function: g) +; CHECK0: *** IR Pass PassManager (function: g) ignored *** +; CHECK0: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK0: *** IR Pass PassManager (function: f) ignored *** +; CHECK0: *** IR Dump After SimplifyCFGPass (function: main) omitted because no change *** +; CHECK0: *** IR Pass PassManager (function: main) ignored *** +; CHECK0: *** IR Pass ModuleToFunctionPassAdaptor{{[ ]?}}> (module) ignored *** +; CHECK0: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK0: *** IR Dump After PrintModulePass (module) omitted because no change *** + +; CHECK1: *** IR Dump At Start: *** +; CHECK1: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK1: *** IR Dump After SimplifyCFGPass (function: g) filtered out *** +; CHECK1: *** IR Pass PassManager (function: g) ignored *** +; CHECK1: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK1: *** IR Pass PassManager (function: f) ignored *** +; CHECK1: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK1: *** IR Pass PassManager (function: main) ignored *** +; CHECK1: *** IR Pass ModuleToFunctionPassAdaptor{{[ ]?}}> (module) ignored *** +; CHECK1: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK1: *** IR Dump After PrintModulePass (module) omitted because no change *** + +; CHECK2: *** IR Dump At Start: *** +; CHECK2: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK2: *** IR Dump After SimplifyCFGPass *** (function: g) +; CHECK2: ModuleID = '' +; CHECK2: *** IR Pass PassManager (function: g) ignored *** +; CHECK2: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK2: ModuleID = '' +; CHECK2: *** IR Pass PassManager (function: f) ignored *** +; CHECK2: *** IR Dump After SimplifyCFGPass (function: main) omitted because no change *** +; CHECK2: *** IR Pass PassManager (function: main) ignored *** +; CHECK2: *** IR Pass ModuleToFunctionPassAdaptor{{[ ]?}}> (module) ignored *** +; CHECK2: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK2: *** IR Dump After PrintModulePass (module) omitted because no change *** + +; CHECK3: *** IR Dump At Start: *** +; CHECK3: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK3: *** IR Dump After SimplifyCFGPass (function: g) filtered out *** +; CHECK3: *** IR Pass PassManager (function: g) ignored *** +; CHECK3: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK3: ModuleID = '' +; CHECK3: *** IR Pass PassManager (function: f) ignored *** +; CHECK3: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK3: *** IR Pass PassManager (function: main) ignored *** +; CHECK3: *** IR Pass ModuleToFunctionPassAdaptor{{[ ]?}}> (module) ignored *** +; CHECK3: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK3: *** IR Dump After PrintModulePass (module) omitted because no change *** + +; CHECK4: *** IR Dump At Start: *** +; CHECK4: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK4: *** IR Dump After SimplifyCFGPass *** (function: g) +; CHECK4: *** IR Pass PassManager (function: g) ignored *** +; CHECK4: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK4: *** IR Pass PassManager (function: f) ignored *** +; CHECK4: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK4: *** IR Pass PassManager (function: main) ignored *** +; CHECK4: *** IR Pass ModuleToFunctionPassAdaptor{{[ ]?}}> (module) ignored *** +; CHECK4: *** IR Dump After VerifierPass (module) omitted because no change *** +; CHECK4: *** IR Dump After PrintModulePass (module) omitted because no change *** + +; CHECK5: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK5: *** IR Dump After SimplifyCFGPass (function: g) filtered out *** +; CHECK5: *** IR Dump At Start: *** (function: g) +; CHECK5: *** IR Dump After InstCombinePass *** (function: g) +; CHECK5: *** IR Pass PassManager (function: g) ignored *** +; CHECK5: *** IR Dump After SimplifyCFGPass (function: f) filtered out *** +; CHECK5: *** IR Dump After InstCombinePass *** (function: f) +; CHECK5: *** IR Pass PassManager (function: f) ignored *** +; CHECK5: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK5: *** IR Dump After InstCombinePass *** (function: main) +; CHECK5: *** IR Pass PassManager (function: main) ignored *** +; CHECK5: *** IR Pass ModuleToFunctionPassAdaptor > (module) ignored *** +; CHECK5: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK5: *** IR Dump After PrintModulePass (module) filtered out *** + +; CHECK6: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK6: *** IR Dump At Start: *** (function: g) +; CHECK6: *** IR Dump After SimplifyCFGPass *** (function: g) +; CHECK6: *** IR Dump After InstCombinePass *** (function: g) +; CHECK6: *** IR Pass PassManager (function: g) ignored *** +; CHECK6: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK6: *** IR Dump After InstCombinePass *** (function: f) +; CHECK6: *** IR Pass PassManager (function: f) ignored *** +; CHECK6: *** IR Dump After SimplifyCFGPass (function: main) omitted because no change *** +; CHECK6: *** IR Dump After InstCombinePass *** (function: main) +; CHECK6: *** IR Pass PassManager (function: main) ignored *** +; CHECK6: *** IR Pass ModuleToFunctionPassAdaptor > (module) ignored *** +; CHECK6: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK6: *** IR Dump After PrintModulePass (module) filtered out *** + +; CHECK7: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK7: *** IR Dump After SimplifyCFGPass (function: g) filtered out *** +; CHECK7: *** IR Dump After InstCombinePass (function: g) filtered out *** +; CHECK7: *** IR Pass PassManager (function: g) ignored *** +; CHECK7: *** IR Dump At Start: *** (function: f) +; CHECK7: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK7: *** IR Dump After InstCombinePass *** (function: f) +; CHECK7: *** IR Pass PassManager (function: f) ignored *** +; CHECK7: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK7: *** IR Dump After InstCombinePass (function: main) filtered out *** +; CHECK7: *** IR Pass PassManager (function: main) ignored *** +; CHECK7: *** IR Pass ModuleToFunctionPassAdaptor > (module) ignored *** +; CHECK7: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK7: *** IR Dump After PrintModulePass (module) filtered out *** + +; CHECK8: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK8: *** IR Dump After SimplifyCFGPass (function: g) filtered out *** +; CHECK8: *** IR Dump After InstCombinePass (function: g) filtered out *** +; CHECK8: *** IR Pass PassManager (function: g) ignored *** +; CHECK8: *** IR Dump At Start: *** (function: f) +; CHECK8: *** IR Dump After SimplifyCFGPass *** (function: f) +; CHECK8: ModuleID = '' +; CHECK8: *** IR Dump After InstCombinePass *** (function: f) +; CHECK8: ModuleID = '' +; CHECK8: *** IR Pass PassManager (function: f) ignored *** +; CHECK8: *** IR Dump After SimplifyCFGPass (function: main) filtered out *** +; CHECK8: *** IR Dump After InstCombinePass (function: main) filtered out *** +; CHECK8: *** IR Pass PassManager (function: main) ignored *** +; CHECK8: *** IR Pass ModuleToFunctionPassAdaptor > (module) ignored *** +; CHECK8: *** IR Dump After VerifierPass (module) filtered out *** +; CHECK8: *** IR Dump After PrintModulePass (module) filtered out ***