rust-lang / rust-lang/rust

Non-literal constant objects are not well optimized comparing to literal constant objects

Open
#118,557 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-optimization T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

The problem is originated from https://github.com/rust-lang/log/pull/599.

Sometimes, multiple function calls can have the same constant arguments:

pub fn test(f: fn(&[u32; 10])) {
    f(&[7; 10]);
    f(&[7; 10]);
    f(&[7; 10]);
    f(&[7; 10]);
}

Rust recognizes that these arguments are the same value, so it would create a single constant value and pass it to each function:

example::test:
        push    r14
        push    rbx
        push    rax
        mov     r14, rdi
        lea     rbx, [rip + .L__unnamed_1]
        mov     rdi, rbx
        call    r14
        mov     rdi, rbx
        call    r14
        mov     rdi, rbx
        call    r14
        mov     rdi, rbx
        mov     rax, r14
        add     rsp, 8
        pop     rbx
        pop     r14
        jmp     rax

.L__unnamed_1:
        .asciz  "\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000\000\007\000\000"

But sometimes, these constant arguments have to be computed by some additional functions:

pub fn test(f: fn(&[u32; 10])) {
    f(&[std::convert::identity(7); 10]);
    f(&[std::convert::identity(7); 10]);
    f(&[std::convert::identity(7); 10]);
    f(&[std::convert::identity(7); 10]);
}

Then the compiler can’t optimize these constant objects well as the first example, additional copying operations are generated:

.LCPI0_0:
        .long   7
        .long   7
        .long   7
        .long   7
example::test:
        push    r14
        push    rbx
        sub     rsp, 40
        mov     rbx, rdi
        movaps  xmm0, xmmword ptr [rip + .LCPI0_0]
        movaps  xmmword ptr [rsp], xmm0
        movaps  xmmword ptr [rsp + 16], xmm0
        movabs  r14, 30064771079
        mov     qword ptr [rsp + 32], r14
        mov     rdi, rsp
        call    rbx
        movaps  xmm0, xmmword ptr [rip + .LCPI0_0]
        movaps  xmmword ptr [rsp], xmm0
        movaps  xmmword ptr [rsp + 16], xmm0
        mov     qword ptr [rsp + 32], r14
        mov     rdi, rsp
        call    rbx
        movaps  xmm0, xmmword ptr [rip + .LCPI0_0]
        movaps  xmmword ptr [rsp], xmm0
        movaps  xmmword ptr [rsp + 16], xmm0
        mov     qword ptr [rsp + 32], r14
        mov     rdi, rsp
        call    rbx
        movaps  xmm0, xmmword ptr [rip + .LCPI0_0]
        movaps  xmmword ptr [rsp], xmm0
        movaps  xmmword ptr [rsp + 16], xmm0
        mov     qword ptr [rsp + 32], r14
        mov     rdi, rsp
        call    rbx
        add     rsp, 40
        pop     rbx
        pop     r14
        ret

You can see the comparison here: https://godbolt.org/z/frj9a8TG6.

Additionally, using a const value as a proxy helps:

pub fn test(f: fn(&[u32; 10])) {
    const SEVEN: u32 = std::convert::identity(7);

    f(&[SEVEN; 10]);
    f(&[SEVEN; 10]);
    f(&[SEVEN; 10]);
    f(&[SEVEN; 10]);
}

But some functions can’t be used to compute a const value, such as std::panic::Location::caller, so the method above does not always work.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust examples and the linked Godbolt comparison, then investigate how the compiler handles repeated literal and non-literal constant objects. Done means equivalent non-literal constant arguments avoid the repeated copying shown in the report, with coverage demonstrating the improved output.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.