Unnecessary copying of struct field when the same field is later overwritten
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
These functions should all produce the same assembly
https://godbolt.org/z/4c674fKxE
```c
typedef unsigned long u64;
typedef struct {
u64 x;
u64 y;
u64 z;
} Big;
// Not optimized
Big assign(Big b) {
b.x = 0;
return b;
}
Big copy_then_assign(Big b) {
Big c = b;
c.x = 0;
return c;
}
Big memcpy_then_assign(Big b) {
Big c;
__builtin_memcpy(&c, &b, sizeof(b));
c.x = 0;
return c;
}
// Optimized
Big c99_initializer(Big b) { return (Big){0, b.y, b.z}; }
Big c99_initializer2(Big b) {
Big c = {b.x, b.y, b.z};
c.x = 0;
return c;
}
Big copy_individually(Big b) {
Big c;
c.x = 0;
c.y = b.y;
c.z = b.z;
return c;
}
Big copy_individually_then_assign(Big b) {
Big c;
c.x = b.x;
c.y = b.y;
c.z = b.z;
c.x = 0;
return c;
}
```
Unoptimized assembly:
```asm
assign:
str xzr, [x0]
ldr x9, [x0, #16]
ldr q0, [x0]
str x9, [x8, #16]
str q0, [x8]
ret
```
Optimized assembly:
```asm
c99_initializer:
ldur q0, [x0, #8]
str xzr, [x8]
stur q0, [x8, #8]
ret
```
Contributor guide
Research direction
Start with the C reproducer linked on Godbolt and compare the assembly for assign, copy_then_assign, and memcpy_then_assign with the optimized initializer examples. Trace the LLVM optimization path responsible for struct copies and verify the result by checking that the affected functions avoid copying fields later overwritten while preserving the returned values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100