Skip to content

Large parameters are copied to stack even in trivial wrappers #91521

Open
@scottmcm

Description

@scottmcm

I tried this code: https://rust.godbolt.org/z/j13WbYT6o

extern "Rust" {
    fn bar(x: [String; 100]) -> usize;
}

pub unsafe fn foo(x: [String; 100]) -> usize {
    bar(x)
}

I expected to see this happen:
Everything should be already set up on the stack appropriately to just call bar immediately on entering foo.

Instead, this happened:
It copies the 2400 bytes to stack, then calls bar with the pointer to that stack copy

example::foo:
        push    rbx
        sub     rsp, 2400
        mov     rsi, rdi
        mov     rbx, rsp
        mov     edx, 2400
        mov     rdi, rbx
        call    qword ptr [rip + memcpy@GOTPCREL]
        mov     rdi, rbx
        call    qword ptr [rip + bar@GOTPCREL]
        add     rsp, 2400
        pop     rbx
        ret

Since at the ABI level that's passed as a pointer, I suspect this is more a "how rustc emits stuff" than an LLVM bug -- maybe there's some https://llvm.org/docs/LangRef.html#parameter-attributes we could set that would help. Or maybe the unnecessary double-move in MIR is part of the problem:

fn foo(_1: [String; 100]) -> usize {
    debug x => _1;                       // in scope 0 at /app/example.rs:5:19: 5:20
    let mut _0: usize;                   // return place in scope 0 at /app/example.rs:5:40: 5:45
    let mut _2: [std::string::String; 100]; // in scope 0 at /app/example.rs:6:9: 6:10

    bb0: {
        StorageLive(_2);                 // scope 0 at /app/example.rs:6:9: 6:10
        _2 = move _1;                    // scope 0 at /app/example.rs:6:9: 6:10
        _0 = bar(move _2) -> bb1;        // scope 0 at /app/example.rs:6:5: 6:11
    }

    bb1: {
        StorageDead(_2);                 // scope 0 at /app/example.rs:6:10: 6:11
        return;                          // scope 0 at /app/example.rs:7:2: 7:2
    }
}

Context

I was trying various things to see if I could remove some bad behaviour from array's map, which is troublesome enough that it's caveated in the docs, #87609

I had thought this was due to newtypes, as in these bugs

But since it repro'd even without the extra wrappers I figured I'd file a distinct bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.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