Skip to content

Missed optimization opportunity when trivially moving struct by moving fields #135786

Open
@recatek

Description

@recatek

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).

See also: #107436 and #135787

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions