diff --git a/llvm/include/llvm/Pass.h b/llvm/include/llvm/Pass.h index ff64117035091..a29b3771abb46 100644 --- a/llvm/include/llvm/Pass.h +++ b/llvm/include/llvm/Pass.h @@ -361,6 +361,12 @@ extern bool TimePassesIsEnabled; // @brief Tells if the function IR should be printed by PrinterPass. extern bool isFunctionInPrintList(StringRef FunctionName); +/// forcePrintModuleIR - returns true if IR printing passes should +// be printing module IR (even for local-pass printers e.g. function-pass) +// to provide more context, as enabled by debugging option -print-module-scope +// @brief Tells if IR printer should be printing module IR +extern bool forcePrintModuleIR(); + } // end namespace llvm // Include support files that contain important APIs commonly used by Passes, diff --git a/llvm/lib/IR/IRPrintingPasses.cpp b/llvm/lib/IR/IRPrintingPasses.cpp index 4c8afda18b711..3308ef4c249ce 100644 --- a/llvm/lib/IR/IRPrintingPasses.cpp +++ b/llvm/lib/IR/IRPrintingPasses.cpp @@ -45,7 +45,10 @@ PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner) PreservedAnalyses PrintFunctionPass::run(Function &F, FunctionAnalysisManager &) { if (isFunctionInPrintList(F.getName())) - OS << Banner << static_cast(F); + if (forcePrintModuleIR()) + OS << Banner << " (function: " << F.getName() << ")\n" << *F.getParent(); + else + OS << Banner << static_cast(F); return PreservedAnalyses::all(); } diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp index c13893d1a9edf..8bd9ed6ef0faa 100644 --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -82,6 +82,12 @@ static cl::opt PrintAfterAll("print-after-all", llvm::cl::desc("Print IR after each pass"), cl::init(false), cl::Hidden); +static cl::opt + PrintModuleScope("print-module-scope", + cl::desc("When printing IR for print-[before|after]{-all} " + "always print a module IR"), + cl::init(false)); + static cl::list PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), cl::desc("Only print IR for functions whose name " @@ -115,6 +121,8 @@ static bool ShouldPrintAfterPass(const PassInfo *PI) { return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); } +bool llvm::forcePrintModuleIR() { return PrintModuleScope; } + bool llvm::isFunctionInPrintList(StringRef FunctionName) { static std::unordered_set PrintFuncNames(PrintFuncsList.begin(), PrintFuncsList.end()); diff --git a/llvm/test/Other/print-module-scope.ll b/llvm/test/Other/print-module-scope.ll new file mode 100644 index 0000000000000..0e9c4d59cc3b3 --- /dev/null +++ b/llvm/test/Other/print-module-scope.ll @@ -0,0 +1,55 @@ +; This test is checking basic properties of -print-module-scope options: +; - dumps all the module IR at once +; - all the function attributes are shown, including those of declarations +; - works on top of -print-after and -filter-print-funcs +; +; RUN: opt < %s 2>&1 -disable-output \ +; RUN: -simplifycfg -print-after=simplifycfg -print-module-scope \ +; RUN: | FileCheck %s -check-prefix=CFG +; RUN: opt < %s 2>&1 -disable-output \ +; RUN: -simplifycfg -print-after=simplifycfg -filter-print-funcs=foo -print-module-scope \ +; RUN: | FileCheck %s -check-prefix=FOO + +; CFG: IR Dump After +; CFG-SAME: function: foo +; CFG-NEXT: ModuleID = +; CFG: define void @foo +; CFG: define void @bar +; CFG: declare void @baz +; CFG: IR Dump After +; CFG-SAME: function: bar +; CFG-NEXT: ModuleID = +; CFG: define void @foo +; CFG: define void @bar +; CFG: declare void @baz + +; FOO: IR Dump After +; FOO-NOT: function: bar +; FOO-SAME: function: foo +; FOO-NEXT: ModuleID = +; FOO: Function Attrs: nounwind ssp +; FOO: define void @foo +; FOO: Function Attrs: nounwind +; FOO: define void @bar +; FOO: Function Attrs: nounwind readnone ssp +; FOO: declare void @baz + +define void @foo() nounwind ssp { + call void @baz() + ret void +} + +define void @bar() #0 { + ret void +} + +declare void @baz() #1 + +attributes #0 = { nounwind "no-frame-pointer-elim"="true" } + +attributes #1 = { nounwind readnone ssp "use-soft-float"="false" } +; FOO: attributes #{{[0-9]}} = { nounwind "no-frame-pointer-elim"="true" } + +; FOO: attributes #{{[0-9]}} = { nounwind readnone ssp "use-soft-float"="false" } + +; FOO-NOT: IR Dump