diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-11-05 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-11-05 17:47:11 +0100 |
| commit | 5a09e1213543fca0cbc9a0a61643e8d1bd4fccd8 (patch) | |
| tree | ad40a748f2f13decb0537bf651da8d2c0230e568 /compiler/rustc_codegen_llvm/src | |
| parent | d22dd65835190278f315e06442614142653ec98f (diff) | |
| download | rust-5a09e1213543fca0cbc9a0a61643e8d1bd4fccd8.tar.gz rust-5a09e1213543fca0cbc9a0a61643e8d1bd4fccd8.zip | |
Initialize LLVM time trace profiler on each code generation thread
In https://reviews.llvm.org/D71059 LLVM 11, the time trace profiler was extended to support multiple threads. `timeTraceProfilerInitialize` creates a thread local profiler instance. When a thread finishes `timeTraceProfilerFinishThread` moves a thread local instance into a global collection of instances. Finally when all codegen work is complete `timeTraceProfilerWrite` writes data from the current thread local instance and the instances in global collection of instances. Previously, the profiler was intialized on a single thread only. Since this thread performs no code generation on its own, the resulting profile was empty. Update LLVM codegen to initialize & finish time trace profiler on each code generation thread.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/lib.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 |
3 files changed, 51 insertions, 5 deletions
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 8f4d79e7147..64fedb7bc1a 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -76,6 +76,27 @@ mod value; #[derive(Clone)] pub struct LlvmCodegenBackend(()); +struct TimeTraceProfiler { + enabled: bool, +} + +impl TimeTraceProfiler { + fn new(enabled: bool) -> Self { + if enabled { + unsafe { llvm::LLVMTimeTraceProfilerInitialize() } + } + TimeTraceProfiler { enabled } + } +} + +impl Drop for TimeTraceProfiler { + fn drop(&mut self) { + if self.enabled { + unsafe { llvm::LLVMTimeTraceProfilerFinishThread() } + } + } +} + impl ExtraBackendMethods for LlvmCodegenBackend { fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm { ModuleLlvm::new_metadata(tcx, mod_name) @@ -119,6 +140,34 @@ impl ExtraBackendMethods for LlvmCodegenBackend { fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> { llvm_util::tune_cpu(sess) } + + fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + std::thread::spawn(move || { + let _profiler = TimeTraceProfiler::new(time_trace); + f() + }) + } + + fn spawn_named_thread<F, T>( + time_trace: bool, + name: String, + f: F, + ) -> std::io::Result<std::thread::JoinHandle<T>> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + std::thread::Builder::new().name(name).spawn(move || { + let _profiler = TimeTraceProfiler::new(time_trace); + f() + }) + } } impl WriteBackendMethods for LlvmCodegenBackend { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 21d2388fc30..749eec459ac 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1737,6 +1737,8 @@ extern "C" { pub fn LLVMTimeTraceProfilerInitialize(); + pub fn LLVMTimeTraceProfilerFinishThread(); + pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char); pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 246bb88885d..34c28938c85 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -113,11 +113,6 @@ unsafe fn configure_llvm(sess: &Session) { } if sess.opts.debugging_opts.llvm_time_trace { - // 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(); } |
