Hi Avinash,
Instead of handling the builtin in rs6000_expand_builtin(),
another possible approach would be to do some handling in 
targetm.resolve_overloaded_builtin().
Here, we can compute the size and decide which _N variant the builtin will map 
to.
Then in the expand pass, we can generate the appropriate RTL since we know the 
size.
Since targetm.resolve_overloaded_builtin() is called only for BUILT_IN_MD 
builtins, we would
have to define a dummy builtin in the builtins.def file.

-Surya

On 10/04/26 12:38 AM, Avinash Jayakar wrote:
> Changes from v1:
> * Use complete source code instead of compact macros in test cases.
> * Use lp64 where __int128 type is needed.
> * Add __int128 overloads.
> 
> Bootstrapped and regtested on powerpc64-linux-gnu (with -m32 and -m64)
> and powerpc64le-linux-gnu, with no regressions. Ok for trunk?
> 
> Thanks,
> Avinash Jayakar
> 
> A few types were not tested with the patch
> https://gcc.gnu.org/pipermail/gcc-patches/2026-March/711326.html
> i.e., (signed/unsigned) long long, and long support in 32 bit system.
> This patch adds support for long long in 64 bit system and for long in
> 32 bit. Also only __int128 type without the 'vector' prefix was missed,
> this patch adds overloads for it.
> 
> Although the generic builtin __atomic_compare_exchange does support long
> long even in 32 bit, it does not generate larx instructions in assembly,
> and instead expands using internal function. Therefore decided not to
> support the new builtin for this type in 32 bit.
> 
> Added a few more tests for checking this failure scenario in 32 bit, and
> separated out 32 bit tests from 64 bit tests.
> 
> 2026-04-10  Avinash Jayakar  <[email protected]>
> 
> gcc/ChangeLog:
>       PR target/124800
>       * config/rs6000/rs6000-builtin.cc (rs6000_expand_builtin): Add
>       long long support. Expand using SI mode for long type in 32 bit.
>       * config/rs6000/rs6000-builtins.def: New builtins for long long.
>       * config/rs6000/rs6000-overload.def: New overloads for long
>       long and __int128.
> 
> gcc/testsuite/ChangeLog:
>       PR target/124800
>       * gcc.target/powerpc/acmp-tst.c: Run only for 64 bit or where
>       __int128 is supported.
>       * gcc.target/powerpc/acmp-tst-32-fail.c: New test.
>       * gcc.target/powerpc/acmp-tst-32.c: New test.
> ---
>  gcc/config/rs6000/rs6000-builtin.cc           |  15 +-
>  gcc/config/rs6000/rs6000-builtins.def         |   2 +
>  gcc/config/rs6000/rs6000-overload.def         |  12 +-
>  .../gcc.target/powerpc/acmp-tst-32-fail.c     |  23 +++
>  .../gcc.target/powerpc/acmp-tst-32.c          |  73 +++++++++
>  gcc/testsuite/gcc.target/powerpc/acmp-tst.c   | 147 +++++++++++++++---
>  6 files changed, 242 insertions(+), 30 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
> 
> diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
> b/gcc/config/rs6000/rs6000-builtin.cc
> index bbf60de3b1b..845dd4c1e50 100644
> --- a/gcc/config/rs6000/rs6000-builtin.cc
> +++ b/gcc/config/rs6000/rs6000-builtin.cc
> @@ -3288,7 +3288,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* 
> subtarget */,
>        || fcode == RS6000_BIF_PPC_ATOMIC_CAS_HI
>        || fcode == RS6000_BIF_PPC_ATOMIC_CAS_SI
>        || fcode == RS6000_BIF_PPC_ATOMIC_CAS_DI
> -      || fcode == RS6000_BIF_PPC_ATOMIC_CAS_TI)
> +      || fcode == RS6000_BIF_PPC_ATOMIC_CAS_TI
> +      || fcode == RS6000_BIF_PPC_ATOMIC_CAS_DI_LL)
>      {
>        machine_mode mode; // Get mode based on BIF ID (QImode, SImode, etc.)
>  
> @@ -3307,13 +3308,21 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* 
> subtarget */,
>         icode = CODE_FOR_atomic_compare_and_swap_localsi;
>         break;
>       case RS6000_BIF_PPC_ATOMIC_CAS_DI:
> -       mode = DImode;
> -       icode = CODE_FOR_atomic_compare_and_swap_localdi;
> +       mode = TARGET_32BIT ? SImode : DImode;
> +       icode = TARGET_32BIT ? CODE_FOR_atomic_compare_and_swap_localsi
> +                            : CODE_FOR_atomic_compare_and_swap_localdi;
>         break;
>       case RS6000_BIF_PPC_ATOMIC_CAS_TI:
>         mode = TImode;
>         icode = CODE_FOR_atomic_compare_and_swap_localti;
>         break;
> +     case RS6000_BIF_PPC_ATOMIC_CAS_DI_LL:
> +       if (TARGET_32BIT)
> +         error ("Invalid arguments to %qs",
> +                "__builtin_ppc_atomic_cas_local");
> +       mode = DImode;
> +       icode = CODE_FOR_atomic_compare_and_swap_localdi;
> +       break;
>       default:
>         gcc_unreachable ();
>       }
> diff --git a/gcc/config/rs6000/rs6000-builtins.def 
> b/gcc/config/rs6000/rs6000-builtins.def
> index 577c9d6c8f0..a7918b4184d 100644
> --- a/gcc/config/rs6000/rs6000-builtins.def
> +++ b/gcc/config/rs6000/rs6000-builtins.def
> @@ -255,6 +255,8 @@
>      PPC_ATOMIC_CAS_SI nothing {}
>    bool __builtin_ppc_atomic_cas_local_di (long *, long *, long *, const int, 
> const int, const int);
>      PPC_ATOMIC_CAS_DI nothing {}
> +  bool __builtin_ppc_atomic_cas_local_di_ll (long long *, long long *, long 
> long *, const int, const int, const int);
> +    PPC_ATOMIC_CAS_DI_LL nothing {}
>    bool __builtin_ppc_atomic_cas_local_ti (vsq *, vsq *, vsq *, const int, 
> const int, const int);
>      PPC_ATOMIC_CAS_TI nothing {}
>  
> diff --git a/gcc/config/rs6000/rs6000-overload.def 
> b/gcc/config/rs6000/rs6000-overload.def
> index 8f2fa978475..d2b1feadb6a 100644
> --- a/gcc/config/rs6000/rs6000-overload.def
> +++ b/gcc/config/rs6000/rs6000-overload.def
> @@ -96,10 +96,18 @@
>      PPC_ATOMIC_CAS_DI PPC_ATOMIC_CAS_SDI
>    bool __builtin_ppc_atomic_cas_local (unsigned long *, unsigned long *, 
> unsigned long *, const int, const int, const int);
>      PPC_ATOMIC_CAS_DI PPC_ATOMIC_CAS_UDI
> -  bool __builtin_ppc_atomic_cas_local (vsq *, vsq *, vsq *, const int, const 
> int, const int);
> +  bool __builtin_ppc_atomic_cas_local (signed long long *, signed long long 
> *, signed long long *, const int, const int, const int);
> +    PPC_ATOMIC_CAS_DI_LL PPC_ATOMIC_CAS_SDI_LL
> +  bool __builtin_ppc_atomic_cas_local (unsigned long long *, unsigned long 
> long *, unsigned long long *, const int, const int, const int);
> +    PPC_ATOMIC_CAS_DI_LL PPC_ATOMIC_CAS_UDI_LL
> +  bool __builtin_ppc_atomic_cas_local (signed __int128 *, signed __int128 *, 
> signed __int128 *, const int, const int, const int);
>      PPC_ATOMIC_CAS_TI PPC_ATOMIC_CAS_STI
> -  bool __builtin_ppc_atomic_cas_local (vuq *, vuq *, vuq *, const int, const 
> int, const int);
> +  bool __builtin_ppc_atomic_cas_local (unsigned __int128 *, unsigned 
> __int128 *, unsigned __int128 *, const int, const int, const int);
>      PPC_ATOMIC_CAS_TI PPC_ATOMIC_CAS_UTI
> +  bool __builtin_ppc_atomic_cas_local (vsq *, vsq *, vsq *, const int, const 
> int, const int);
> +    PPC_ATOMIC_CAS_TI PPC_ATOMIC_CAS_VSTI
> +  bool __builtin_ppc_atomic_cas_local (vuq *, vuq *, vuq *, const int, const 
> int, const int);
> +    PPC_ATOMIC_CAS_TI PPC_ATOMIC_CAS_VUTI
>  
>  [BCDADD, __builtin_bcdadd, __builtin_vec_bcdadd]
>    vsq __builtin_vec_bcdadd (vsq, vsq, const int);
> diff --git a/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c 
> b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
> new file mode 100644
> index 00000000000..07a327baf9c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +bool word_exchange_di2 (long long *ptr, long long *expected, long long * 
> desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_sdi2 (signed long long *ptr, signed long long *expected, 
> signed long long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_udi2 (unsigned long long *ptr, unsigned long long 
> *expected, unsigned long long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +/* { dg-excess-errors "This test is expected to fail on 32-bit" } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c 
> b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
> new file mode 100644
> index 00000000000..2de2972a381
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
> @@ -0,0 +1,73 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +bool word_exchange_qi (signed char *ptr, signed char *expected, signed char 
> * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_uqi (unsigned char *ptr, unsigned char *expected, 
> unsigned char * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_hi (short *ptr, short *expected, short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_shi (signed short *ptr, signed short *expected, signed 
> short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_uhi (unsigned short *ptr, unsigned short *expected, 
> unsigned short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_si (int *ptr, int *expected, int * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_ssi (signed int *ptr, signed int *expected, signed int * 
> desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_usi (unsigned int *ptr, unsigned int *expected, unsigned 
> int * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_di (long *ptr, long *expected, long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_sdi (signed long *ptr, signed long *expected, signed long 
> * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_udi (unsigned long *ptr, unsigned long *expected, 
> unsigned long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +/* { dg-final { scan-assembler-times {\mlbarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } 
> */
> +/* { dg-final { scan-assembler-times {\mlharx +[0-9]+,[0-9]+,[0-9]+,1} 3 } } 
> */
> +/* { dg-final { scan-assembler-times {\mlwarx +[0-9]+,[0-9]+,[0-9]+,1} 6 } } 
> */
> diff --git a/gcc/testsuite/gcc.target/powerpc/acmp-tst.c 
> b/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> index 6ebd2ebbc28..6f0f8518b49 100644
> --- a/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> @@ -1,32 +1,129 @@
>  /* { dg-do compile } */
> +/* { dg-require-effective-target lp64 } */
>  /* { dg-options "-O2" } */
>  
> -#define TESTS \
> -  X(signed char, qi) \
> -  X(unsigned char, uqi) \
> -  X(short, hi) \
> -  X(signed short, shi) \
> -  X(unsigned short, uhi) \
> -  X(int, si) \
> -  X(signed int, ssi) \
> -  X(unsigned int, usi) \
> -  X(long, di) \
> -  X(signed long, sdi) \
> -  X(unsigned long, udi) \
> -  X(vector signed __int128, sti) \
> -  X(vector unsigned __int128, uti)
> -
> -#define X(T, name) \
> -bool word_exchange_##name (T *ptr, T *expected, T * desired) \
> -{ \
> -  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0, \
> -                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE); \
> -}
> -
> -TESTS
> +bool word_exchange_sqi (signed char *ptr, signed char *expected, signed char 
> * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_uqi (unsigned char *ptr, unsigned char *expected, 
> unsigned char * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_hi (short *ptr, short *expected, short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_shi (signed short *ptr, signed short *expected, signed 
> short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_uhi (unsigned short *ptr, unsigned short *expected, 
> unsigned short * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_si (int *ptr, int *expected, int * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_ssi (signed int *ptr, signed int *expected, signed int * 
> desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_usi (unsigned int *ptr, unsigned int *expected, unsigned 
> int * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_di (long *ptr, long *expected, long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_sdi (signed long *ptr, signed long *expected, signed long 
> * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_udi (unsigned long *ptr, unsigned long *expected, 
> unsigned long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_di2 (long long *ptr, long long *expected, long long * 
> desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_sdi2 (signed long long *ptr, signed long long *expected, 
> signed long long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_udi2 (unsigned long long *ptr, unsigned long long 
> *expected, unsigned long long * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_ti (__int128 *ptr, __int128 *expected, __int128 * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_sti (signed __int128 *ptr, signed __int128 *expected, 
> signed __int128 * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_uti (unsigned __int128 *ptr, unsigned __int128 *expected, 
> unsigned __int128 * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_vti (vector __int128 *ptr, vector __int128 *expected, 
> vector __int128 * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_vsti (vector signed __int128 *ptr, vector signed __int128 
> *expected, vector signed __int128 * desired)
> +{
> +  return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                      __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
> +
> +bool word_exchange_vuti (vector unsigned __int128 *ptr, vector unsigned 
> __int128 *expected, vector unsigned __int128 * desired)
> +{
> +return __builtin_ppc_atomic_cas_local (ptr, expected, desired, 0,
> +                                    __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
> +}
>  
>  /* { dg-final { scan-assembler-times {\mlbarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } 
> */
>  /* { dg-final { scan-assembler-times {\mlharx +[0-9]+,[0-9]+,[0-9]+,1} 3 } } 
> */
>  /* { dg-final { scan-assembler-times {\mlwarx +[0-9]+,[0-9]+,[0-9]+,1} 3 } } 
> */
> -/* { dg-final { scan-assembler-times {\mldarx +[0-9]+,[0-9]+,[0-9]+,1} 3 } } 
> */
> -/* { dg-final { scan-assembler-times {\mlqarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } 
> */
> +/* { dg-final { scan-assembler-times {\mldarx +[0-9]+,[0-9]+,[0-9]+,1} 6 } } 
> */
> +/* { dg-final { scan-assembler-times {\mlqarx +[0-9]+,[0-9]+,[0-9]+,1} 6 } } 
> */

Reply via email to