Skip to content

Small structs with many elements as function arguments seem inefficient #16506

@dotdash

Description

@dotdash

Currently, we pass everything that's smaller than a pointer as an immediate argument (except for fiexd size arrays, but that's a different issue) and everything else as non-immediate. This seems to be not quite optimal for structs like this:

#[deriving(Show)]
struct RGBA {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
}

#[inline(never)]
fn gradient(from: RGBA, to: RGBA) {
    println!("Gradient from {} to {}", from, to);
}

fn main() {
    let from = RGBA { r: 0, g: 0, b: 0, a: 0 };
    let to = RGBA { r: 255, g: 255, b: 255, a: 255 };
    gradient(from, to);
    gradient(to, from);
}

The calls end up being lowered to this:

    movl    $255, 8(%rsp)
    movl    $255, (%rsp)
    xorl    %edi, %edi
    xorl    %esi, %esi
    xorl    %edx, %edx
    xorl    %ecx, %ecx
    movl    $255, %r8d
    movl    $255, %r9d
    callq   _ZN8gradient20h9b7e3615552adffcPcaE
    movl    $0, 8(%rsp)
    movl    $0, (%rsp)
    movl    $255, %edi
    movl    $255, %esi
    movl    $255, %edx
    movl    $255, %ecx
    xorl    %r8d, %r8d
    xorl    %r9d, %r9d
    callq   _ZN8gradient20h9b7e3615552adffcPcaE

So to pass effectively 8 bytes, we need 6 registers and 16 bytes of stack.

For return values, this also means that such structs in fact isn't return as an immediate values in the eax register, but in memory. Using 4 single byte movs (maybe coalescing those into a single store is something that could be handled in LLVM, but it still seems bad that it goes through memory).

Maybe the rust ABI should be re-evaluated and we need to add casts/coercions for small structs to pass them more efficiently. Passing e.g. slices in registers instead of memory also seems like it might be a good idea. I'm far off from being an expert in this area though, so feel free to correct me if things are fine as they are.

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-slowIssue: Problems and improvements with respect to performance of generated code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions