Closed
Description
Rust currently doesn't pass vectors of floats by vector register.
This should be able to be passed by vector registers:
pub struct Stats { x: f32, y: f32, z: f32, q: f32 }
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, q: a.q + b.q };
}
But in Rust 1.47 it uses the stack:
example::sum_rust:
mov rax, rdi
movups xmm0, xmmword ptr [rsi]
movups xmm1, xmmword ptr [rdx]
addps xmm1, xmm0
movups xmmword ptr [rdi], xmm1
ret
Post 1.47, it is packed into integer registers (see this issue: #85265):
example::sum_rust:
movss xmm0, dword ptr [rdi]
movss xmm1, dword ptr [rdi + 4]
addss xmm0, dword ptr [rsi]
addss xmm1, dword ptr [rsi + 4]
movsd xmm2, qword ptr [rdi + 8]
movsd xmm3, qword ptr [rsi + 8]
addps xmm3, xmm2
movd eax, xmm0
movd ecx, xmm1
movd esi, xmm3
shufps xmm3, xmm3, 229
movd edx, xmm3
shl rdx, 32
or rdx, rsi
shl rcx, 32
or rax, rcx
ret
This issue should be fixed by #93405 and should bring it back to pre 1.48.
But ideally it should be optimized to:
example::sum_rust:
addps xmm1, xmm0
ret
@dotdash mentions in #85265 that this is due to Rust not using the proper types on the LLVM IR level: #85265 (comment)
EDIT:
Clang is able to use this optimization in a similar case:
struct Foo
{
float bar1;
float bar2;
float bar3;
float bar4;
};
Foo sum_cpp(Foo foo1, Foo foo2)
{
Foo foo3;
foo3.bar1 = foo1.bar1 + foo2.bar1;
foo3.bar2 = foo1.bar2 + foo2.bar2;
foo3.bar3 = foo1.bar3 + foo2.bar3;
foo3.bar4 = foo1.bar4 + foo2.bar4;
return foo3;
}
Gets turned into:
sum_cpp(Foo, Foo): # @sum_cpp(Foo, Foo)
addps xmm0, xmm2
addps xmm1, xmm3
ret
Metadata
Metadata
Assignees
Labels
No labels