From: Gianluca Guida <gianl...@rivosinc.com>

This patch adds support for amocas.{b|h|w|d}. Support for amocas.q
(64/128 bit cas for rv32/64) will be added in a future patch.

Extension: https://github.com/riscv/riscv-zacas
Ratification: https://jira.riscv.org/browse/RVS-680

gcc/ChangeLog:

        * common/config/riscv/riscv-common.cc
        (riscv_subset_list::to_string): Skip zacas when not supported by
        the assembler.
        * config.in: Regenerate.
        * config/riscv/arch-canonicalize: Make zacas imply zaamo.
        * config/riscv/riscv.opt: Add zacas.
        * config/riscv/sync.md (zacas_atomic_cas_value<mode>): New pattern.
        (atomic_compare_and_swap<mode>): Use new pattern for compare-and-swap 
ops.
        * configure: Regenerate.
        * configure.ac: Regenerate.
        * doc/sourcebuild.texi: Add Zacas documentation.

gcc/testsuite/ChangeLog:

        * lib/target-supports.exp: Add zacas testsuite infra support.
        * 
gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c:
        Remove zacas to continue to test the lr/sc pairs.
        * gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c: 
Ditto.
        * 
gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c: Ditto.
        * gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c: 
Ditto.
        * 
gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c: Ditto.
        * gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c: 
Ditto.
        * gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c: 
Ditto.
        * 
gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c: Ditto.
        * gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c: 
Ditto.
        * gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c: New test.
        * gcc.target/riscv/amo/zacas-char-requires-zabha.c: New test.
        * gcc.target/riscv/amo/zacas-char-requires-zacas.c: New test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c: New 
test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c: 
New test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c: 
New test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c: 
New test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c: 
New test.
        * gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c: 
New test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c: New 
test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c: New test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c: New 
test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c: New test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c: New 
test.
        * gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c: New test.

Co-authored-by: Patrick O'Neill <patr...@rivosinc.com>
---
Gianluca Guida created the initial patch. Rebased and added more
testcases/docs/etc.

Tested using amo.exp with rv64gc_zalrsc and rv64gc_ztso.
Relying on precommit for full testing.
---
 gcc/common/config/riscv/riscv-common.cc       | 11 +++
 gcc/config.in                                 |  6 ++
 gcc/config/riscv/arch-canonicalize            |  1 +
 gcc/config/riscv/riscv.opt                    |  2 +
 gcc/config/riscv/sync.md                      | 69 ++++++++++++++++---
 gcc/configure                                 | 31 +++++++++
 gcc/configure.ac                              |  5 ++
 gcc/doc/sourcebuild.texi                      | 10 +++
 .../amo/zabha-zacas-preferred-over-zalrsc.c   | 16 +++++
 .../riscv/amo/zacas-char-requires-zabha.c     | 17 +++++
 .../riscv/amo/zacas-char-requires-zacas.c     | 17 +++++
 ...acas-rvwmo-compare-exchange-char-acq-rel.c | 15 ++++
 ...acas-rvwmo-compare-exchange-char-acquire.c | 15 ++++
 ...acas-rvwmo-compare-exchange-char-relaxed.c | 15 ++++
 ...acas-rvwmo-compare-exchange-char-release.c | 15 ++++
 ...acas-rvwmo-compare-exchange-char-seq-cst.c | 15 ++++
 ...zacas-rvwmo-compare-exchange-int-acq-rel.c | 15 ++++
 ...zacas-rvwmo-compare-exchange-int-acquire.c | 15 ++++
 ...zacas-rvwmo-compare-exchange-int-relaxed.c | 15 ++++
 ...zacas-rvwmo-compare-exchange-int-release.c | 15 ++++
 ...zacas-rvwmo-compare-exchange-int-seq-cst.c | 15 ++++
 ...cas-rvwmo-compare-exchange-short-acq-rel.c | 15 ++++
 ...cas-rvwmo-compare-exchange-short-acquire.c | 15 ++++
 ...cas-rvwmo-compare-exchange-short-relaxed.c | 15 ++++
 ...cas-rvwmo-compare-exchange-short-release.c | 15 ++++
 ...cas-rvwmo-compare-exchange-short-seq-cst.c | 15 ++++
 ...zacas-ztso-compare-exchange-char-seq-cst.c | 14 ++++
 .../amo/zacas-ztso-compare-exchange-char.c    | 29 ++++++++
 .../zacas-ztso-compare-exchange-int-seq-cst.c | 14 ++++
 .../amo/zacas-ztso-compare-exchange-int.c     | 29 ++++++++
 ...acas-ztso-compare-exchange-short-seq-cst.c | 14 ++++
 .../amo/zacas-ztso-compare-exchange-short.c   | 29 ++++++++
 ...wmo-compare-exchange-int-acquire-release.c |  2 +
 ...alrsc-rvwmo-compare-exchange-int-acquire.c |  2 +
 ...alrsc-rvwmo-compare-exchange-int-consume.c |  2 +
 ...alrsc-rvwmo-compare-exchange-int-relaxed.c |  2 +
 ...alrsc-rvwmo-compare-exchange-int-release.c |  2 +
 ...wmo-compare-exchange-int-seq-cst-relaxed.c |  2 +
 ...alrsc-rvwmo-compare-exchange-int-seq-cst.c |  2 +
 ...tso-compare-exchange-int-acquire-release.c |  1 +
 ...zalrsc-ztso-compare-exchange-int-acquire.c |  1 +
 ...zalrsc-ztso-compare-exchange-int-consume.c |  1 +
 ...zalrsc-ztso-compare-exchange-int-relaxed.c |  1 +
 ...zalrsc-ztso-compare-exchange-int-release.c |  1 +
 ...tso-compare-exchange-int-seq-cst-relaxed.c |  1 +
 ...zalrsc-ztso-compare-exchange-int-seq-cst.c |  1 +
 gcc/testsuite/lib/target-supports.exp         | 25 ++++++-
 47 files changed, 576 insertions(+), 9 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c

