diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index f25131eab28b89ee5f44ac5c1bee1992fcba8e67..21f83f26371f638f7b80cc8886fd367a4b00dd04 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -71,6 +71,8 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {"zks", "zksed"},
   {"zks", "zksh"},
 
+  {"ztso", "a"},
+
   {"v", "zvl128b"},
   {"v", "zve64d"},
 
@@ -218,6 +220,8 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zkn",   ISA_SPEC_CLASS_NONE, 1, 0},
   {"zks",   ISA_SPEC_CLASS_NONE, 1, 0},
 
+  {"ztso",  ISA_SPEC_CLASS_NONE, 1, 0},
+
   {"zve32x", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zve32f", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zve64x", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1406,6 +1410,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"svinval", &gcc_options::x_riscv_sv_subext, MASK_SVINVAL},
   {"svnapot", &gcc_options::x_riscv_sv_subext, MASK_SVNAPOT},
 
+  {"ztso", &gcc_options::x_riscv_ztso_subext, MASK_ZTSO},
+
   {"xtheadba",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBA},
   {"xtheadbb",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBB},
   {"xtheadbs",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBS},
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 28d9b81bd8006fd892fd637bc6ad9f21fdfd4223..d6d785d0075ea85d7cb1db1ab78381ce38fb933e 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -152,6 +152,10 @@ enum riscv_entity
 #define TARGET_ZKSH   ((riscv_zk_subext & MASK_ZKSH) != 0)
 #define TARGET_ZKT    ((riscv_zk_subext & MASK_ZKT) != 0)
 
