rs6000: Add long long support and fix 32 bit failures for __builtin_ppc_atomic_cas_local [PR124800]

Message ID 20260408023615.653320-1-avinashd@linux.ibm.com
State New
Headers
Series rs6000: Add long long support and fix 32 bit failures for __builtin_ppc_atomic_cas_local [PR124800] |

Commit Message

Avinash Jayakar April 8, 2026, 2:36 a.m. UTC
  From: Avinash Jayakar <avinashd@gcc.gnu.org>

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

Regtested on powerpc64le-linux-gnu with no regressions, ok for trunk?

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.

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         |  4 +++
 .../gcc.target/powerpc/acmp-tst-32-fail.c     | 18 ++++++++++++
 .../gcc.target/powerpc/acmp-tst-32.c          | 29 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/acmp-tst.c   |  5 +++-
 6 files changed, 69 insertions(+), 4 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
  

Comments

Surya Kumari Jangala April 8, 2026, 4:06 p.m. UTC | #1
Hi Avinash,

On 08/04/26 8:06 AM, Avinash Jayakar wrote:
> From: Avinash Jayakar <avinashd@gcc.gnu.org>
> 
> 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.
> 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.
> 
> Regtested on powerpc64le-linux-gnu with no regressions, ok for trunk?

Please bootstrap and regtest on powerpc64 too.

> 
> 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.
> 
> gcc/testsuite/ChangeLog:
> 	PR target/124800
> 	* gcc.target/powerpc/acmp-tst.c: Run only for 64 bit or where
> 	__int128 is supported.

Well, technically we haven't specified {dg-require-effective-target lp64}.
But of course right now __int128 is only supported for 64bit mode.
Given that you have split the tests into 32bit & 64bit mode, and because
we want this test to run only in 64bit mode, I think it is
better to add {dg-require-effective-target lp64} instead of
{dg-require-effective-target int128}.

> 	* 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         |  4 +++
>  .../gcc.target/powerpc/acmp-tst-32-fail.c     | 18 ++++++++++++
>  .../gcc.target/powerpc/acmp-tst-32.c          | 29 +++++++++++++++++++
>  gcc/testsuite/gcc.target/powerpc/acmp-tst.c   |  5 +++-
>  6 files changed, 69 insertions(+), 4 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..6ee90c0f8c7 100644
> --- a/gcc/config/rs6000/rs6000-overload.def
> +++ b/gcc/config/rs6000/rs6000-overload.def
> @@ -96,6 +96,10 @@
>      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 (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 (vsq *, vsq *, vsq *, 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);
> 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..c466d7bb18e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +#define TESTS \
> +  X(signed long long, sdi) \
> +  X(unsigned long long, udi)
> +
> +#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
> +
> +/* { dg-excess-errors "This test is expected to fail on 32-bit" { target ilp32 } } */
> 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..6763cee5ff8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
> @@ -0,0 +1,29 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +#define TESTS \

Using #defines is a good way to get a compact test case, but it is better to expand
all the individual tests so that in case of an issue, it will be easier to
debug, do a visual inspection of the test even, without having to first get
the preprocessed file.

-Surya

> +  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)
> +
> +#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
> +
> +/* { 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..27c98c37acf 100644
> --- a/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> @@ -1,4 +1,5 @@
>  /* { dg-do compile } */
> +/* { dg-require-effective-target int128 } */
>  /* { dg-options "-O2" } */
>  
>  #define TESTS \
> @@ -13,6 +14,8 @@
>    X(long, di) \
>    X(signed long, sdi) \
>    X(unsigned long, udi) \
> +  X(signed long long, sdi2) \
> +  X(unsigned long long, udi2) \
>    X(vector signed __int128, sti) \
>    X(vector unsigned __int128, uti)
>  
> @@ -28,5 +31,5 @@ TESTS
>  /* { 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 {\mldarx +[0-9]+,[0-9]+,[0-9]+,1} 5 } } */
>  /* { dg-final { scan-assembler-times {\mlqarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } */
  
Manjunath S Matti April 9, 2026, 1:41 p.m. UTC | #2
Hi Avinash,