diff --git a/gcc/common/config/riscv/riscv-common.cc 
b/gcc/common/config/riscv/riscv-common.cc
index 16bdb3fd225..43255c5bb8d 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -83,6 +83,7 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {"a", "zalrsc"},

   {"zabha", "zaamo"},
+  {"zacas", "zaamo"},

   {"zdinx", "zfinx"},
   {"zfinx", "zicsr"},
@@ -263,6 +264,7 @@ static const struct riscv_ext_version 
riscv_ext_version_table[] =
   {"zaamo", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zalrsc", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zabha", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zacas", ISA_SPEC_CLASS_NONE, 1, 0},

   {"zba", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -922,6 +924,7 @@ riscv_subset_list::to_string (bool version_p) const
   bool skip_zifencei = false;
   bool skip_zaamo_zalrsc = false;
   bool skip_zabha = false;
+  bool skip_zacas = false;
   bool skip_zicsr = false;
   bool i2p0 = false;

@@ -957,6 +960,10 @@ riscv_subset_list::to_string (bool version_p) const
   /* Skip since binutils 2.42 and earlier don't recognize zabha.  */
   skip_zabha = true;
 #endif
+#ifndef HAVE_AS_MARCH_ZACAS
+  /* Skip since binutils 2.42 and earlier don't recognize zacas.  */
+  skip_zacas = true;
+#endif

   for (subset = m_head; subset != NULL; subset = subset->next)
     {
@@ -977,6 +984,9 @@ riscv_subset_list::to_string (bool version_p) const
       if (skip_zabha && subset->name == "zabha")
        continue;

+      if (skip_zacas && subset->name == "zacas")
+       continue;
+
       /* For !version_p, we only separate extension with underline for
         multi-letter extension.  */
       if (!first &&
@@ -1650,6 +1660,7 @@ static const riscv_ext_flag_table_t 
riscv_ext_flag_table[] =
   {"zaamo",   &gcc_options::x_riscv_za_subext, MASK_ZAAMO},
   {"zalrsc",  &gcc_options::x_riscv_za_subext, MASK_ZALRSC},
   {"zabha",   &gcc_options::x_riscv_za_subext, MASK_ZABHA},
+  {"zacas",   &gcc_options::x_riscv_za_subext, MASK_ZACAS},

   {"zba",    &gcc_options::x_riscv_zb_subext, MASK_ZBA},
   {"zbb",    &gcc_options::x_riscv_zb_subext, MASK_ZBB},
diff --git a/gcc/config.in b/gcc/config.in
index ae41596596f..ea7d98da6fd 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -641,6 +641,12 @@
 #endif


+/* Define if the assembler understands -march=rv*_zacas. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZACAS
+#endif
+
+
 /* Define if the assembler understands -march=rv*_zifencei. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_MARCH_ZIFENCEI
diff --git a/gcc/config/riscv/arch-canonicalize 
b/gcc/config/riscv/arch-canonicalize
index 35a7fe4455a..3341a54069f 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -43,6 +43,7 @@ IMPLIED_EXT = {

   "a" : ["zaamo", "zalrsc"],
   "zabha" : ["zaamo"],
+  "zacas" : ["zaamo"],

   "f" : ["zicsr"],
   "zdinx" : ["zfinx", "zicsr"],
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 32a0dda5843..6bf5d58305f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -264,6 +264,8 @@ Mask(ZALRSC) Var(riscv_za_subext)

 Mask(ZABHA) Var(riscv_za_subext)

+Mask(ZACAS) Var(riscv_za_subext)
+
 Mask(ZA64RS)  Var(riscv_za_subext)

 Mask(ZA128RS) Var(riscv_za_subext)
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 0470e2ca457..8ef61f22c6e 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -530,6 +530,27 @@
   [(set_attr "type" "multi")
    (set (attr "length") (const_int 16))])

+(define_insn "zacas_atomic_cas_value<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=&r")
+       (match_operand:GPR 1 "memory_operand" "+A"))
+   (set (match_dup 1)
+       (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
+                             (match_operand:GPR 3 "reg_or_0_operand" "rJ")
+                             (match_operand:SI 4 "const_int_operand")  ;; mod_s
+                             (match_operand:SI 5 "const_int_operand")] ;; mod_f
+        UNSPEC_COMPARE_AND_SWAP))]
+  "TARGET_ZACAS"
+  {
+    enum memmodel model_success = (enum memmodel) INTVAL (operands[4]);
+    enum memmodel model_failure = (enum memmodel) INTVAL (operands[5]);
+    /* Find the union of the two memory models so we can satisfy both success
+       and failure memory models.  */
+    operands[5] = GEN_INT (riscv_union_memmodels (model_success, 
model_failure));
+    return "amocas.<amo>%A5\t%0,%z3,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "atomic_compare_and_swap<mode>"
   [(match_operand:SI 0 "register_operand" "")   ;; bool output
    (match_operand:GPR 1 "register_operand" "")  ;; val output
@@ -539,7 +560,7 @@
    (match_operand:SI 5 "const_int_operand" "")  ;; is_weak
    (match_operand:SI 6 "const_int_operand" "")  ;; mod_s
    (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
-  "TARGET_ZALRSC"
+  "TARGET_ZALRSC || TARGET_ZACAS"
 {
   if (word_mode != <MODE>mode && operands[3] != const0_rtx)
     {
@@ -550,9 +571,14 @@
       operands[3] = simplify_gen_subreg (<MODE>mode, tmp0, word_mode, 0);
     }

-  emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
-                                               operands[3], operands[4],
-                                               operands[6], operands[7]));
+  if (TARGET_ZACAS)
+    emit_insn (gen_zacas_atomic_cas_value<mode> (operands[1], operands[2],
+                                                operands[3], operands[4],
+                                                operands[6], operands[7]));
+  else
+    emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
+                                                 operands[3], operands[4],
+                                                 operands[6], operands[7]));

   rtx compare = operands[1];
   if (operands[3] != const0_rtx)
@@ -573,6 +599,27 @@
   DONE;
 })

+(define_insn "zacas_atomic_cas_value<mode>"
+  [(set (match_operand:SHORT 0 "register_operand" "=&r")
+       (match_operand:SHORT 1 "memory_operand" "+A"))
+   (set (match_dup 1)
+       (unspec_volatile:SHORT [(match_operand:SHORT 2 "register_operand" "0")
+                             (match_operand:SHORT 3 "register_operand" "rJ")
+                             (match_operand:SI 4 "const_int_operand")  ;; mod_s
+                             (match_operand:SI 5 "const_int_operand")] ;; mod_f
+        UNSPEC_COMPARE_AND_SWAP))]
+  "TARGET_ZACAS && TARGET_ZABHA"
+  {
+    enum memmodel model_success = (enum memmodel) INTVAL (operands[4]);
+    enum memmodel model_failure = (enum memmodel) INTVAL (operands[5]);
+    /* Find the union of the two memory models so we can satisfy both success
+       and failure memory models.  */
+    operands[5] = GEN_INT (riscv_union_memmodels (model_success, 
model_failure));
+    return "amocas.<amobh>%A5\t%0,%z3,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "atomic_compare_and_swap<mode>"
   [(match_operand:SI 0 "register_operand")    ;; bool output
    (match_operand:SHORT 1 "register_operand") ;; val output
@@ -582,11 +629,17 @@
    (match_operand:SI 5 "const_int_operand")   ;; is_weak
    (match_operand:SI 6 "const_int_operand")   ;; mod_s
    (match_operand:SI 7 "const_int_operand")]  ;; mod_f
-  "TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
+  "(TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC) || (TARGET_ZACAS && 
TARGET_ZABHA)"
 {
-  emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
-                                               operands[3], operands[4],
-                                               operands[6], operands[7]));
+
+  if (TARGET_ZACAS && TARGET_ZABHA)
+    emit_insn (gen_zacas_atomic_cas_value<mode> (operands[1], operands[2],
+                                                operands[3], operands[4],
+                                                operands[6], operands[7]));
+  else
+    emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
+                                                 operands[3], operands[4],
+                                                 operands[6], operands[7]));

   rtx val = gen_reg_rtx (SImode);
   if (operands[1] != const0_rtx)
