diff --git a/include/llvm/LTO/legacy/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h index bbd671eb818..f1468211128 100644 --- a/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -41,6 +41,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Module.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include @@ -205,6 +206,9 @@ private: void emitError(const std::string &ErrMsg); void emitWarning(const std::string &ErrMsg); + bool setupOptimizationRemarks(); + void finishOptimizationRemarks(); + LLVMContext &Context; std::unique_ptr MergedModule; std::unique_ptr TheLinker; @@ -232,6 +236,7 @@ private: bool ShouldEmbedUselists = false; bool ShouldRestoreGlobalsLinkage = false; TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile; + std::unique_ptr DiagnosticOutputFile; }; } #endif diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 75810643b9c..d2f964e4d24 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -49,6 +49,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" @@ -92,6 +93,11 @@ cl::opt LTOStripInvalidDebugInfo( cl::Hidden); } +static cl::opt + RemarksFilename("pass-remarks-output", + cl::desc("Output filename for pass remarks"), + cl::value_desc("filename")); + LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context) : Context(Context), MergedModule(new Module("ld-temp.o", Context)), TheLinker(new Linker(*MergedModule)) { @@ -495,6 +501,29 @@ void LTOCodeGenerator::verifyMergedModuleOnce() { report_fatal_error("Broken module found, compilation aborted!"); } +bool LTOCodeGenerator::setupOptimizationRemarks() { + if (RemarksFilename != "") { + std::error_code EC; + DiagnosticOutputFile = llvm::make_unique( + RemarksFilename, EC, sys::fs::F_None); + if (EC) { + emitError(EC.message()); + return false; + } + Context.setDiagnosticsOutputFile( + new yaml::Output(DiagnosticOutputFile->os())); + } + return true; +} + +void LTOCodeGenerator::finishOptimizationRemarks() { + if (DiagnosticOutputFile) { + DiagnosticOutputFile->keep(); + // FIXME: LTOCodeGenerator dtor is not invoked on Darwin + DiagnosticOutputFile->os().flush(); + } +} + /// Optimize merged modules using various IPO passes bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, bool DisableGVNLoadPRE, @@ -502,6 +531,9 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, if (!this->determineTarget()) return false; + if (!setupOptimizationRemarks()) + return false; + // We always run the verifier once on the merged module, the `DisableVerify` // parameter only applies to subsequent verify. verifyMergedModuleOnce(); @@ -535,6 +567,8 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, // Run our queue of passes all at once now, efficiently. passes.run(*MergedModule); + finishOptimizationRemarks(); + return true; } diff --git a/test/LTO/X86/diagnostic-handler-remarks.ll b/test/LTO/X86/diagnostic-handler-remarks.ll index 9da11f1ab62..b861fa79134 100644 --- a/test/LTO/X86/diagnostic-handler-remarks.ll +++ b/test/LTO/X86/diagnostic-handler-remarks.ll @@ -27,6 +27,13 @@ ; RUN: FileCheck %s -allow-empty ; RUN: llvm-nm %t.o | FileCheck %s -check-prefix NM +; Optimization records are collected regardless of the diagnostic handler +; RUN: llvm-lto -pass-remarks-output=%t.yaml \ +; RUN: -exported-symbol _func2 \ +; RUN: -exported-symbol _main -o %t.o %t.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty +; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML + ; REMARKS: remark: {{.*}} foo inlined into main ; REMARKS: remark: {{.*}} loop not vectorized: cannot prove it is safe to reorder memory operations ; REMARKS_DH: llvm-lto: remark: {{.*}} foo inlined into main @@ -37,6 +44,16 @@ ; NM: func2 ; NM: main +; YAML: --- !Passed +; YAML: Pass: inline +; YAML: Name: Inlined +; YAML: Function: main +; YAML: Args: +; YAML: - Callee: foo +; YAML: - String: ' inlined into ' +; YAML: - Caller: main +; YAML: ... + target triple = "x86_64-apple-darwin" declare i32 @bar()