diff options
| author | bors <bors@rust-lang.org> | 2020-09-27 02:35:11 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-09-27 02:35:11 +0000 |
| commit | 62fe055aba3ddac5e5d113920cf5fd80522104e2 (patch) | |
| tree | 4545619f936a4860e19494c8f68720e366b44e90 /src/test/codegen | |
| parent | 1ec980d225fff2346a1a631a7ffc88b37e9e18af (diff) | |
| parent | cc2ba3bd2753ec94adc93ec4aa9d8d093129cd2d (diff) | |
| download | rust-62fe055aba3ddac5e5d113920cf5fd80522104e2.tar.gz rust-62fe055aba3ddac5e5d113920cf5fd80522104e2.zip | |
Auto merge of #76986 - jonas-schievink:ret-in-reg, r=nagisa
Return values up to 128 bits in registers
This fixes https://github.com/rust-lang/rust/issues/26494#issuecomment-619506345 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
```
Diffstat (limited to 'src/test/codegen')
| -rw-r--r-- | src/test/codegen/return-value-in-reg.rs | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/test/codegen/return-value-in-reg.rs b/src/test/codegen/return-value-in-reg.rs new file mode 100644 index 00000000000..4bc0136c5e3 --- /dev/null +++ b/src/test/codegen/return-value-in-reg.rs @@ -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 } +} |
