diff --git a/llvm/test/tools/gold/X86/time-trace.ll b/llvm/test/tools/gold/X86/time-trace.ll new file mode 100644 index 0000000000000..391150f412f01 --- /dev/null +++ b/llvm/test/tools/gold/X86/time-trace.ll @@ -0,0 +1,32 @@ +; RUN: llvm-as %s -o %t.o + +; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: -m elf_x86_64 --plugin-opt=time-trace=%t2.json \ +; RUN: -shared %t.o -o /dev/null +; RUN: FileCheck --input-file %t2.json %s + +; RUN: %gold -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: -m elf_x86_64 --plugin-opt=time-trace=%t2.json \ +; RUN: --plugin-opt=time-trace-granularity=250 \ +; RUN: -shared %t.o -o /dev/null +; RUN: FileCheck --input-file %t2.json %s + +; RUN: not %gold -plugin %llvmshlibdir/LLVMgold%shlibext \ +; RUN: -m elf_x86_64 --plugin-opt=time-trace=%t2.json \ +; RUN: --plugin-opt=time-trace-granularity=hello \ +; RUN: -shared %t.o -o /dev/null 2> %t4.txt +; RUN: FileCheck --input-file %t4.txt %s --check-prefix=ERR + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @f1() { + ret void +} + +define void @f2() { + ret void +} + +; CHECK: "traceEvents": +; ERR: Invalid time trace granularity: hello diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp index 5503f7343cb67..265ebcbff5877 100644 --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Statistic.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" @@ -31,6 +32,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Threading.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" #include @@ -220,6 +222,10 @@ namespace options { static std::string cs_profile_path; static bool cs_pgo_gen = false; + // Time trace options. + static std::string time_trace_file; + static unsigned time_trace_granularity = 500; + static void process_plugin_option(const char *opt_) { if (opt_ == nullptr) @@ -308,6 +314,14 @@ namespace options { RemarksFormat = std::string(opt); } else if (opt.consume_front("stats-file=")) { stats_file = std::string(opt); + } else if (opt.consume_front("time-trace=")) { + time_trace_file = std::string(opt); + } else if (opt.consume_front("time-trace-granularity=")) { + unsigned Granularity; + if (opt.getAsInteger(10, Granularity)) + message(LDPL_FATAL, "Invalid time trace granularity: %s", opt); + else + time_trace_granularity = Granularity; } else { // Save this option to pass to the code generator. // ParseCommandLineOptions() expects argv[0] to be program name. Lazily @@ -953,6 +967,10 @@ static std::unique_ptr createLTO(IndexWriteCallback OnIndexWrite, Conf.HasWholeProgramVisibility = options::whole_program_visibility; Conf.StatsFile = options::stats_file; + + Conf.TimeTraceEnabled = !options::time_trace_file.empty(); + Conf.TimeTraceGranularity = options::time_trace_granularity; + return std::make_unique(std::move(Conf), Backend, options::ParallelCodeGenParallelismLevel); } @@ -1113,6 +1131,19 @@ static ld_plugin_status allSymbolsReadHook() { if (unsigned NumOpts = options::extra.size()) cl::ParseCommandLineOptions(NumOpts, &options::extra[0]); + // Initialize time trace profiler + if (!options::time_trace_file.empty()) + llvm::timeTraceProfilerInitialize(options::time_trace_granularity, + options::extra.size() ? options::extra[0] + : "LLVMgold"); + auto FinalizeTimeTrace = llvm::make_scope_exit([&]() { + if (!llvm::timeTraceProfilerEnabled()) + return; + assert(!options::time_trace_file.empty()); + check(llvm::timeTraceProfilerWrite(options::time_trace_file, output_name)); + llvm::timeTraceProfilerCleanup(); + }); + std::vector, bool>> Files = runLTO(); if (options::TheOutputType == options::OT_DISABLE ||