https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113282
Bug ID: 113282 Summary: RISC-V non-atomic union store/load reordering Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: patrick at rivosinc dot com Target Milestone: --- I'm not sure if this is a bug or a valid optimization. Posting this here to educate myself :) Testcase: union { long c; int b; } e; int f; int *g = &e.b; long *h = &e.c; int main() { *g = 1; if (*h == 1) return 0; else return 1; } risc-v -O2: main: lui a5,%hi(h) ld a5,%lo(h)(a5) ld a0,0(a5) lui a5,%hi(g) ld a5,%lo(g)(a5) << Load li a4,1 addi a0,a0,-1 snez a0,a0 sw a4,0(a5) << Store pushed below the load ret f: .zero 4 .zero 4 e: .zero 8 h: .dword e g: .dword e My educated guess is that since the operations aren't marked as atomic, the compiler is free to ignore the dependency and optimize the load before the store. After marking the ops as atomic: union { long c; int b; } e; int f; int *g = &e.b; long *h = &e.c; int main() { __atomic_store_n(g, 1, __ATOMIC_RELAXED); if (__atomic_load_n(h, __ATOMIC_RELAXED) == 1) return 0; else return 1; } The problem goes away: main: lui a5,%hi(g) ld a5,%lo(g)(a5) li a4,1 sw a4,0(a5) << Store remains above the load lui a5,%hi(h) ld a5,%lo(h)(a5) ld a0,0(a5) << Load addi a0,a0,-1 snez a0,a0 ret f: .zero 4 .zero 4 e: .zero 8 h: .dword e g: .dword e Is that a correct line of reasoning? On x86 this problem doesn't manifest so it's also possibly a risc-v bug.