-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #76986 - jonas-schievink:ret-in-reg, r=nagisa
Return values up to 128 bits in registers This fixes #26494 (comment) by making Rust's default ABI pass return values up to 128 bits in size in registers, just like the System V ABI. The result is that these methods from the comment linked above now generate the same code, making the Rust ABI as efficient as the `"C"` ABI: ```rust pub struct Stats { x: u32, y: u32, z: u32, } pub extern "C" fn sum_c(a: &Stats, b: &Stats) -> Stats { return Stats {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; } pub fn sum_rust(a: &Stats, b: &Stats) -> Stats { return Stats {x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; } ``` ```asm sum_rust: movl (%rsi), %eax addl (%rdi), %eax movl 4(%rsi), %ecx addl 4(%rdi), %ecx movl 8(%rsi), %edx addl 8(%rdi), %edx shlq $32, %rcx orq %rcx, %rax retq ```
- Loading branch information
Showing
3 changed files
with
52 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//! This test checks that types of up to 128 bits are returned by-value instead of via out-pointer. | ||
// compile-flags: -C no-prepopulate-passes -O | ||
// only-x86_64 | ||
|
||
#![crate_type = "lib"] | ||
|
||
pub struct S { | ||
a: u64, | ||
b: u32, | ||
c: u32, | ||
} | ||
|
||
// CHECK: define i128 @modify(%S* noalias nocapture dereferenceable(16) %s) | ||
#[no_mangle] | ||
pub fn modify(s: S) -> S { | ||
S { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c } | ||
} | ||
|
||
#[repr(packed)] | ||
pub struct TooBig { | ||
a: u64, | ||
b: u32, | ||
c: u32, | ||
d: u8, | ||
} | ||
|
||
// CHECK: define void @m_big(%TooBig* [[ATTRS:.*sret.*]], %TooBig* [[ATTRS2:.*]] %s) | ||
#[no_mangle] | ||
pub fn m_big(s: TooBig) -> TooBig { | ||
TooBig { a: s.a + s.a, b: s.b + s.b, c: s.c + s.c, d: s.d + s.d } | ||
} |