llvm: Add support for collecting time trace (#8546)
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).
This commit is contained in:
@@ -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>
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user