+#define MASK_ZTSO   (1 << 0)
+
+#define TARGET_ZTSO ((riscv_ztso_subext & MASK_ZTSO) != 0)
+
 #define MASK_VECTOR_ELEN_32    (1 << 0)
 #define MASK_VECTOR_ELEN_64    (1 << 1)
 #define MASK_VECTOR_ELEN_FP_32 (1 << 2)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index bb9815a01d7a2b4ad1f206323e3568da91d0bfe0..5dc19ecd3777d17511bfbf864f55cdc05b8a93bc 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4808,6 +4808,10 @@ riscv_union_memmodels (enum memmodel model1, enum memmodel model2)
 static bool
 riscv_memmodel_needs_amo_acquire (enum memmodel model)
 {
+  /* ZTSO amo mappings require no annotations.  */
+  if (TARGET_ZTSO)
+    return false;
+
   switch (model)
     {
       case MEMMODEL_ACQ_REL:
@@ -4831,6 +4835,10 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 static bool
 riscv_memmodel_needs_amo_release (enum memmodel model)
 {
+  /* ZTSO amo mappings require no annotations.  */
+  if (TARGET_ZTSO)
+    return false;
+
   switch (model)
     {
       case MEMMODEL_ACQ_REL:
@@ -5050,7 +5058,10 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 
     case 'I': {
       const enum memmodel model = memmodel_base (INTVAL (op));
-      if (model == MEMMODEL_SEQ_CST)
+      if (TARGET_ZTSO && model != MEMMODEL_SEQ_CST)
+	/* LR ops only have an annotation for SEQ_CST in the Ztso mapping.  */
+	break;
+      else if (model == MEMMODEL_SEQ_CST)
 	fputs (".aqrl", file);
       else if (riscv_memmodel_needs_amo_acquire (model))
 	fputs (".aq", file);
@@ -5059,7 +5070,12 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 
     case 'J': {
       const enum memmodel model = memmodel_base (INTVAL (op));
-      if (riscv_memmodel_needs_amo_release (model))
+      if (TARGET_ZTSO && model == MEMMODEL_SEQ_CST)
+	/* SC ops only have an annotation for SEQ_CST in the Ztso mapping.  */
+	fputs (".rl", file);
+      else if (TARGET_ZTSO)
+	break;
+      else if (riscv_memmodel_needs_amo_release (model))
 	fputs (".rl", file);
       break;
     }
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 688fd697255b94dc6a148f0430b36b6039077c4c..b456fa6abb3c5f284068f8b9d1a646d4cf6afb92 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3321,6 +3321,8 @@
 (include "bitmanip.md")
 (include "crypto.md")
 (include "sync.md")
+(include "sync-rvwmo.md")
+(include "sync-ztso.md")
 (include "peephole.md")
 (include "pic.md")
 (include "generic.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 4dfd8f78ad5e383d8106e5b4f8bea407b303a2b3..717b51b53050c9d1ce812ecfcdf15a1616c07501 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -245,6 +245,9 @@ int riscv_zm_subext
 TargetVariable
 int riscv_sv_subext
 
+TargetVariable
+int riscv_ztso_subext
+
 TargetVariable
 int riscv_xthead_subext
 
diff --git a/gcc/config/riscv/sync-rvwmo.md b/gcc/config/riscv/sync-rvwmo.md
new file mode 100644
index 0000000000000000000000000000000000000000..1fc7cf16b5bf8505329126b0c73d6c4dc4d722d8
--- /dev/null
+++ b/gcc/config/riscv/sync-rvwmo.md
@@ -0,0 +1,96 @@
+;; Machine description for RISC-V atomic operations.
+;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Contributed by Andrew Waterman (andrew@sifive.com).
+;; Based on MIPS target for GNU compiler.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; Memory barrier.
+
+(define_insn "mem_thread_fence_rvwmo"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+   (match_operand:SI 1 "const_int_operand" "")]  ;; model
+  "!TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[1]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+	return "fence\trw,rw";
+    else if (model == MEMMODEL_ACQ_REL)
+	return "fence.tso";
+    else if (model == MEMMODEL_ACQUIRE)
+	return "fence\tr,rw";
+    else if (model == MEMMODEL_RELEASE)
+	return "fence\trw,w";
+    else
+	gcc_unreachable ();
+  }
+  [(set (attr "length") (const_int 4))])
+
+;; Atomic memory operations.
+
+(define_insn "atomic_load_rvwmo<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec_volatile:GPR
+	    [(match_operand:GPR 1 "memory_operand" "A")
+	     (match_operand:SI 2 "const_int_operand")]  ;; model
+	 UNSPEC_ATOMIC_LOAD))]
+  "TARGET_ATOMIC && !TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+	     "l<amo>\t%0,%1\;"
+	     "fence\tr,rw";
+    if (model == MEMMODEL_ACQUIRE)
+      return "l<amo>\t%0,%1\;"
+	     "fence\tr,rw";
+    else
+      return "l<amo>\t%0,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 12))])
+
+;; Implement atomic stores with conservative fences.
+;; This allows us to be compatible with the ISA manual Table A.6 and Table A.7.
+(define_insn "atomic_store_rvwmo<mode>"
+  [(set (match_operand:GPR 0 "memory_operand" "=A")
+	(unspec_volatile:GPR
+	    [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+	     (match_operand:SI 2 "const_int_operand")]  ;; model
+	 UNSPEC_ATOMIC_STORE))]
+  "TARGET_ATOMIC && !TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "fence\trw,w\;"
+	     "s<amo>\t%z1,%0\;"
+	     "fence\trw,rw";
+    if (model == MEMMODEL_RELEASE)
+      return "fence\trw,w\;"
+	     "s<amo>\t%z1,%0";
+    else
+      return "s<amo>\t%z1,%0";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 12))])
diff --git a/gcc/config/riscv/sync-ztso.md b/gcc/config/riscv/sync-ztso.md
new file mode 100644
index 0000000000000000000000000000000000000000..91c2a48c069f7dd2d632371abb26cc2919e65665
--- /dev/null
+++ b/gcc/config/riscv/sync-ztso.md
@@ -0,0 +1,80 @@
+;; Machine description for RISC-V atomic operations.
+;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Contributed by Andrew Waterman (andrew@sifive.com).
+;; Based on MIPS target for GNU compiler.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; Memory barriers.
+
+(define_insn "mem_thread_fence_ztso"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
+   (match_operand:SI 1 "const_int_operand" "")]  ;; model
+  "TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[1]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+	return "fence\trw,rw";
+    else
+	gcc_unreachable ();
+  }
+  [(set (attr "length") (const_int 4))])
+
+;; Atomic memory operations.
+
+(define_insn "atomic_load_ztso<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec_volatile:GPR
+	    [(match_operand:GPR 1 "memory_operand" "A")
+	     (match_operand:SI 2 "const_int_operand")]  ;; model
+	 UNSPEC_ATOMIC_LOAD))]
+  "TARGET_ATOMIC && TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+	     "l<amo>\t%0,%1\;";
+    else
+      return "l<amo>\t%0,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 12))])
+
+(define_insn "atomic_store_ztso<mode>"
+  [(set (match_operand:GPR 0 "memory_operand" "=A")
+	(unspec_volatile:GPR
+	    [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+	     (match_operand:SI 2 "const_int_operand")]  ;; model
+	 UNSPEC_ATOMIC_STORE))]
+  "TARGET_ATOMIC && TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "s<amo>\t%z1,%0\;"
+	     "fence\trw,rw";
+    else
+      return "s<amo>\t%z1,%0";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 8))])
\ No newline at end of file
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 9fc626267de3840ce15d196bff72440a980fd234..2f85951508f89593307b6cf521615d31ffca76ba 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -36,88 +36,55 @@
 (define_expand "mem_thread_fence"
   [(match_operand:SI 0 "const_int_operand" "")] ;; model
   ""
-{
-  if (INTVAL (operands[0]) != MEMMODEL_RELAXED)
-    {
-      rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
-      MEM_VOLATILE_P (mem) = 1;
-      emit_insn (gen_mem_thread_fence_1 (mem, operands[0]));
-    }
-  DONE;
-})
-
-(define_insn "mem_thread_fence_1"
-  [(set (match_operand:BLK 0 "" "")
-	(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
-   (match_operand:SI 1 "const_int_operand" "")] ;; model
-  ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[1]);
-    model = memmodel_base (model);
-    if (model == MEMMODEL_SEQ_CST)
-	return "fence\trw,rw";
-    else if (model == MEMMODEL_ACQ_REL)
-	return "fence.tso";
-    else if (model == MEMMODEL_ACQUIRE)
-	return "fence\tr,rw";
-    else if (model == MEMMODEL_RELEASE)
-	return "fence\trw,w";
-    else
-	gcc_unreachable ();
-  }
-  [(set (attr "length") (const_int 4))])
+    enum memmodel model = memmodel_base (INTVAL (operands[0]));
+
+    if (TARGET_ZTSO && model == MEMMODEL_SEQ_CST)
+      {
+	rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+	MEM_VOLATILE_P (mem) = 1;
+	emit_insn (gen_mem_thread_fence_ztso (mem, operands[0]));
+      }
+    else if (!TARGET_ZTSO && model != MEMMODEL_RELAXED)
+      {
+	rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+	MEM_VOLATILE_P (mem) = 1;
+	emit_insn (gen_mem_thread_fence_rvwmo (mem, operands[0]));
+      }
+    DONE;
+  })
 
 ;; Atomic memory operations.
 