On 08/04/26 8:06 am, Avinash Jayakar wrote:
> From: Avinash Jayakar <avinashd@gcc.gnu.org>
>
> 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.
> 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.
>
> Regtested on powerpc64le-linux-gnu with no regressions, ok for trunk?
>
> 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.
>
> 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         |  4 +++
>   .../gcc.target/powerpc/acmp-tst-32-fail.c     | 18 ++++++++++++
>   .../gcc.target/powerpc/acmp-tst-32.c          | 29 +++++++++++++++++++
>   gcc/testsuite/gcc.target/powerpc/acmp-tst.c   |  5 +++-
>   6 files changed, 69 insertions(+), 4 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");

Your Error message is a generic string that doesn't specify which type 
is problematic.

As a suggestion, can we have a more meaningful or specific error message

" long long not supported in 32-bit mode for __buitin_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..6ee90c0f8c7 100644
> --- a/gcc/config/rs6000/rs6000-overload.def
> +++ b/gcc/config/rs6000/rs6000-overload.def
> @@ -96,6 +96,10 @@
>       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 (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 (vsq *, vsq *, vsq *, 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);
> 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..c466d7bb18e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +#define TESTS \
> +  X(signed long long, sdi) \
> +  X(unsigned long long, udi)
> +
> +#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
> +
> +/* { dg-excess-errors "This test is expected to fail on 32-bit" { target ilp32 } } */
> 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..6763cee5ff8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
> @@ -0,0 +1,29 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target ilp32 } */
> +/* { dg-options "-O2 -m32" } */
> +
> +#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)
> +
> +#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
> +
> +/* { 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..27c98c37acf 100644
> --- a/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> +++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
> @@ -1,4 +1,5 @@
>   /* { dg-do compile } */
> +/* { dg-require-effective-target int128 } */
>   /* { dg-options "-O2" } */
>   
>   #define TESTS \
> @@ -13,6 +14,8 @@
>     X(long, di) \
>     X(signed long, sdi) \
>     X(unsigned long, udi) \
> +  X(signed long long, sdi2) \
> +  X(unsigned long long, udi2) \
>     X(vector signed __int128, sti) \
>     X(vector unsigned __int128, uti)
>   
> @@ -28,5 +31,5 @@ TESTS
>   /* { 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 {\mldarx +[0-9]+,[0-9]+,[0-9]+,1} 5 } } */
>   /* { dg-final { scan-assembler-times {\mlqarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } */


Thanks,

Manjunath S Matti
  
Michael Meissner April 10, 2026, 3:54 a.m. UTC | #3
On Wed, Apr 08, 2026 at 08:06:15AM +0530, Avinash Jayakar wrote:
> From: Avinash Jayakar <avinashd@gcc.gnu.org>
> 
> 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.
> 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.
> 
> Regtested on powerpc64le-linux-gnu with no regressions, ok for trunk?

This looks ok when GCC 17 opens up, and for backporting to GCC 16 after
GCC 16.1 ships, providing you did a bootstrap build on a big endian
PowerPC system that has 32-bit support enabled for running the tests.
  

Patch

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..6ee90c0f8c7 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -96,6 +96,10 @@ 
     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 (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 (vsq *, vsq *, vsq *, 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);
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..c466d7bb18e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32-fail.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -m32" } */
+
+#define TESTS \
+  X(signed long long, sdi) \
+  X(unsigned long long, udi)
+
+#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
+
+/* { dg-excess-errors "This test is expected to fail on 32-bit" { target ilp32 } } */
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..6763cee5ff8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst-32.c
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -m32" } */
+
+#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)
+
+#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
+
+/* { 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..27c98c37acf 100644
--- a/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
+++ b/gcc/testsuite/gcc.target/powerpc/acmp-tst.c
@@ -1,4 +1,5 @@ 
 /* { dg-do compile } */
+/* { dg-require-effective-target int128 } */
 /* { dg-options "-O2" } */
 
 #define TESTS \
@@ -13,6 +14,8 @@ 
   X(long, di) \
   X(signed long, sdi) \
   X(unsigned long, udi) \
+  X(signed long long, sdi2) \
+  X(unsigned long long, udi2) \
   X(vector signed __int128, sti) \
   X(vector unsigned __int128, uti)
 
@@ -28,5 +31,5 @@  TESTS
 /* { 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 {\mldarx +[0-9]+,[0-9]+,[0-9]+,1} 5 } } */
 /* { dg-final { scan-assembler-times {\mlqarx +[0-9]+,[0-9]+,[0-9]+,1} 2 } } */