diff options
| author | Michael Benfield <mbenfield@google.com> | 2021-05-07 07:41:37 +0000 |
|---|---|---|
| committer | Michael Benfield <mbenfield@google.com> | 2021-10-06 19:36:52 +0000 |
| commit | a17193dbb931ea0c8b66d82f640385bce8b4929a (patch) | |
| tree | 5649047fed7b0c037e06ba0cfc05bd70028428e1 /compiler/rustc_codegen_llvm/src | |
| parent | d7539a6af09e5889ed9bcb8b49571b7a59c32e65 (diff) | |
| download | rust-a17193dbb931ea0c8b66d82f640385bce8b4929a.tar.gz rust-a17193dbb931ea0c8b66d82f640385bce8b4929a.zip | |
Enable AutoFDO.
This largely involves implementing the options debug-info-for-profiling and profile-sample-use and forwarding them on to LLVM. AutoFDO can be used on x86-64 Linux like this: rustc -O -Cdebug-info-for-profiling main.rs -o main perf record -b ./main create_llvm_prof --binary=main --out=code.prof rustc -O -Cprofile-sample-use=code.prof main.rs -o main2 Now `main2` will have feedback directed optimization applied to it. The create_llvm_prof tool can be obtained from this github repository: https://github.com/google/autofdo Fixes #64892.
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/attributes.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/back/write.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 |
3 files changed, 22 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 51c70f0868f..659cf9ea070 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -263,6 +263,10 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: attributes::emit_uwtable(llfn, true); } + if cx.sess().opts.debugging_opts.profile_sample_use.is_some() { + llvm::AddFunctionAttrString(llfn, Function, cstr!("use-sample-profile")); + } + // FIXME: none of these three functions interact with source level attributes. set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index ab48c56a626..ca78254f0c8 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -370,6 +370,13 @@ fn get_pgo_use_path(config: &ModuleConfig) -> Option<CString> { .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) } +fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> { + config + .pgo_sample_use + .as_ref() + .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) +} + pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool { // The new pass manager is enabled by default for LLVM >= 13. // This matches Clang, which also enables it since Clang 13. @@ -389,6 +396,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( let using_thin_buffers = opt_stage == llvm::OptStage::PreLinkThinLTO || config.bitcode_needed(); let pgo_gen_path = get_pgo_gen_path(config); let pgo_use_path = get_pgo_use_path(config); + let pgo_sample_use_path = get_pgo_sample_use_path(config); let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO; // Sanitizer instrumentation is only inserted during the pre-link optimization stage. let sanitizer_options = if !is_lto { @@ -439,6 +447,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), config.instrument_coverage, config.instrument_gcov, + pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), + config.debug_info_for_profiling, llvm_selfprofiler, selfprofile_before_pass_callback, selfprofile_after_pass_callback, @@ -544,6 +554,9 @@ pub(crate) unsafe fn optimize( if config.instrument_coverage { llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap()); } + if config.debug_info_for_profiling { + llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap()); + } add_sanitizer_passes(config, &mut extra_passes); @@ -1001,6 +1014,7 @@ pub unsafe fn with_llvm_pmb( let inline_threshold = config.inline_threshold; let pgo_gen_path = get_pgo_gen_path(config); let pgo_use_path = get_pgo_use_path(config); + let pgo_sample_use_path = get_pgo_sample_use_path(config); llvm::LLVMRustConfigurePassManagerBuilder( builder, @@ -1011,6 +1025,7 @@ pub unsafe fn with_llvm_pmb( prepare_for_thin_lto, pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), + pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()), ); llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 436d906827b..5d437b2a068 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2176,6 +2176,7 @@ extern "C" { PrepareForThinLTO: bool, PGOGenPath: *const c_char, PGOUsePath: *const c_char, + PGOSampleUsePath: *const c_char, ); pub fn LLVMRustAddLibraryInfo( PM: &PassManager<'a>, @@ -2210,6 +2211,8 @@ extern "C" { PGOUsePath: *const c_char, InstrumentCoverage: bool, InstrumentGCOV: bool, + PGOSampleUsePath: *const c_char, + DebugInfoForProfiling: bool, llvm_selfprofiler: *mut c_void, begin_callback: SelfProfileBeforePassCallback, end_callback: SelfProfileAfterPassCallback, |
