On Tue, 22 Sep 2026, Jakub Jelinek wrote: > Hi! > > 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). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Richard. > 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. > > --- a/gcc/builtins.cc 2026-09-16 22:17:08.702383790 +0200 > +++ b/gcc/builtins.cc 2026-09-21 12:48:35.777166119 +0200 > @@ -6949,8 +6949,7 @@ expand_builtin_atomic_fetch_op (machine_ > { > rtx val, mem, ret; > enum memmodel model; > - tree fndecl; > - tree addr; > + tree fndecl, addr, oldval; > > model = get_memmodel (CALL_EXPR_ARG (exp, 2)); > > @@ -6977,6 +6976,13 @@ expand_builtin_atomic_fetch_op (machine_ > > 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 > @@ -6993,6 +6999,7 @@ expand_builtin_atomic_fetch_op (machine_ > /* 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, > @@ -7072,6 +7079,9 @@ expand_ifn_atomic_bit_test_and (gcall *c > 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); > --- a/gcc/testsuite/gcc.dg/pr127492.c 2026-09-21 13:41:47.160775175 +0200 > +++ b/gcc/testsuite/gcc.dg/pr127492.c 2026-09-21 13:48:58.216043364 +0200 > @@ -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 (); > +} > > Jakub > > -- Richard Biener <[email protected]> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)