diff --git a/gcc/configure b/gcc/configure
index 1335db2d4d2..991797bc4a8 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -30884,6 +30884,37 @@ if test $gcc_cv_as_riscv_march_zabha = yes; then

 $as_echo "#define HAVE_AS_MARCH_ZABHA 1" >>confdefs.h

+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for 
-march=rv32i_zacas support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zacas support... " >&6; }
+if ${gcc_cv_as_riscv_march_zacas+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_march_zacas=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zacas -o conftest.o 
conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       gcc_cv_as_riscv_march_zacas=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zacas" 
>&5
+$as_echo "$gcc_cv_as_riscv_march_zacas" >&6; }
+if test $gcc_cv_as_riscv_march_zacas = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZACAS 1" >>confdefs.h
+
 fi

     ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index eb72f65865a..34cff840b13 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5464,6 +5464,11 @@ configured with --enable-newlib-nano-formatted-io.])
       [-march=rv32i_zabha],,,
       [AC_DEFINE(HAVE_AS_MARCH_ZABHA, 1,
                 [Define if the assembler understands -march=rv*_zabha.])])
+    gcc_GAS_CHECK_FEATURE([-march=rv32i_zacas support],
+      gcc_cv_as_riscv_march_zacas,
+      [-march=rv32i_zacas],,,
+      [AC_DEFINE(HAVE_AS_MARCH_ZACAS, 1,
+                [Define if the assembler understands -march=rv*_zacas.])])
     ;;
     loongarch*-*-*)
     gcc_GAS_CHECK_FEATURE([.dtprelword support],
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 66c4206bfc2..d5c48e67b71 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2530,6 +2530,9 @@ Test target architecture has support for the zaamo 
extension.
 @item riscv_zabha
 Test target architecture has support for the zabha extension.

+@item riscv_zacas
+Test target architecture has support for the zacas extension.
+
 @item riscv_zalrsc
 Test target architecture has support for the zalrsc extension.

@@ -3298,6 +3301,9 @@ Add the zaamo extension to the -march string on RISC-V 
targets.
 @item riscv_zabha
 Add the zabha extension to the -march string on RISC-V targets.

+@item riscv_zacas
+Add the zacas extension to the -march string on RISC-V targets.
+
 @item riscv_zalrsc
 Add the zalrsc extension to the -march string on RISC-V targets.

@@ -3345,6 +3351,10 @@ extension is present downgrade it to zalrsc.
 Remove the zabha extension and implied zaamo extension from the -march string
 on RISC-V.

+@item riscv_zacas
+Remove the zacas extension and implied zaamo extension from the -march string
+on RISC-V.
+
 @item riscv_zalrsc
 Remove the zalrsc extension from the -march string on RISC-V. If the 'A'
 extension is present downgrade it to zaamo.
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c 
b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c
new file mode 100644
index 00000000000..8eabb67162e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* Ensure that AMO ops are emitted for subword cas when both zalrsc and
+   zacas/zabha are enabled.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zalrsc } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 1 } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c
new file mode 100644
index 00000000000..c7d6e7c578b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Ensure subword zacas is not emitted unless both zacas and zabha are
+   present.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_zabha } */
+/* { dg-remove-options riscv_zalrsc } */
+/* { dg-final { scan-assembler "\tcall\t" } } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-not "amocas\.b\t" } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c
new file mode 100644
index 00000000000..d0cf14432fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Ensure subword zacas is not emitted unless both zacas and zabha are
+   present.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_zacas } */
+/* { dg-remove-options riscv_zalrsc } */
+/* { dg-final { scan-assembler "\tcall\t" } } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-not "amocas\.b\t" } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
new file mode 100644
index 00000000000..bde42d28a6c
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
new file mode 100644
index 00000000000..f2cdc58a54b
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aq\t" 1 } } */
+
+
+void atomic_compare_exchange_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
new file mode 100644
index 00000000000..6719c8cea66
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 1 } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
new file mode 100644
index 00000000000..0d8928c5e31
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.rl\t" 1 } } */
+
+
+void atomic_compare_exchange_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
new file mode 100644
index 00000000000..1eb037a13ba
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c
new file mode 100644
index 00000000000..8e3eec635ba
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c
new file mode 100644
index 00000000000..b317c474649
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aq\t" 1 } } */
+
+
+void atomic_compare_exchange_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c
new file mode 100644
index 00000000000..7dc20361bec
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 1 } } */
+
+
+void atomic_compare_exchange_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c
new file mode 100644
index 00000000000..df551de7b94
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.rl\t" 1 } } */
+
+
+void atomic_compare_exchange_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c
new file mode 100644
index 00000000000..856653849ef
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
new file mode 100644
index 00000000000..9fcd531c635
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
new file mode 100644
index 00000000000..3327973c13a
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aq\t" 1 } } */
+
+
+void atomic_compare_exchange_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
new file mode 100644
index 00000000000..5636db05ac3
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 1 } } */
+
+
+void atomic_compare_exchange_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
new file mode 100644
index 00000000000..b9fb678bd57
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.rl\t" 1 } } */
+
+
+void atomic_compare_exchange_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
new file mode 100644
index 00000000000..531bdbce7c6
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
@@ -0,0 +1,15 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aqrl\t" 1 } } */
+
+
+void atomic_compare_exchange_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c
new file mode 100644
index 00000000000..8b3032d357b
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c
@@ -0,0 +1,14 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 1 } } */
+
+void atomic_compare_exchange_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c
new file mode 100644
index 00000000000..e88251e86f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c
@@ -0,0 +1,29 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 4 } } */
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c
new file mode 100644
index 00000000000..9dbaef4ed29
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c
@@ -0,0 +1,14 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 1 } } */
+
+void atomic_compare_exchange_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c
new file mode 100644
index 00000000000..1d771a08150
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c
@@ -0,0 +1,29 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 4 } } */
+
+void atomic_compare_exchange_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
new file mode 100644
index 00000000000..35e80a36cfb
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
@@ -0,0 +1,14 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 1 } } */
+
+void atomic_compare_exchange_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, 
__ATOMIC_SEQ_CST);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c 
b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c
new file mode 100644
index 00000000000..76e410aee37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c
@@ -0,0 +1,29 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  
*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 4 } } */
+
+void atomic_compare_exchange_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, 
__ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, 
__ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, 
__ATOMIC_RELAXED);
+}
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
index 49eeda9cb33..7307c1f7818 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
@@ -2,9 +2,11 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* Mixed mappings need to be unioned.  */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
index b9e3adece8d..7514f50062f 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
@@ -2,8 +2,10 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
index 11839d84f14..50433255bb5 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
@@ -2,8 +2,10 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
index 852ec99df76..4922f214138 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
@@ -2,8 +2,10 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
index 9c51a082d0b..eb3bac4e575 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
@@ -2,8 +2,10 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
index d985e2cef8b..d1bff7e7695 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
@@ -3,8 +3,10 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
index 6efd232ce21..b4422c172e6 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
@@ -2,8 +2,10 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */

 void foo (int bar, int baz, int qux)
 {
diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
index 9761a955ede..496af8bfd7d 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
@@ -3,6 +3,7 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
index 3303f8021e1..737e3eb3d68 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
index 7474e832bb1..51b3b5a8dc7 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
index e43193820f2..9a41410a57b 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
index a0d5872e1bd..ee778a760d1 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
index fc464ab1ff5..6fbe943b316 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
@@ -3,6 +3,7 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */

diff --git 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
index 152806cfde3..a361c10086d 100644
--- 
a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
+++ 
b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended 
mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */

diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index e7a1984704a..7fd37c1c297 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1922,6 +1922,17 @@ proc check_effective_target_riscv_zabha { } {
     }]
 }

