https://gcc.gnu.org/g:48930ecbe15f90ad6f3201de8dbec6df2c8de208

commit r16-9150-g48930ecbe15f90ad6f3201de8dbec6df2c8de208
Author: Jeevitha <[email protected]>
Date:   Mon Jun 22 15:16:19 2026 -0500

    rs6000: Add Future ISA compare and swap equal AMO operations [RFC02689]
    
    This patch adds support for compare-and-swap-equal atomic memory
    operations that may be added to a future PowerPC processor. Note that
    the names of these functions may change in the future.
    
    Add _AMO_LD_CS_EQ to the _AMO_LD enum and define four new
    compare-and-swap equal helper functions, all guarded by _ARCH_FUTURE.
    For non-Future targets, provide error-attribute stubs to emit a
    compile-time diagnostic.
    
    2026-06-09  Jeevitha Palanisamy  <[email protected]>
    
    gcc/
            * config/rs6000/amo.h (_AMO_LD): Add _AMO_LD_CS_EQ enumerator, 
gated on
            _ARCH_FUTURE.
            (amo_lwat_cas_eq, amo_lwat_scas_eq, amo_ldat_cas_eq,
            amo_ldat_scas_eq): New compare-and-swap equal helper functions.
            (_AMO_ERR_CMPSWP): New macro for error-attribute stubs on non-Future
            targets.
            * doc/extend.texi (PowerPC Atomic Memory Operation Functions): 
Document
            new functions.
    
    gcc/testsuite/
            * gcc.target/powerpc/amo8.c: New test.
            * gcc.target/powerpc/amo9.c: New test.
    
    (cherry picked from commit f5e868161a067809c80517de5f4e836253bbd1d9)

Diff:
---
 gcc/config/rs6000/amo.h                 | 25 ++++++++++++++-
 gcc/doc/extend.texi                     | 18 +++++++++++
 gcc/testsuite/gcc.target/powerpc/amo8.c | 36 +++++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/amo9.c | 57 +++++++++++++++++++++++++++++++++
 4 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/gcc/config/rs6000/amo.h b/gcc/config/rs6000/amo.h
