Index: include/llvm/LTO/Config.h =================================================================== --- include/llvm/LTO/Config.h +++ include/llvm/LTO/Config.h @@ -88,6 +88,9 @@ /// Whether to emit the pass manager debuggging informations. bool DebugPassManager = false; + /// Statistics output file path. + std::string StatsFile; + bool ShouldDiscardValueNames = true; DiagnosticHandlerFunction DiagHandler; Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/LTO/LTO.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeReader.h" @@ -791,9 +792,26 @@ }; computeDeadSymbols(ThinLTO.CombinedIndex, GUIDPreservedSymbols, isPrevailing); - if (auto E = runRegularLTO(AddStream)) - return E; - return runThinLTO(AddStream, Cache); + // Setup output file to emit statistics. + std::unique_ptr StatsFile = nullptr; + if (!Conf.StatsFile.empty()) { + EnableStatistics(false); + std::error_code EC; + StatsFile = + llvm::make_unique(Conf.StatsFile, EC, sys::fs::F_None); + if (EC) + return errorCodeToError(EC); + StatsFile->keep(); + } + + Error Result = runRegularLTO(AddStream); + if (!Result) + Result = runThinLTO(AddStream, Cache); + + if (StatsFile) + PrintStatisticsJSON(StatsFile->os()); + + return Result; } Error LTO::runRegularLTO(AddStreamFn AddStream) { Index: test/tools/gold/X86/stats-file-option.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/stats-file-option.ll @@ -0,0 +1,23 @@ +; RUN: llvm-as -o %t.bc %s + +; Try to save statistics to file. +; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext -plugin-opt=stats-file=%t2.stats \ +; RUN: -m elf_x86_64 -r -o %t.o %t.bc +; RUN: FileCheck --input-file=%t2.stats %s + +; CHECK: { +; CHECK: "asm-printer.EmittedInsts": +; CHECK: } + + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @foo() { + ret i32 10 +} + +; Try to save statistics to an invalid file. +; RUN: not %gold -plugin %llvmshlibdir/LLVMgold%shlibext -plugin-opt=stats-file=%t2/foo.stats \ +; RUN: -m elf_x86_64 -r -o %t.o %t.bc 2>&1 | FileCheck --check-prefix=ERROR %s +; ERROR: LLVM gold plugin: No such file or directory Index: test/tools/llvm-lto2/X86/stats-file-option.ll =================================================================== --- /dev/null +++ test/tools/llvm-lto2/X86/stats-file-option.ll @@ -0,0 +1,23 @@ +; RUN: llvm-as < %s > %t1.bc + +; Try to save statistics to file. +; RUN: llvm-lto2 run %t1.bc -o %t.o -r %t1.bc,patatino,px -stats-file=%t2.stats +; RUN: FileCheck --input-file=%t2.stats %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @patatino() { + fence seq_cst + ret void +} + +; CHECK: { +; CHECK: "asm-printer.EmittedInsts": +; CHECK: } + + +; Try to save statistics to an invalid file. +; RUN: not llvm-lto2 run %t1.bc -o %t.o -r %t1.bc,patatino,px \ +; RUN: -stats-file=%t2/foo.stats 2>&1 | FileCheck --check-prefix=ERROR %s +; ERROR: LTO::run failed: No such file or directory Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -203,6 +203,8 @@ static std::string objcopy; // Directory to store the .dwo files. static std::string dwo_dir; + /// Statistics output filename. + static std::string stats_file; // Optimization remarks filename and hotness options static std::string OptRemarksFilename; @@ -278,6 +280,8 @@ OptRemarksFilename = opt.substr(strlen("opt-remarks-filename=")); } else if (opt == "opt-remarks-with-hotness") { OptRemarksWithHotness = true; + } else if (opt.startswith("stats-file=")) { + stats_file = opt.substr(strlen("stats-file=")); } else { // Save this option to pass to the code generator. // ParseCommandLineOptions() expects argv[0] to be program name. Lazily @@ -899,6 +903,7 @@ // Debug new pass manager if requested Conf.DebugPassManager = options::debug_pass_manager; + Conf.StatsFile = options::stats_file; return llvm::make_unique(std::move(Conf), Backend, options::ParallelCodeGenParallelismLevel); } Index: tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- tools/llvm-lto2/llvm-lto2.cpp +++ tools/llvm-lto2/llvm-lto2.cpp @@ -113,6 +113,9 @@ DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden, cl::desc("Print pass management debugging information")); +static cl::opt + StatsFile("stats-file", cl::desc("Filename to write statistics to")); + static void check(Error E, std::string Msg) { if (!E) return; @@ -240,6 +243,7 @@ Conf.OverrideTriple = OverrideTriple; Conf.DefaultTriple = DefaultTriple; + Conf.StatsFile = StatsFile; ThinBackend Backend; if (ThinLTODistributedIndexes)