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]>

Reply via email to