https://gcc.gnu.org/g:090a6cebe5a22843f08030dae1855bd1cd72a07c
commit r14-12929-g090a6cebe5a22843f08030dae1855bd1cd72a07c Author: Jakub Jelinek <[email protected]> Date: Tue Sep 22 14:58:22 2026 +0200 builtins: Fix further fallback of atomic builtins [PR127492] This is a continuation of the PR127336 problem, just in a different file. If TER results in val being expanded as a MEM, we need to force it into a register before the atomic operation (and as a bonus for expand_builtin_atomic_fetch_op even better reuse it also for the atomic call itself). 2026-09-22 Jakub Jelinek <[email protected]> PR middle-end/127492 * builtins.cc (expand_builtin_atomic_fetch_op): Force val into a pseudo if updates to mem could change its value. (expand_ifn_atomic_bit_test_and): Likewise. * gcc.dg/pr127492.c: New test. Reviewed-by: Richard Biener <[email protected]> (cherry picked from commit 325646488a306c36c28e84260b4dd551bd30a47f) Diff: --- gcc/builtins.cc | 14 ++++++++++++-- gcc/testsuite/gcc.dg/pr127492.c | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 8cd8e80a11f8..6f006a1016bc 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -6898,8 +6898,7 @@ expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target, { rtx val, mem, ret; enum memmodel model; - tree fndecl; - tree addr; + tree fndecl, addr, oldval; model = get_memmodel (CALL_EXPR_ARG (exp, 2)); @@ -6926,6 +6925,13 @@ expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target, gcc_assert (TREE_OPERAND (addr, 0) == fndecl); TREE_OPERAND (addr, 0) = builtin_decl_explicit (ext_call); + oldval = CALL_EXPR_ARG (exp, 1); + + if (!ignore && reg_overlap_mentioned_p (mem, val)) + { + val = force_reg (mode, val); + CALL_EXPR_ARG (exp, 1) = make_tree (TREE_TYPE (oldval), val); + } /* If we will emit code after the call, the call cannot be a tail call. If it is emitted as a tail call, a barrier is emitted after it, and @@ -6942,6 +6948,7 @@ expand_builtin_atomic_fetch_op (machine_mode mode, tree exp, rtx target, /* Then issue the arithmetic correction to return the right result. */ if (!ignore) { + CALL_EXPR_ARG (exp, 1) = oldval; if (code == NOT) { ret = expand_simple_binop (mode, AND, ret, val, NULL_RTX, true, @@ -7021,6 +7028,9 @@ expand_ifn_atomic_bit_test_and (gcall *call) if (maybe_expand_insn (icode, 5, ops)) return; + if (reg_overlap_mentioned_p (mem, val)) + val = force_reg (mode, val); + rtx bitval = val; val = expand_simple_binop (mode, ASHIFT, const1_rtx, val, NULL_RTX, true, OPTAB_DIRECT); diff --git a/gcc/testsuite/gcc.dg/pr127492.c b/gcc/testsuite/gcc.dg/pr127492.c new file mode 100644 index 000000000000..89c747602123 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr127492.c @@ -0,0 +1,19 @@ +/* PR middle-end/127492 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-latomic" { target libatomic_available } } */ + +#ifdef __SIZEOF_INT128__ +#define T __int128 +#else +#define T long long +#endif +T v = 1; + +int +main () +{ + T r = __atomic_add_fetch (&v, v, __ATOMIC_RELAXED); + if (r != 2 || v != 2) + __builtin_abort (); +}
