I tried this code:
https://rust.godbolt.org/z/Yrr6h6ebq
I expected to see this happen: Rust ABI to be similar to C ABI in returning SIMD types via registers.
Instead, this happened:
On x86-64 Rust ABI returns native SIMD types like __m128i using memory pointer instead of SIMD registers on both Linux (where C and sysv64 use registers instead) and Windows (where C ABI, unfortunately, uses memory too).
On aarch64 a similar issue happens with both native SIMD types like float64x2_t and float aggregates like #[repr(C)] struct(f64, f64, f64), where C ABI uses registers and Rust ABI uses memory instead.
Similar issues exist for arguments too as shown in the reproduction.
While Rust ABI is unspecified and is free to do that, in performance-sensitive situations like tail call interpreters with every I/O register accounted for, the default ABI causes a major regression that would have been nice to not have. At least on platforms where C ABI has the expected behavior.
It is especially bad on x86-64 Linux where using all 6 GPRs for input arguments + SIMD for return value causes both return value and some input arguments to spill into memory.
I didn't find an existing identical issue and not sure if this should have been two or even three separate issues instead, so let me know if anything needs to change here.
Meta
rustc --version --verbose:
rustc 1.100.0-nightly (8fa1c96cf 2026-08-17)
binary: rustc
commit-hash: 8fa1c96cfd489e4c27654c144ae871ce2c4db6c6
commit-date: 2026-08-17
host: x86_64-unknown-linux-gnu
release: 1.100.0-nightly
LLVM version: 23.1.0
I tried this code:
https://rust.godbolt.org/z/Yrr6h6ebq
I expected to see this happen: Rust ABI to be similar to C ABI in returning SIMD types via registers.
Instead, this happened:
On x86-64
RustABI returns native SIMD types like__m128iusing memory pointer instead of SIMD registers on both Linux (whereCandsysv64use registers instead) and Windows (whereCABI, unfortunately, uses memory too).On aarch64 a similar issue happens with both native SIMD types like
float64x2_tand float aggregates like#[repr(C)] struct(f64, f64, f64), whereCABI uses registers andRustABI uses memory instead.Similar issues exist for arguments too as shown in the reproduction.
While
RustABI is unspecified and is free to do that, in performance-sensitive situations like tail call interpreters with every I/O register accounted for, the default ABI causes a major regression that would have been nice to not have. At least on platforms whereCABI has the expected behavior.It is especially bad on x86-64 Linux where using all 6 GPRs for input arguments + SIMD for return value causes both return value and some input arguments to spill into memory.
I didn't find an existing identical issue and not sure if this should have been two or even three separate issues instead, so let me know if anything needs to change here.
Meta
rustc --version --verbose: