llvm / llvm/llvm-project

clang emits a redundant stack round-trip for a volatile struct assignment from a non-volatile local

Open
#217,779 1 comment 0 reactions 0 assignees View on GitHub
clang:codegen
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.