Skip to content

Commit 5747631

Browse files
committed
Auto merge of #54592 - GabrielMajeri:no-plt, r=<try>
[WIP] Support for disabling PLT for better function call performance This PR gives `rustc` the ability to skip the PLT when generating function calls into shared libraries. This can improve performance by reducing branch indirection. AFAIK, the only advantage of using the PLT is to allow for ELF lazy binding. However, since Rust already [enables full relro for security](#43170), lazy binding was disabled anyway. This is a little known feature which is supported by [GCC](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html) and [Clang](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fplt) as `-fno-plt` (some Linux distros [enable it by default](https://git.archlinux.org/svntogit/packages.git/tree/trunk/makepkg.conf?h=packages/pacman#n40) for all builds). Implementation inspired by [this patch](https://reviews.llvm.org/D39079#change-YvkpNDlMs_LT) which adds `-fno-plt` support to Clang. ## Performance I didn't run a lot of benchmarks, but these are the results on my machine for a `clap` [benchmark](https://github.com/clap-rs/clap/blob/master/benches/05_ripgrep.rs): ``` name control ns/iter no-plt ns/iter diff ns/iter diff % speedup build_app_long 11,097 10,733 -364 -3.28% x 1.03 build_app_short 11,089 10,742 -347 -3.13% x 1.03 build_help_long 186,835 182,713 -4,122 -2.21% x 1.02 build_help_short 80,949 78,455 -2,494 -3.08% x 1.03 parse_clean 12,385 12,044 -341 -2.75% x 1.03 parse_complex 19,438 19,017 -421 -2.17% x 1.02 parse_lots 431,493 421,421 -10,072 -2.33% x 1.02 ``` A small performance improvement across the board, with no downsides. It's likely binaries which make a lot of function calls into dynamic libraries could see even more improvements. [This comment](https://patchwork.ozlabs.org/patch/468993/#1028255) suggests that, in some cases, `-fno-plt` could improve PIC/PIE code performance by 10%. ## To do - [ ] Do a perf run to see the effect this has on the compiler (cc @michaelwoerister), and possibly run benchmarks on some more crates - [ ] Add a code gen test - [ ] Should this be always enabled or should it be behind a command line option? If so, what should it be called? `-Z no-plt`? `-Z plt=no`?
2 parents 6846f22 + ddf98c1 commit 5747631

File tree

4 files changed

+11
-1
lines changed

4 files changed

+11
-1
lines changed

Diff for: src/librustc_codegen_llvm/attributes.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc::ty::layout::HasTyCtxt;
2020
use rustc::ty::query::Providers;
2121
use rustc_data_structures::sync::Lrc;
2222
use rustc_data_structures::fx::FxHashMap;
23-
use rustc_target::spec::PanicStrategy;
23+
use rustc_target::spec::{PanicStrategy, RelroLevel};
2424

2525
use attributes;
2626
use llvm::{self, Attribute};
@@ -174,6 +174,12 @@ pub fn from_fn_attrs(
174174
set_frame_pointer_elimination(cx, llfn);
175175
set_probestack(cx, llfn);
176176

177+
// Only enable this optimization if full relro is also enabled.
178+
// In this case, lazy binding was already unavailable, so nothing is lost.
179+
if let RelroLevel::Full = cx.sess().target.target.options.relro_level {
180+
Attribute::NonLazyBind.apply_llfn(Function, llfn);
181+
}
182+
177183
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
178184
Attribute::Cold.apply_llfn(Function, llfn);
179185
}

Diff for: src/librustc_codegen_llvm/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ pub enum Attribute {
122122
SanitizeThread = 20,
123123
SanitizeAddress = 21,
124124
SanitizeMemory = 22,
125+
NonLazyBind = 23,
125126
}
126127

127128
/// LLVMIntPredicate

Diff for: src/rustllvm/RustWrapper.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
178178
return Attribute::SanitizeAddress;
179179
case SanitizeMemory:
180180
return Attribute::SanitizeMemory;
181+
case NonLazyBind:
182+
return Attribute::NonLazyBind;
181183
}
182184
report_fatal_error("bad AttributeKind");
183185
}

Diff for: src/rustllvm/rustllvm.h

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum LLVMRustAttribute {
9797
SanitizeThread = 20,
9898
SanitizeAddress = 21,
9999
SanitizeMemory = 22,
100+
NonLazyBind = 23,
100101
};
101102

102103
typedef struct OpaqueRustString *RustStringRef;

0 commit comments

Comments
 (0)