Add support for enabling the LLVM time-trace feature
I found this helpful while investigating an LLVM performance issue. Passing `-Z llvm-time-trace` causes a `llvm_timings.json` file to be created. This file can be inspected in either the Chrome Profiler tools or with any other compatible tool like SpeedScope. More information on the LLVM feature: - https://aras-p.info/blog/2019/01/16/time-trace-timeline-flame-chart-profiler-for-Clang/ - https://reviews.llvm.org/rL357340
This commit is contained in:
parent
cd1ef390e7
commit
f5f86be1d4
5 changed files with 48 additions and 0 deletions
|
@ -332,6 +332,12 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
// any more, we can finalize it (which involves renaming it)
|
// any more, we can finalize it (which involves renaming it)
|
||||||
rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
|
rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
|
||||||
|
|
||||||
|
sess.time("llvm_dump_timing_file", || {
|
||||||
|
if sess.opts.debugging_opts.llvm_time_trace {
|
||||||
|
llvm_util::time_trace_profiler_finish("llvm_timings.json");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1454,6 +1454,10 @@ extern "C" {
|
||||||
|
|
||||||
pub fn LLVMInitializePasses();
|
pub fn LLVMInitializePasses();
|
||||||
|
|
||||||
|
pub fn LLVMTimeTraceProfilerInitialize();
|
||||||
|
|
||||||
|
pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char);
|
||||||
|
|
||||||
pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
|
pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
|
||||||
|
|
||||||
pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
|
pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
|
||||||
|
|
|
@ -113,6 +113,15 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sess.opts.debugging_opts.llvm_time_trace && get_major_version() >= 9 {
|
||||||
|
// time-trace is not thread safe and running it in parallel will cause seg faults.
|
||||||
|
if !sess.opts.debugging_opts.no_parallel_llvm {
|
||||||
|
bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::LLVMTimeTraceProfilerInitialize();
|
||||||
|
}
|
||||||
|
|
||||||
llvm::LLVMInitializePasses();
|
llvm::LLVMInitializePasses();
|
||||||
|
|
||||||
::rustc_llvm::initialize_available_targets();
|
::rustc_llvm::initialize_available_targets();
|
||||||
|
@ -120,6 +129,15 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||||
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
|
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn time_trace_profiler_finish(file_name: &str) {
|
||||||
|
unsafe {
|
||||||
|
if get_major_version() >= 9 {
|
||||||
|
let file_name = CString::new(file_name).unwrap();
|
||||||
|
llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WARNING: the features after applying `to_llvm_feature` must be known
|
// WARNING: the features after applying `to_llvm_feature` must be known
|
||||||
// to LLVM or the feature detection code will walk past the end of the feature
|
// to LLVM or the feature detection code will walk past the end of the feature
|
||||||
// array, leading to crashes.
|
// array, leading to crashes.
|
||||||
|
|
|
@ -718,6 +718,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||||
"measure time of rustc processes"),
|
"measure time of rustc processes"),
|
||||||
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
|
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"measure time of each LLVM pass"),
|
"measure time of each LLVM pass"),
|
||||||
|
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
|
||||||
|
"generate JSON tracing data file from LLVM data"),
|
||||||
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"gather statistics about the input"),
|
"gather statistics about the input"),
|
||||||
asm_comments: bool = (false, parse_bool, [TRACKED],
|
asm_comments: bool = (false, parse_bool, [TRACKED],
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "llvm/Transforms/Instrumentation.h"
|
#include "llvm/Transforms/Instrumentation.h"
|
||||||
#if LLVM_VERSION_GE(9, 0)
|
#if LLVM_VERSION_GE(9, 0)
|
||||||
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
||||||
|
#include "llvm/Support/TimeProfiler.h"
|
||||||
#endif
|
#endif
|
||||||
#if LLVM_VERSION_GE(8, 0)
|
#if LLVM_VERSION_GE(8, 0)
|
||||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||||
|
@ -57,6 +58,23 @@ extern "C" void LLVMInitializePasses() {
|
||||||
initializeTarget(Registry);
|
initializeTarget(Registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMTimeTraceProfilerInitialize() {
|
||||||
|
#if LLVM_VERSION_GE(9, 0)
|
||||||
|
timeTraceProfilerInitialize();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
|
||||||
|
#if LLVM_VERSION_GE(9, 0)
|
||||||
|
StringRef FN(FileName);
|
||||||
|
std::error_code EC;
|
||||||
|
raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
|
||||||
|
|
||||||
|
timeTraceProfilerWrite(OS);
|
||||||
|
timeTraceProfilerCleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
enum class LLVMRustPassKind {
|
enum class LLVMRustPassKind {
|
||||||
Other,
|
Other,
|
||||||
Function,
|
Function,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue