-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Open
Labels
A-ABIArea: Concerning the application binary interface (ABI)Area: Concerning the application binary interface (ABI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationArea: Code generationC-bugCategory: This is a bug.Category: This is a bug.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.Issue: 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.Relevant to the compiler team, which will review and decide on the PR/issue.
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
Metadata
Metadata
Assignees
Labels
A-ABIArea: Concerning the application binary interface (ABI)Area: Concerning the application binary interface (ABI)A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationArea: Code generationC-bugCategory: This is a bug.Category: This is a bug.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.Issue: 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.Relevant to the compiler team, which will review and decide on the PR/issue.