Skip to content

Redundant memory stores with mut parameters in by-value returns #149762

@andy091203

Description

@andy091203

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ABIArea: Concerning the application binary interface (ABI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationC-bugCategory: This is a bug.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.T-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