-(define_insn "atomic_load<mode>"
-  [(set (match_operand:GPR 0 "register_operand" "=r")
-    (unspec_volatile:GPR
-      [(match_operand:GPR 1 "memory_operand" "A")
-       (match_operand:SI 2 "const_int_operand")]      ;; model
-      UNSPEC_ATOMIC_LOAD))]
+(define_expand "atomic_load<mode>"
+  [(match_operand:GPR 0 "register_operand")
+   (match_operand:GPR 1 "memory_operand")
+   (match_operand:SI 2 "const_int_operand")] ;; model
   "TARGET_ATOMIC"
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    model = memmodel_base (model);
-
-    if (model == MEMMODEL_SEQ_CST)
-      return "fence\trw,rw\;"
-	     "l<amo>\t%0,%1\;"
-	     "fence\tr,rw";
-    if (model == MEMMODEL_ACQUIRE)
-      return "l<amo>\t%0,%1\;"
-	     "fence\tr,rw";
+    if (TARGET_ZTSO)
+      emit_insn (gen_atomic_load_ztso<mode> (operands[0], operands[1],
+					     operands[2]));
     else
-      return "l<amo>\t%0,%1";
-  }
-  [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 12))])
-
-;; Implement atomic stores with conservative fences.
-;; This allows us to be compatible with the ISA manual Table A.6 and Table A.7.
-(define_insn "atomic_store<mode>"
-  [(set (match_operand:GPR 0 "memory_operand" "=A")
-    (unspec_volatile:GPR
-      [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
-       (match_operand:SI 2 "const_int_operand")]      ;; model
-      UNSPEC_ATOMIC_STORE))]
+      emit_insn (gen_atomic_load_rvwmo<mode> (operands[0], operands[1],
+					      operands[2]));
+    DONE;
+  })
+
+(define_expand "atomic_store<mode>"
+  [(match_operand:GPR 0 "memory_operand")
+   (match_operand:GPR 1 "reg_or_0_operand")
+   (match_operand:SI 2 "const_int_operand")] ;; model
   "TARGET_ATOMIC"
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    model = memmodel_base (model);
-
-    if (model == MEMMODEL_SEQ_CST)
-      return "fence\trw,w\;"
-	     "s<amo>\t%z1,%0\;"
-	     "fence\trw,rw";
-    if (model == MEMMODEL_RELEASE)
-      return "fence\trw,w\;"
-	     "s<amo>\t%z1,%0";
+    if (TARGET_ZTSO)
+      emit_insn (gen_atomic_store_ztso<mode> (operands[0], operands[1],
+					      operands[2]));
     else
-      return "s<amo>\t%z1,%0";
-  }
-  [(set_attr "type" "atomic")
-   (set (attr "length") (const_int 12))])
+      emit_insn (gen_atomic_store_rvwmo<mode> (operands[0], operands[1],
+					       operands[2]));
+    DONE;
+  })
 
 (define_insn "atomic_<atomic_optab><mode>"
   [(set (match_operand:GPR 0 "memory_operand" "+A")
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a7097e9aab96b361f3eb3a56d5d06f43301b5e50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	amoadd\.w\tzero,a1,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e99390343980ed28882c1a366ada1aa3171f6a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that atomic op mappings the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	amoadd\.w\tzero,a1,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..e1cd209fcb2ca690a2cadb6ad2e3a448a8a13697
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	amoadd\.w\tzero,a1,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-4.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..484d11eb100ddeb0fd67e78e08709bd672b07c17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-4.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	amoadd\.w\tzero,a1,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-5.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..2117283fd0d3b193f52859f908deba6387f98b27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-amo-add-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	amoadd\.w\tzero,a1,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..03247c632fd0e9e54b831b8a8aa4394797d5d085
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (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-table-ztso-compare-exchange-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..463567470679b26cc66bb6cd41132372ba51c143
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (int bar, int baz, int qux)
+{
+  __atomic_compare_exchange_n(&bar, &baz, qux, 1, __ATOMIC_CONSUME, __ATOMIC_CONSUME);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf252dba6ecd6a0ee3aa1ce62a178aa3f92bad5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (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-table-ztso-compare-exchange-4.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a0c86569b540203f7fdb200ace899ec9bcc19f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (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-table-ztso-compare-exchange-5.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..750ba89cd7456ee435366fea294d9242c1f5d9e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+
+void foo (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-table-ztso-compare-exchange-6.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-6.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d0bf26d95adf5a6e413257c83b7df55edd4fd5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-6.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (int bar, int baz, int qux)
+{
+  __atomic_compare_exchange_n(&bar, &baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-7.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-7.c
new file mode 100644
index 0000000000000000000000000000000000000000..838568ed588ee73913a4ea53f10e1f5777d9330f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-compare-exchange-7.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that compare exchange mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+
+void foo (int bar, int baz, int qux)
+{
+  __atomic_compare_exchange_n(&bar, &baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a9ba4a252e7444d4ed16d4c009afd55405bf9794
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* Verify that fence mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	ret
+*/
+void foo()
+{
+  __atomic_thread_fence(__ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b083431d1a37b17634658e1c56d55081836903a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* Verify that fence mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	ret
+*/
+void foo()
+{
+  __atomic_thread_fence(__ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..db21ee6f0314034ea59fcfa861315c8d11ce8b15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* Verify that fence mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	ret
+*/
+void foo()
+{
+  __atomic_thread_fence(__ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-4.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..d5bc61b57e88b54108b6dfa5fa7e5b1220e177a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* Verify that fence mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	ret
+*/
+void foo()
+{
+  __atomic_thread_fence(__ATOMIC_ACQ_REL);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-5.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5e5f4e50126e95ee591a6bd3a08c00a776f79c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-fence-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Verify that fence mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	fence\trw,rw
+**	ret
+*/
+void foo()
+{
+  __atomic_thread_fence(__ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..be5f8d310a422eae0cd865906ec97b2122e90099
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* Verify that load mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	lw\ta[0-9]+,0\(a0\)
+**	sw\ta[0-9]+,0\(a1\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_load(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..305838416489cea3fdf27e3115b4e45153907ae3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* Verify that load mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	lw\ta[0-9]+,0\(a0\)
+**	sw\ta[0-9]+,0\(a1\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_load(bar, baz, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..c1c3b57bfe519c40d7a9e4e98e9d12b8dc6228e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-load-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Verify that load mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	fence\trw,rw
+**	lw\ta[0-9]+,0\(a0\)
+**	sw\ta[0-9]+,0\(a1\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_load(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..f5519db22f72db3ae21e2056ed67592e8c01891c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* Verify that store mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	lw\ta[0-9]+,0\(a1\)
+**	sw\ta[0-9]+,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_store(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..440f407e66abc7ff0d7e28c15816c36e82065ef9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* Verify that store mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	lw\ta[0-9]+,0\(a1\)
+**	sw\ta[0-9]+,0\(a0\)
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_store(bar, baz, __ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..a92d4d1ce9a4b56d02db9d1648d4d80dde250179
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-store-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Verify that store mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso -O3" } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** foo:
+**	lw\ta[0-9]+,0\(a1\)
+**	sw\ta[0-9]+,0\(a0\)
+**	fence\trw,rw
+**	ret
+*/
+void foo (int* bar, int* baz)
+{
+  __atomic_store(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-1.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..e187a6b7335ed158f6b91a7758b912bab15233a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (short* bar, short* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-2.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..1e0867624bad139b2267e708381b31ff031feba9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (short* bar, short* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-3.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b2ef967375ffeb34e8a44d70c64ff2f2a10bf1b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (short* bar, short* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-4.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..87e5356f0a7ebc616e84daf3610557d83d6cd353
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
+
+void foo (short* bar, short* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-5.c b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-5.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd59c8880ecec98b9e384708d7afdcf9ed7c0d43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo-table-ztso-subword-amo-add-5.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
+/* { dg-options "-march=rv64id_ztso" } */
+/* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
+/* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
+
+void foo (short* bar, short* baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}