Hi All, This patch depends on the "Add PowerPC future hardware compiler support checks" patch. It will be upstreamed after the above patch is upstreamed. These changes have been bootstrapped and regression tested on powerpc64le-linux.
Changes from V3: * Moved target-supports.exp changes to separate patch. * Added respective dg flags and checks. Changes from V2: * Corrected wording in amo.h. * Added new dg-do run test. * Added powerpc_future_hw_ok object. Changes from V1: * Corrected wording in amo.h and the test file. * Added changes to extend.texi. 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-05-27 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. diff --git a/gcc/config/rs6000/amo.h b/gcc/config/rs6000/amo.h index 2b52ec755de..549026b5874 100644 --- a/gcc/config/rs6000/amo.h +++ b/gcc/config/rs6000/amo.h @@ -44,6 +44,9 @@ enum _AMO_LD { _AMO_LD_SMIN = 0x07, /* Fetch and Signed Minimum. */ _AMO_LD_SWAP = 0x08, /* Swap. */ _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 e14d033267d..627daa8a9fa 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -27060,6 +27060,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 00000000000..f553bac1346 --- /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 00000000000..e24dde40524 --- /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; +}
