-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Fix -Zregparm
for LLVM builtins
#145309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix -Zregparm
for LLVM builtins
#145309
Conversation
I think this should fix it already, let me know if I am missing something! Working on the tests now. |
rustbot has assigned @petrochenkov. Use |
I added a test verifying that the |
r? nikic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for doing a quick fix here!
Just a few requests to make sure we're testing what we expect
This PR modifies cc @jieyouxu |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two small nits but this looks good to me once CI passes, please squash
@nikic anything else?
74a664c
to
2e24b51
Compare
I squashed, let me know if there is anything else I can do! |
2e24b51
to
02d4666
Compare
Looks great! Thanks for making this happen, and welcome :) @bors r+ |
Thank you very much for all the help! I'll keep an eye on the issue tracker, but if you come across anything you think would be a good fit, please let me know! |
set * Enforce the `-Zregparm=N` flag by setting the NumRegisterParameters LLVM module flag * Add assembly tests verifying that the parameters are passed in registers for reparm values 1, 2, and 3, for both LLVM intrinsics and non-builtin functions * Add c_void type to minicore
02d4666
to
04ff144
Compare
Fixed the typo, thank you! |
@bors r=tgross35 rollup=iffy assembly test |
If we do this, do we have to also keep the logic in our own adjustments or does setting just the LLVM flag suffice? |
Regparm already sets the Our Rust ABI isn't affected by regparm, at least not currently. In theory we probably could make use of the same settings for some perf improvements on 32-bit builds. |
…ross35 Fix `-Zregparm` for LLVM builtins This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead. When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls. As proposed by `@tgross35,` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set. ```rust // compiler/rust_codegen_llvm/src/context.rs#375-382 if let Some(regparm_count) = sess.opts.unstable_opts.regparm { llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Error, "NumRegisterParameters", regparm_count, ); } ``` [Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer. Here is the final result for the code snippet in the original issue: ```asm entrypoint: push esi mov esi, eax mov eax, ecx mov ecx, esi pop esi jmp memset ; Tail call parameters in registers ``` Fixes: rust-lang#145271
…ross35 Fix `-Zregparm` for LLVM builtins This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead. When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls. As proposed by ``@tgross35,`` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set. ```rust // compiler/rust_codegen_llvm/src/context.rs#375-382 if let Some(regparm_count) = sess.opts.unstable_opts.regparm { llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Error, "NumRegisterParameters", regparm_count, ); } ``` [Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer. Here is the final result for the code snippet in the original issue: ```asm entrypoint: push esi mov esi, eax mov eax, ecx mov ecx, esi pop esi jmp memset ; Tail call parameters in registers ``` Fixes: rust-lang#145271
Rollup of 11 pull requests Successful merges: - #139345 (Extend `QueryStability` to handle `IntoIterator` implementations) - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 11 pull requests Successful merges: - #139345 (Extend `QueryStability` to handle `IntoIterator` implementations) - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
…ross35 Fix `-Zregparm` for LLVM builtins This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead. When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls. As proposed by ```@tgross35,``` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set. ```rust // compiler/rust_codegen_llvm/src/context.rs#375-382 if let Some(regparm_count) = sess.opts.unstable_opts.regparm { llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Error, "NumRegisterParameters", regparm_count, ); } ``` [Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer. Here is the final result for the code snippet in the original issue: ```asm entrypoint: push esi mov esi, eax mov eax, ecx mov ecx, esi pop esi jmp memset ; Tail call parameters in registers ``` Fixes: rust-lang#145271
Rollup of 10 pull requests Successful merges: - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 10 pull requests Successful merges: - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 10 pull requests Successful merges: - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 10 pull requests Successful merges: - #144838 (Fix outdated doc comment) - #145206 (Port `#[custom_mir(..)]` to the new attribute system) - #145208 (Implement declarative (`macro_rules!`) derive macros (RFC 3698)) - #145309 (Fix `-Zregparm` for LLVM builtins) - #145355 (Add codegen test for issue 122734) - #145420 (cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`) - #145451 (Add static glibc to the nix dev shell) - #145460 (Speedup `copy_src_dirs` in bootstrap) - #145476 (Fix typo in doc for library/std/src/fs.rs#set_permissions) - #145485 (Fix deprecation attributes on foreign statics) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of #145309 - winstonallo:issue-145271-fix, r=tgross35 Fix `-Zregparm` for LLVM builtins This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead. When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls. As proposed by ````@tgross35,```` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set. ```rust // compiler/rust_codegen_llvm/src/context.rs#375-382 if let Some(regparm_count) = sess.opts.unstable_opts.regparm { llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Error, "NumRegisterParameters", regparm_count, ); } ``` [Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer. Here is the final result for the code snippet in the original issue: ```asm entrypoint: push esi mov esi, eax mov eax, ecx mov ecx, esi pop esi jmp memset ; Tail call parameters in registers ``` Fixes: #145271
…test, r=tgross35 Add assembly test for `-Zreg-struct-return` option r? `@tgross35` As discussed in rust-lang#145309 with `@tgross35` and `@ojeda,` I added assembly tests for the `-Zreg-struct-return` option verifying that it changes the ABI from hidden pointer to register-return on x86_32. The test covers: - Direct struct construction, showing register return vs hidden pointer - External function calls returning structs, showing ABI mismatch handling Different memory layouts affect ABI mismatch handling, but register returns use the same register allocation regardless of struct field layout (apart from the fact that they use smaller registers for smaller structs, of course). [Here](https://godbolt.org/z/dcW6rnMG3) is a compiler explorer with 2 examples. Let me know if there is anything more I could add. Since register returns only happen for structs up to the size of 2 registers, I figured testing the pivot value (8 bytes) would be most critical.
Rollup merge of #145382 - winstonallo:reg-struct-return-asm-test, r=tgross35 Add assembly test for `-Zreg-struct-return` option r? `@tgross35` As discussed in #145309 with `@tgross35` and `@ojeda,` I added assembly tests for the `-Zreg-struct-return` option verifying that it changes the ABI from hidden pointer to register-return on x86_32. The test covers: - Direct struct construction, showing register return vs hidden pointer - External function calls returning structs, showing ABI mismatch handling Different memory layouts affect ABI mismatch handling, but register returns use the same register allocation regardless of struct field layout (apart from the fact that they use smaller registers for smaller structs, of course). [Here](https://godbolt.org/z/dcW6rnMG3) is a compiler explorer with 2 examples. Let me know if there is anything more I could add. Since register returns only happen for structs up to the size of 2 registers, I figured testing the pivot value (8 bytes) would be most critical.
This fixes the issue where
-Zregparm=N
was not working correctly when calling LLVM intrinsicsBy default on
x86-32
, arguments are passed on the stack. The-Zregparm=N
flag allows the firstN
arguments to be passed in registers instead.When calling intrinsics like
memset
, LLVM still passes parameters on the stack, which prevents optimizations like tail calls.As proposed by @tgross35, I fixed this by setting the
NumRegisterParameters
LLVM module flag toN
when the-Zregparm=N
is set.Here is a before/after compiler explorer.
Here is the final result for the code snippet in the original issue:
Fixes: #145271