https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127336
--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <[email protected]>: https://gcc.gnu.org/g:be20f2a5b7887853833308617292d271be91414b commit r17-4225-gbe20f2a5b7887853833308617292d271be91414b Author: Jakub Jelinek <[email protected]> Date: Mon Sep 14 13:29:21 2026 +0200 optabs: Fix up fallback expansions of some atomic builtins [PR127336] If the val operand due to TER is a MEM (or contains a MEM) which can alias with mem (the memory atomically updated), we have various wrong-code problems in the fallback expansions. The first one can be seen on the testcase and is solved by the second/third hunks, if the backend has an instruction to atomically update in the mode and return the previous rather than the updated value, we perform non-atomic update of that value with val again after the atomic insn. If val is or overlaps with mem, we then incorrectly use an updated value rather than the original value (of course, the code is weird because it non-atomically reads first what is then atomically updated, so if some other thread modifies it, what will be the result is pretty random). This patch changes - movl v(%rip), %eax + movl v(%rip), %edx + movl %edx, %eax lock xaddl %eax, v(%rip) - addl v(%rip), %eax + addl %edx, %eax cmpl $18, %eax jne .L3 xorl %eax, %eax ret on x86_64 by forcing the val into pseudo in that case. Another problem (the last 2 hunks in optabs.cc) is if there is no named pattern for it and we fallback to compare and exchange loop. E.g. if similar testcase uses unsigned long long instead of unsigned on x86_64 -m32 -march=x86-64. Not included in testsuite because it actually "works" on uncontended variable, the bug is that val is read from memory twice, once before the loop and once inside of the loop before the cmpxchg8b instruction. So it is actually correct unless cmpxchg8b fails the first time. And the first hunk is to do the same thing on various other places that use cmpxchg fallback loop. 2026-09-14 Jakub Jelinek <[email protected]> PR middle-end/127336 * optabs.cc (maybe_emit_compare_and_swap_exchange_loop, expand_atomic_fetch_op_no_fallback, expand_atomic_fetch_op): Force val into a pseduo if it updates to mem could change its value and when using val after the atomic op or inside of a loop. * gcc.dg/pr127336.c: New test. Reviewed-by: Richard Biener <[email protected]>