+# Return 1 if the target arch supports the atomic CAS extension, 0 otherwise.
+# Cache the result.
+
+proc check_effective_target_riscv_zacas { } {
+    return [check_no_compiler_messages riscv_ext_zacas assembly {
+       #ifndef __riscv_zacas
+       #error "Not __riscv_zacas"
+       #endif
+    }]
+}
+
 # Return 1 if the target arch supports the double precision floating point
 # extension, 0 otherwise.  Cache the result.

@@ -2140,7 +2151,7 @@ proc check_effective_target_riscv_v_misalign_ok { } {
 proc riscv_get_arch { } {
     set gcc_march ""
     # ??? do we neeed to add more extensions to the list below?
-    foreach ext { i m a f d q c v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh 
ztso zaamo zalrsc zabha } {
+    foreach ext { i m a f d q c v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh 
ztso zaamo zalrsc zabha zacas } {
        if { [check_no_compiler_messages  riscv_ext_$ext assembly [string map 
[list DEF __riscv_$ext] {
                #ifndef DEF
                #error "Not DEF"
@@ -2308,6 +2319,9 @@ proc remove_options_for_riscv_zaamo { flags } {
     # If zabha is set then zaamo will be implied. We need to remove zabha
     # as well.
     set modified_flags [remove_options_for_riscv_z_ext zabha $modified_flags]
+    # If zacas is set then zaamo will be implied. We need to remove zacas
+    # as well.
+    set modified_flags [remove_options_for_riscv_z_ext zacas $modified_flags]
     # If 'a' is set then zaamo will be implied. We need to downgrade instances
     # of 'a' to 'zalrsc'
     set no_a_flags [remove_options_for_riscv_a_only $modified_flags]
@@ -2343,6 +2357,15 @@ proc remove_options_for_riscv_zabha { flags } {
     return [remove_options_for_riscv_z_ext zabha $modified_flags]
 }

+proc add_options_for_riscv_zacas { flags } {
+    return [add_options_for_riscv_z_ext zacas $flags]
+}
+
+proc remove_options_for_riscv_zacas { flags } {
+    set modified_flags [remove_options_for_riscv_zaamo $flags]
+    return [remove_options_for_riscv_z_ext zacas $modified_flags]
+}
+
 proc add_options_for_riscv_zfh { flags } {
     return [add_options_for_riscv_z_ext zfh $flags]
 }
--
2.34.1

Reply via email to