clang emits a redundant stack round-trip for a volatile struct assignment from a non-volatile local
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Compiling this C code with `clang -S -o - -Os -target arm64-apple-macosx`:
```c++
volatile struct st {
unsigned value;
} x;
void foo(void) {
struct st s = { 123 };
x = s;
}
```
produces:
```asm
_foo:
sub sp, sp, #16
mov w8, #123
str w8, [sp, #12]
ldr w8, [sp, #12]
adrp x9, _x@PAGE
str w8, [x9, _x@PAGEOFF]
add sp, sp, #16
ret
```
The store to and load from the stack slot (`str w8, [sp, #12]` / `ldr w8, [sp, #12]`) are unnecessary. clang could move the constant 123 into a register and store it directly to `x`, without going through the stack slot in between.
`x = s` is a struct copy where the destination (`x`) is volatile-qualified but the source (`s`) is a plain, non-volatile local. clang's frontend lowers the struct copy to a call to `@llvm.memcpy`, but `@llvm.memcpy` takes only a single boolean flag that controls volatility for both the destination and the source (https://llvm.org/docs/LangRef.html#llvm-memcpy-intrinsic). clang computes that flag as `dest.isVolatile() || src.isVolatile()`, so it passes `i1 true` to the second `@llvm.memcpy` call below, even though only the destination (`x`) is actually volatile:
```llvm
define void @foo() {
entry:
%s = alloca %struct.st, align 4
call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 4 @__const.foo.s, i64 4, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr align 4 @x, ptr align 4 %s, i64 4, i1 true)
ret void
}
```
Contributor guide
Research direction
Start with Clang's lowering of the `x = s` struct copy and the `@llvm.memcpy` volatility calculation described in the report. Reproduce with the provided `clang -S -o - -Os -target arm64-apple-macosx` command, then verify that the generated assembly no longer performs the unnecessary stack store and reload while preserving volatile-destination behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cpp
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100