On Thu, Sep 24, 2026 at 11:18 AM Dimitar Dimitrov <[email protected]> wrote:
>
> On Tue, Sep 22, 2026 at 10:17:01AM +0200, 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?
> >
> > 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
>
> Hi Jakub,
>
> Runtime target check is missing, which causes test fails on simple
> targets like pru-unknown-elf where long long atomics are not supported.
>
> Do you think the following would be a suitable solution? It seems to
> work for x86_64 and pru-unknown-elf:
>
> /* { dg-additional-options "-DT_INT128" { target sync_int_128_runtime } } */
This might be the wrong choice. Since that is only set for
loongarch64. Because the runtime is there with libatomic_available if
int128 is supported too.
So maybe there needs to have some new target support here or something
different.
> /* { dg-additional-options "-DT_LONGLONG" { target sync_long_long_runtime } }
> */
>
> #ifdef T_INT128
> #define T __int128
> #elif defined(T_LONGLONG)
> #define T long long
> #else
> #define T float
int rather than float
> #endif
>
> T v = 1;
>
> int
> main ()
> {
> #if defined(T_INT128) || defined(T_LONGLONG)
> T r = __atomic_add_fetch (&v, v, __ATOMIC_RELAXED);
> if (r != 2 || v != 2)
> __builtin_abort ();
> #endif
> return 0;
> }
>
>
> > +T v = 1;
> > +
> > +int
> > +main ()
> > +{
> > + T r = __atomic_add_fetch (&v, v, __ATOMIC_RELAXED);
> > + if (r != 2 || v != 2)
> > + __builtin_abort ();
>
> return is missing, so program could exit with
With C11 (and above), main has an implicit return. GCC defaults
(including in the testsuite) as C23. So this part is not needed to
change.
>
> Regards,
> Dimitar
> > +}
> >
> > Jakub
> >