rust-lang / rust-lang/rust

Redundant memory stores with mut parameters in by-value returns

Open
#149,762 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-ABI A-codegen A-LLVM C-bug C-optimization E-needs-test I-slow T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Godbolt link
https://godbolt.org/z/W8xxse95v

Summary

When a function takes a mut parameter and returns the same type by value, the compiler generates redundant memory stores compared to using semantically equivalent let mut rebinding.

Code Examples

pub struct SomeComplexType {
    a: u64,
    b: u64,
    c: u64,
}

// Version 1: with `mut` parameter (problematic - generates redundant stores)
#[inline(never)]
pub fn with_mut_param(mut a: SomeComplexType) -> SomeComplexType {
    a.a += 10;
    a.b += 2;
    a
}

// Version 2: with `let mut` rebinding (optimal - no redundant stores)
#[inline(never)]
pub fn with_rebind(a: SomeComplexType) -> SomeComplexType {
    let mut a = a;
    a.a += 10;
    a.b += 2;
    a
}
Expected Behavior

Both functions should generate identical optimal assembly (like with_rebind), since they are semantically equivalent.

Actual Behavior

compiled with --target=riscv64gc-unknown-linux-gnu -C opt-level=3
this bug can also be seen on x86_64

example::with_rebind::h8093d7779180c3d2:
        ld      a2, 0(a1) # load a.a
        ld      a3, 8(a1) # load a.b
        ld      a1, 16(a1) # load a.c
        addi    a2, a2, 10 # a.a+=10
        addi    a3, a3, 2 # a.b+=2
        sd      a2, 0(a0) #store a.a to return
        sd      a3, 8(a0) #store a.b to return 
        sd      a1, 16(a0) #store a.c to return
        ret

example::with_mut_param::hd013a2ed7fc4bb64:
        ld      a2, 0(a1) # load a.a
        ld      a3, 8(a1) # load a.b
        ld      a4, 16(a1) # load a.c
        addi    a2, a2, 10 # a.a+=10
        addi    a3, a3, 2 # a.b+=2
        sd      a2, 0(a1) # REDUNDANT: store back to source (a.a)
        sd      a3, 8(a1) # REDUNDANT: store back to source (a.b)
        sd      a2, 0(a0) # store a.a to return 
        sd      a3, 8(a0) # store a.b to return 
        sd      a4, 16(a0) # store a.c to return
        ret
Meta

This bug exists in rustc 1.91.0 and both nightly and beta compilers at November 8

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

Reproduce the two functions from the Godbolt link with rustc 1.91.0 at opt-level=3 for riscv64gc-unknown-linux-gnu and x86_64, then compare their generated assembly. Trace where the mut-parameter version introduces the stores shown in the report and verify that the completed change produces assembly matching with_rebind without changing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.