index 5b03cdefe83e..549026b58745 100644
--- a/gcc/config/rs6000/amo.h
+++ b/gcc/config/rs6000/amo.h
@@ -43,7 +43,10 @@ enum _AMO_LD {
   _AMO_LD_UMIN         = 0x06,         /* Fetch and Unsigned Minimum.  */
   _AMO_LD_SMIN         = 0x07,         /* Fetch and Signed Minimum.  */
   _AMO_LD_SWAP         = 0x08,         /* Swap.  */
-  _AMO_LD_CS_NE                = 0x10,         /* Compare and Swap Not Equal.  
*/
+  _AMO_LD_CS_NE        = 0x10,         /* Compare and Swap Not Equal.  */
+#ifdef _ARCH_FUTURE
+  _AMO_LD_CS_EQ        = 0x11,         /* Compare and Swap Equal.  */
+#endif
   _AMO_LD_INC_BOUNDED  = 0x18,         /* Fetch and Increment Bounded.  */
   _AMO_LD_INC_EQUAL    = 0x19,         /* Fetch and Increment Equal.  */
   _AMO_LD_DEC_BOUNDED  = 0x1C          /* Fetch and Decrement Bounded.  */
@@ -159,6 +162,26 @@ _AMO_LD_INCREMENT (amo_ldat_sinc_eq,      int64_t, "ldat", 
_AMO_LD_INC_EQUAL)
 _AMO_LD_INCREMENT (amo_ldat_sinc_bounded, int64_t, "ldat", _AMO_LD_INC_BOUNDED)
 _AMO_LD_DECREMENT (amo_ldat_sdec_bounded, int64_t, "ldat", _AMO_LD_DEC_BOUNDED)
 
+/* Future specific compare-and-swap equal operations.  */
+#ifdef _ARCH_FUTURE
+_AMO_LD_CMPSWP (amo_lwat_cas_eq,  uint32_t, "lwat", _AMO_LD_CS_EQ)
+_AMO_LD_CMPSWP (amo_lwat_scas_eq, int32_t,  "lwat", _AMO_LD_CS_EQ)
+_AMO_LD_CMPSWP (amo_ldat_cas_eq,  uint64_t, "ldat", _AMO_LD_CS_EQ)
+_AMO_LD_CMPSWP (amo_ldat_scas_eq, int64_t,  "ldat", _AMO_LD_CS_EQ)
+#else /* ! _ARCH_FUTURE */
+/* Dummy declarations with GCC error attribute: Triggers error on use.  */
+#define _AMO_ERR_CMPSWP(NAME, TYPE)                                     \
+extern TYPE                                                             \
+NAME (TYPE *_ADDR, TYPE _COND, TYPE _VALUE)                             \
+  __attribute__ ((error (#NAME " requires ISA<future>; not available on" \
+                              " ISA 3.1 or earlier")));
+_AMO_ERR_CMPSWP (amo_lwat_cas_eq,  uint32_t)
+_AMO_ERR_CMPSWP (amo_lwat_scas_eq, int32_t)
+_AMO_ERR_CMPSWP (amo_ldat_cas_eq,  uint64_t)
+_AMO_ERR_CMPSWP (amo_ldat_scas_eq, int64_t)
+#undef _AMO_ERR_CMPSWP
+#endif
+
 /* Enumeration of the STWAT/STDAT sub-opcodes.  */
 enum _AMO_ST {
   _AMO_ST_ADD          = 0x00,         /* Store Add.  */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7580a49e0f13..5f8aa3575e92 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -27027,6 +27027,24 @@ void amo_stdat_smin (int64_t *, int64_t);
 void amo_stdat_stwin (int64_t *, int64_t);
 @end smallexample
 
+Future ISA of the PowerPC added new atomic memory operation (AMO) instructions.
+
+The AMO functions described in this section may be available on future PowerPC
+processors. At present, these functions exist to allow testing of new
+instructions. There is no guarantee that these instructions will actually be
+implemented.
+
+The functions supported are:
+
+@smallexample
+#include <amo.h>
+
+uint32_t amo_lwat_cas_eq  (uint32_t *, uint32_t, uint32_t);
+int32_t  amo_lwat_scas_eq (int32_t *, int32_t, int32_t);
+uint64_t amo_ldat_cas_eq  (uint64_t *, uint64_t, uint64_t);
+int64_t  amo_ldat_scas_eq (int64_t *, int64_t, int64_t);
+@end smallexample
+
 @node PowerPC Matrix-Multiply Assist Built-in Functions
 @subsection PowerPC Matrix-Multiply Assist Built-in Functions
 ISA 3.1 of the PowerPC added new Matrix-Multiply Assist (MMA) instructions.
diff --git a/gcc/testsuite/gcc.target/powerpc/amo8.c 
b/gcc/testsuite/gcc.target/powerpc/amo8.c
new file mode 100644
index 000000000000..f553bac13466
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/amo8.c
@@ -0,0 +1,36 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+
+#include <amo.h>
+#include <stdint.h>
+
+/* Test whether the compiler generates expected code for the ISA <future> AMO
+   (atomic memory operations) functions  */
+
+uint32_t
+do_lw_cs_eq (uint32_t *mem, uint32_t cond, uint32_t value)
+{
+  return amo_lwat_cas_eq (mem, cond, value);
+}
+
+int32_t
+do_lw_scs_eq (int32_t *mem, int32_t cond, int32_t value)
+{
+  return amo_lwat_scas_eq (mem, cond, value);
+}
+
+uint64_t
+do_ld_cs_eq (uint64_t *mem, uint64_t cond, uint64_t value)
+{
+  return amo_ldat_cas_eq (mem, cond, value);
+}
+
+int64_t
+do_ld_scs_eq (int64_t *mem, int64_t cond, int64_t value)
+{
+  return amo_ldat_scas_eq (mem, cond, value);
+}
+
+/* { dg-final { scan-assembler-times {\mlwat\M}  2 } } */
+/* { dg-final { scan-assembler-times {\mldat\M}  2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/amo9.c 
b/gcc/testsuite/gcc.target/powerpc/amo9.c
new file mode 100644
index 000000000000..e24dde405248
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/amo9.c
@@ -0,0 +1,57 @@
+/* { dg-do run { target { lp64 } } } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+/* { dg-require-effective-target powerpc_future_hw } */
+
+#include <amo.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+
+/* Test whether the compiler generates expected output for the Future ISA amo
+   (atomic memory operations) functions  */
+
+int
+main (void)
+{
+  static uint32_t u32_test1_mem = 100;
+  static uint32_t u32_test1_cond = 100;
+  static uint32_t u32_test1_value = 250;
+  static uint32_t u32_test1_expected_result = 100;
+  static uint32_t u32_test1_actual_result;
+  static uint32_t u32_test2_mem = 100;
+  static uint32_t u32_test2_cond = 200;
+  static uint32_t u32_test2_value = 250;
+  static uint32_t u32_test2_expected_result = 100;
+  static uint32_t u32_test2_actual_result;
+  static uint64_t u64_mem = 300;
+  static uint64_t u64_cond = 300;
+  static uint64_t u64_value = 250;
+  static uint64_t u64_expected_result = 300;
+  static uint64_t u64_actual_result;
+
+  u32_test1_actual_result = amo_lwat_cas_eq (&u32_test1_mem,
+                                            u32_test1_cond, u32_test1_value);
+  u32_test2_actual_result = amo_lwat_cas_eq (&u32_test2_mem,
+                                            u32_test2_cond, u32_test2_value);
+  u64_actual_result = amo_ldat_cas_eq (&u64_mem, u64_cond, u64_value);
+
+  if (u32_test1_mem != u32_test1_value)
+    abort ();
+
+  if (u32_test1_actual_result != u32_test1_expected_result)
+    abort ();
+
+  if (u32_test2_mem != u32_test2_expected_result)
+    abort ();
+
+  if (u32_test2_actual_result != u32_test2_expected_result)
+    abort ();
+
+  if (u64_mem != u64_value)
+    abort ();
+
+  if (u64_actual_result != u64_expected_result)
+    abort ();
+
+  return 0;
+}

Reply via email to