Skip to content

Commit

Permalink
llvm: Add support for collecting time trace (#8546)
Browse files Browse the repository at this point in the history
LLVM time profiler can collect time traces and present them in a
hierarchical view. Which breakdowns the time spent in each Pass or even
IR unit. The result is also exported into a format that can be easily
visualized by the Chrome browser.

Currently this features is controlled by the following environment
variables:
 - `ZIG_LLVM_TIME_TRACE_FILE` toggles this feature and specifies the
   output time trace file.
 - `ZIG_LLVM_TIME_TRACE_GRANULARITY` controls the time granularity in
   ms (default to 500).
  • Loading branch information
mshockwave committed Jun 4, 2021
1 parent 9c08a33 commit 83e0a49
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions src/zig_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/TargetParser.h>
#include <llvm/Support/TimeProfiler.h>
#include <llvm/Support/Timer.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/TargetRegistry.h>
Expand Down Expand Up @@ -187,13 +189,48 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
return unwrap(TD)->getProgramAddressSpace();
}

namespace {
// LLVM's time profiler can provide a hierarchy view of the time spent
// in each component. It generates JSON report in Chrome's "Trace Event"
// format. So the report can be easily visualized by the Chrome browser.
struct TimeTracerRAII {
// Granularity in ms
unsigned TimeTraceGranularity;
StringRef TimeTraceFile, OutputFilename;
bool EnableTimeTrace;

TimeTracerRAII(StringRef ProgramName, StringRef OF)
: TimeTraceGranularity(500U),
TimeTraceFile(std::getenv("ZIG_LLVM_TIME_TRACE_FILE")),
OutputFilename(OF),
EnableTimeTrace(!TimeTraceFile.empty()) {
if (EnableTimeTrace) {
if (const char *G = std::getenv("ZIG_LLVM_TIME_TRACE_GRANULARITY"))
TimeTraceGranularity = (unsigned)std::atoi(G);

llvm::timeTraceProfilerInitialize(TimeTraceGranularity, ProgramName);
}
}

~TimeTracerRAII() {
if (EnableTimeTrace) {
if (auto E = llvm::timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {
handleAllErrors(std::move(E), [&](const StringError &SE) {
errs() << SE.getMessage() << "\n";
});
return;
}
timeTraceProfilerCleanup();
}
}
};
} // end anonymous namespace

bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
char **error_message, bool is_debug,
bool is_small, bool time_report, bool tsan, bool lto,
const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)
{
// TODO: Maybe we should collect time trace rather than using timer
// to get a more hierarchical timeline view
TimePassesIsEnabled = time_report;

raw_fd_ostream *dest_asm_ptr = nullptr;
Expand All @@ -219,6 +256,12 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr),
dest_bin(dest_bin_ptr);

auto PID = sys::Process::getProcessId();
std::string ProcName = "zig-";
ProcName += std::to_string(PID);
TimeTracerRAII TimeTracer(ProcName,
bin_filename? bin_filename : asm_filename);

TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);
target_machine.setO0WantsFastISel(true);

Expand Down

0 comments on commit 83e0a49

Please sign in to comment.