Skip to content

Commit 8f49d46

Browse files
committed
Auto merge of #68720 - wesleywiser:llvm_time_trace, r=davidtwco
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 with 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
2 parents f43c34a + f5f86be commit 8f49d46

File tree

5 files changed

+48
-0
lines changed

5 files changed

+48
-0
lines changed

src/librustc_codegen_llvm/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,12 @@ impl CodegenBackend for LlvmCodegenBackend {
332332
// any more, we can finalize it (which involves renaming it)
333333
rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
334334

335+
sess.time("llvm_dump_timing_file", || {
336+
if sess.opts.debugging_opts.llvm_time_trace {
337+
llvm_util::time_trace_profiler_finish("llvm_timings.json");
338+
}
339+
});
340+
335341
Ok(())
336342
}
337343
}

src/librustc_codegen_llvm/llvm/ffi.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,10 @@ extern "C" {
14541454

14551455
pub fn LLVMInitializePasses();
14561456

1457+
pub fn LLVMTimeTraceProfilerInitialize();
1458+
1459+
pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char);
1460+
14571461
pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
14581462

14591463
pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;

src/librustc_codegen_llvm/llvm_util.rs

+18
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,31 @@ unsafe fn configure_llvm(sess: &Session) {
113113
}
114114
}
115115

116+
if sess.opts.debugging_opts.llvm_time_trace && get_major_version() >= 9 {
117+
// time-trace is not thread safe and running it in parallel will cause seg faults.
118+
if !sess.opts.debugging_opts.no_parallel_llvm {
119+
bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
120+
}
121+
122+
llvm::LLVMTimeTraceProfilerInitialize();
123+
}
124+
116125
llvm::LLVMInitializePasses();
117126

118127
::rustc_llvm::initialize_available_targets();
119128

120129
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
121130
}
122131

132+
pub fn time_trace_profiler_finish(file_name: &str) {
133+
unsafe {
134+
if get_major_version() >= 9 {
135+
let file_name = CString::new(file_name).unwrap();
136+
llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
137+
}
138+
}
139+
}
140+
123141
// WARNING: the features after applying `to_llvm_feature` must be known
124142
// to LLVM or the feature detection code will walk past the end of the feature
125143
// array, leading to crashes.

src/librustc_session/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
730730
"measure time of rustc processes"),
731731
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
732732
"measure time of each LLVM pass"),
733+
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],
734+
"generate JSON tracing data file from LLVM data"),
733735
input_stats: bool = (false, parse_bool, [UNTRACKED],
734736
"gather statistics about the input"),
735737
asm_comments: bool = (false, parse_bool, [TRACKED],

src/rustllvm/PassWrapper.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/Transforms/Instrumentation.h"
2727
#if LLVM_VERSION_GE(9, 0)
2828
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
29+
#include "llvm/Support/TimeProfiler.h"
2930
#endif
3031
#if LLVM_VERSION_GE(8, 0)
3132
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
@@ -57,6 +58,23 @@ extern "C" void LLVMInitializePasses() {
5758
initializeTarget(Registry);
5859
}
5960

61+
extern "C" void LLVMTimeTraceProfilerInitialize() {
62+
#if LLVM_VERSION_GE(9, 0)
63+
timeTraceProfilerInitialize();
64+
#endif
65+
}
66+
67+
extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
68+
#if LLVM_VERSION_GE(9, 0)
69+
StringRef FN(FileName);
70+
std::error_code EC;
71+
raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
72+
73+
timeTraceProfilerWrite(OS);
74+
timeTraceProfilerCleanup();
75+
#endif
76+
}
77+
6078
enum class LLVMRustPassKind {
6179
Other,
6280
Function,

0 commit comments

Comments
 (0)