Open
Description
Example code:
#[repr(C)]
pub struct ThreeFields<'a> {
a: &'a [u32],
b: &'a [u32],
c: &'a [u32],
}
#[inline(always)]
pub fn should_be_no_op(val: ThreeFields) -> ThreeFields {
ThreeFields {
a: val.a,
b: val.b,
c: val.c,
}
}
pub fn sum_slices_1(val: ThreeFields) -> u32 {
sum(&val)
}
pub fn sum_slices_2(val: ThreeFields) -> u32 {
let val = should_be_no_op(val);
sum(&val)
}
#[inline(never)]
pub fn sum(val: &ThreeFields) -> u32 {
val.a.iter().sum::<u32>() + val.b.iter().sum::<u32>() + val.c.iter().sum::<u32>()
}
In rustc 1.84 stable this generates a number of moves that I don't think need to be there, especially when inlining:
example::sum_slices_1::hc2a0527df8a4985d:
jmp qword ptr [rip + example::sum::h228167780f08fdbb@GOTPCREL]
example::sum_slices_2::hfa5e09ed5de6d084:
sub rsp, 56
movups xmm0, xmmword ptr [rdi]
movups xmm1, xmmword ptr [rdi + 16]
movups xmm2, xmmword ptr [rdi + 32]
movups xmmword ptr [rsp + 8], xmm0
movups xmmword ptr [rsp + 24], xmm1
movups xmmword ptr [rsp + 40], xmm2
lea rdi, [rsp + 8]
call qword ptr [rip + example::sum::h228167780f08fdbb@GOTPCREL]
add rsp, 56
ret
See https://rust.godbolt.org/z/erxfM53Kq
While this is a pretty pointless example, this comes up in situations where you might want to convert a tuple of slices into a struct of slices in order to assign names to the tuple members (I've been running into these issues working on gecs).