https://gcc.gnu.org/g:b6bebf2a7326e6b5566f1aa2979233a60e5c8377

commit r17-2556-gb6bebf2a7326e6b5566f1aa2979233a60e5c8377
Author: Shreya Munnangi <[email protected]>
Date:   Mon Jul 20 07:02:48 2026 -0600

    [PATCH][RISC-V][PR target/124741] Improving atomic sequences
    
     In PR 124741, we have a testcase:
    
    typedef struct
    {
      int x;
      unsigned repr;
    } atomic_u_t;
    
    unsigned
    atomic_load_u (const atomic_u_t *a)
    {
      unsigned result;
      __atomic_load (&a->repr, &result, 0);
      return result;
    }
    
    When compiled with rv64, it outputs:
    
    addi    a5,a0,4
    lw      a0,0(a5)
    sext.w  a0,a0
    ret
    
    Here we have a redundant sign extension and inefficient address arithmetic.
    This can be simplified into two instructions, a load and a return.
    
    The lw insn is already doing a sign extension from 32 to 64 bits, making
    the separate sext.w unnecessary. Adding a copy of the pattern that
    explicitly shows the sign extension in the RTL, with the modes adjusted
    accordingly, no longer emits the sext.w insn. I also generalized the 
pattern to
    support both sign and zero extension. These changes have been reflected
    on the total store ordering memory consistency model as well. As Zalrsc
    doesn't support zero extending load-acquire instructions, I introduced a new
    iterator, ensuring zero extend is limited to !TARGET_ZALRSC for load.
    
    The addi and lw are combined into lw a0,4(a5) by adjusting the memory
    operand constraint to handle offsets in the load patterns. The validity of
    the memory operand constraint depends on the value of operand 2 - the
    memory model. I introduced new constraint alternatives, such that the
    behavior of the memory operand constraint is triggered on whether the
    memory model acquire is being used or not and the Zalrsc or non-Zalrsc
    targets accordingly. Similar changes were made for the store patterns
    where the inefficient address arithmetic problem was also present.
    
            PR target/124741
    
    gcc/
            * config/riscv/constraints.md (B1, B2, B3, B4): New constraints for
            atomic loads with and without ZALASR & MEMMODEL_ACQUIRE.
            * config/riscv/iterators.md (cond_extend): New iterator to for use
            in extending atomic loads.
            * config/riscv/sync-rvwmo.md (atomic_load_rvwmo<mode>): Adjust
            contraints to enable folding small offsets into memory load.
            (atomic_store_rvwmo): Likewise.
            (extending atomic_load_rvwmo): New pattern.
            * config/riscv/sync-ztso.md (atomic_load_ztso<mode>): Adjust
            constraints to enable folding small offsets into memory load.
            (atomic_store_ztso): Likewise.
            (extending atomic_load_ztso): New pattern.
    
    gcc/testsuite/
            * gcc.target/riscv/load-zalasr.c: Testcases for atomic load compiled
            with rv64 and zalasr ext.
            * gcc.target/riscv/load.c: Testcases for atomic load compiled with
            rv64.
            * gcc.target/riscv/load32-zalasr.c: Testcases for atomic load
            compiled with rv32 and zalasr ext.
            * gcc.target/riscv/load32.c: Testcases for atomic load compiled with
            rv32.
            * gcc.target/riscv/store-zalasr.c: Testcases for atomic store
            compiled with rv64 and zalasr ext.
            * gcc.target/riscv/store.c: Testcases for atomic store compiled
            with rv64.
            * gcc.target/riscv/store32-zalasr.c: Testcases for atomic store
            compiled with rv32 and zalasr ext.
            * gcc.target/riscv/store32.c: Testcases for atomic store compiled
            with rv32.
    
    Co-authored-by: Jeff Law <[email protected]>

Diff:
---
 gcc/config/riscv/constraints.md                 |  26 +++
 gcc/config/riscv/iterators.md                   |   3 +
 gcc/config/riscv/sync-rvwmo.md                  |  43 ++++-
 gcc/config/riscv/sync-ztso.md                   |  31 +++-
 gcc/testsuite/gcc.target/riscv/load-zalasr.c    | 201 ++++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/load.c           | 197 +++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/load32-zalasr.c  | 161 +++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/load32.c         | 157 ++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/store-zalasr.c   | 122 ++++++++++++++
 gcc/testsuite/gcc.target/riscv/store.c          | 122 ++++++++++++++
 gcc/testsuite/gcc.target/riscv/store32-zalasr.c | 105 +++++++++++++
 gcc/testsuite/gcc.target/riscv/store32.c        | 106 +++++++++++++
 12 files changed, 1263 insertions(+), 11 deletions(-)

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 8051c1e330b1..d9fc9704ef57 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -145,6 +145,32 @@
   (and (match_code "mem")
        (match_test "GET_CODE(XEXP(op,0)) == REG")))
 
+(define_constraint "B1"
+  "Memory models that can match with A for load."
+  (and (match_code "const_int")
+       (and (match_test "ival == MEMMODEL_ACQUIRE")
+           (match_test "TARGET_ZALASR"))))
+
+(define_constraint "B2"
+  "Memory models that can match with m for load."
+  (and (match_code "const_int")
+       (ior (match_test "ival != MEMMODEL_ACQUIRE")
+           (match_test "!TARGET_ZALASR"))))
+
+(define_constraint "B3"
+  "Memory models that can match with A for store."
+  (and (match_code "const_int")
+       (and (ior (match_test "ival == MEMMODEL_RELEASE")
+                (match_test "ival == MEMMODEL_SEQ_CST"))
+            (match_test "TARGET_ZALASR"))))
+
+(define_constraint "B4"
+  "Memory models that can match with m for store."
+  (and (match_code "const_int")
+       (ior (and (match_test "ival != MEMMODEL_RELEASE")
+                 (match_test "ival != MEMMODEL_SEQ_CST"))
+            (match_test "!TARGET_ZALASR"))))
+
 (define_constraint "S"
   "A constraint that matches an absolute symbolic address."
   (match_operand 0 "absolute_symbolic_operand"))
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 076911e5e7f1..dc25dfd2e99d 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -207,6 +207,9 @@
 ;; This code iterator allows signed and unsigned widening multiplications
 ;; to use the same template.
 (define_code_iterator any_extend [sign_extend zero_extend])
+
+(define_code_iterator cond_extend [sign_extend (zero_extend "!TARGET_ZALASR")])
+
 (define_code_attr extend_name [
   (sign_extend "extend") (zero_extend "zero_extend")
 ])
diff --git a/gcc/config/riscv/sync-rvwmo.md b/gcc/config/riscv/sync-rvwmo.md
index 3d4093888376..5519f2ac015d 100644
--- a/gcc/config/riscv/sync-rvwmo.md
+++ b/gcc/config/riscv/sync-rvwmo.md
@@ -47,10 +47,10 @@
 ;; Atomic memory operations.
 
 (define_insn "atomic_load_rvwmo<mode>"
-  [(set (match_operand:ANYI 0 "register_operand" "=r")
+  [(set (match_operand:ANYI 0 "register_operand" "=r,r")
        (unspec_volatile:ANYI
-           [(match_operand:ANYI 1 "memory_operand" "A")
-            (match_operand:SI 2 "const_int_operand")]  ;; model
+           [(match_operand:ANYI 1 "memory_operand" "m,A")
+            (match_operand:SI 2 "const_int_operand" "B2,B1")]
         UNSPECV_ATOMIC_LOAD))]
   "!TARGET_ZTSO"
   {
@@ -74,13 +74,43 @@
                      : is_mm_acquire (memmodel_from_int (INTVAL 
(operands[2]))) ? 8
                      : 4)"))])
 
+(define_insn "atomic_load_rvwmo<X:mode><SUBX:mode><code>"
+  [(set (match_operand:X 0 "register_operand" "=r,r")
+       (cond_extend:X
+           (unspec_volatile:SUBX
+               [(match_operand:SUBX 1 "memory_operand" "m,A")
+               (match_operand:SUBX 2 "const_int_operand" "B2,B1")]
+           UNSPECV_ATOMIC_LOAD)))]
+  "!TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+            "<SUBX:load><u>\t%0,%1\;"
+            "fence\tr,rw";
+    if (TARGET_ZALASR && model == MEMMODEL_ACQUIRE)
+      return "<SUBX:load><u>.aq\t%0,%1";
+    if (model == MEMMODEL_ACQUIRE)
+      return "<SUBX:load><u>\t%0,%1\;"
+            "fence\tr,rw";
+    else
+      return "<SUBX:load><u>\t%0,%1";
+  }
+  [(set_attr "type" "multi")
+   (set (attr "length")
+       (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) 
? 12
+                     : is_mm_acquire (memmodel_from_int (INTVAL 
(operands[2]))) ? 8
+                     : 4)"))])
+
 ;; 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:ANYI 0 "memory_operand" "=A")
+  [(set (match_operand:ANYI 0 "memory_operand" "=m,A")
        (unspec_volatile:ANYI
-           [(match_operand:ANYI 1 "reg_or_0_operand" "rJ")
-            (match_operand:SI 2 "const_int_operand")]  ;; model
+           [(match_operand:ANYI 1 "reg_or_0_operand" "rJ,rJ")
+            (match_operand:SI 2 "const_int_operand" "B4,B3")]
         UNSPECV_ATOMIC_STORE))]
   "!TARGET_ZTSO"
   {
@@ -90,7 +120,6 @@
     if (TARGET_ZALASR
        && (model == MEMMODEL_RELEASE || model == MEMMODEL_SEQ_CST))
       return "<store>.rl\t%z1,%0";
-
     if (model == MEMMODEL_SEQ_CST)
       return "fence\trw,w\;"
             "<store>\t%z1,%0\;"
diff --git a/gcc/config/riscv/sync-ztso.md b/gcc/config/riscv/sync-ztso.md
index 9bdd9e291d92..154ff1a91af4 100644
--- a/gcc/config/riscv/sync-ztso.md
+++ b/gcc/config/riscv/sync-ztso.md
@@ -43,7 +43,7 @@
 (define_insn "atomic_load_ztso<mode>"
   [(set (match_operand:ANYI 0 "register_operand" "=r")
        (unspec_volatile:ANYI
-           [(match_operand:ANYI 1 "memory_operand" "A")
+           [(match_operand:ANYI 1 "memory_operand" "m")
             (match_operand:SI 2 "const_int_operand")]  ;; model
         UNSPECV_ATOMIC_LOAD))]
   "TARGET_ZTSO"
@@ -64,12 +64,35 @@
        (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) 
? 8
                      : 4)"))])
 
+(define_insn "atomic_load_ztso<X:mode><SUBX:mode><code>"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (any_extend:X
+           (unspec_volatile:SUBX
+               [(match_operand:SUBX 1 "memory_operand" "m")
+               (match_operand:SUBX 2 "const_int_operand")]
+           UNSPECV_ATOMIC_LOAD)))]
+  "TARGET_ZTSO"
+  {
+    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+    model = memmodel_base (model);
+
+    if (model == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+             "<SUBX:load><u>\t%0,%1";
+    else
+      return "<SUBX:load><u>\t%0,%1";
+  }
+  [(set_attr "type" "multi")
+   (set (attr "length")
+        (symbol_ref "(is_mm_seq_cst (memmodel_from_int (INTVAL (operands[2]))) 
? 8
+                      : 4)"))])
+
 
 (define_insn "atomic_store_ztso<mode>"
-  [(set (match_operand:ANYI 0 "memory_operand" "=A")
+  [(set (match_operand:ANYI 0 "memory_operand" "=m,A")
        (unspec_volatile:ANYI
-           [(match_operand:ANYI 1 "reg_or_0_operand" "rJ")
-            (match_operand:SI 2 "const_int_operand")]  ;; model
+           [(match_operand:ANYI 1 "reg_or_0_operand" "rJ,rJ")
+            (match_operand:SI 2 "const_int_operand" "B4,B3")]  ;; model
         UNSPECV_ATOMIC_STORE))]
   "TARGET_ZTSO"
   {
diff --git a/gcc/testsuite/gcc.target/riscv/load-zalasr.c 
b/gcc/testsuite/gcc.target/riscv/load-zalasr.c
new file mode 100644
index 000000000000..10638b8a738b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/load-zalasr.c
@@ -0,0 +1,201 @@
+/* { dg-do compile { target rv64 } } */
+/* { dg-options "-march=rv64gc_zalasr -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Og" "-Oz" } } */
+
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_zero_t;
+
+typedef struct
+{
+  char pad;
+  signed char repr;
+} qi_sign_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_zero_t;
+
+typedef struct
+{
+  short pad;
+  short repr;
+} hi_sign_t;
+
+typedef struct
+{
+  int pad;
+  int repr;
+} si_sign_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_zero_t;
+
+
+
+/*
+**atomic_load_qi_zero:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     andi    [a-z][0-9]+,[a-z][0-9]+,0xff
+**     ret
+*/
+unsigned atomic_load_qi_zero (const qi_zero_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_sign:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_qi_sign (const qi_sign_t *a) {
+  signed char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_zero:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     slli    [a-z][0-9]+,[a-z][0-9]+,48
+**     srli    [a-z][0-9]+,[a-z][0-9]+,48
+**     ret
+*/
+unsigned atomic_load_hi_zero (const hi_zero_t *a) {
+  unsigned short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_sign:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_hi_sign (const hi_sign_t *a) {
+  short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_sign:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_si_sign (const si_sign_t *a) {
+  int r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_zero:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_si_zero (const si_zero_t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+
+typedef struct
+{
+  int pad;
+  unsigned long long repr;
+} di_t;
+
+typedef struct
+{
+  int pad;
+  unsigned char repr;
+} qi_di_t;
+
+
+/*
+**atomic_load_di:
+**     ld      [a-z][0-9]+,8\([a-z][0-9]+\)
+**     ret
+*/
+unsigned long long atomic_load_di (const di_t *a) {
+  unsigned long long r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_di:
+**     lb      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     andi    [a-z][0-9]+,[a-z][0-9]+,0xff
+**     ret
+*/
+unsigned long long atomic_load_qi_di (const qi_di_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} t;
+
+
+/*
+**atomic_load_relaxed:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_relaxed (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_acquire:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     lw.aq   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_acquire (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE);
+  return r;
+}
+
+/*
+**atomic_load_seqcst:
+**     fence   rw,rw
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_seqcst (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST);
+  return r;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/load.c 
b/gcc/testsuite/gcc.target/riscv/load.c
new file mode 100644
index 000000000000..8a917888203e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/load.c
@@ -0,0 +1,197 @@
+/* { dg-do compile { target rv64 } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Os" "-Og" "-Oz" } } */
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_zero_t;
+
+typedef struct
+{
+  char pad;
+  signed char repr;
+} qi_sign_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_zero_t;
+
+typedef struct
+{
+  short pad;
+  short repr;
+} hi_sign_t;
+
+typedef struct
+{
+  int pad;
+  int repr;
+} si_sign_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_zero_t;
+
+
+
+/*
+**atomic_load_qi_zero:
+**     lbu     [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_qi_zero (const qi_zero_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_sign:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_qi_sign (const qi_sign_t *a) {
+  signed char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_zero:
+**     lhu     [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_hi_zero (const hi_zero_t *a) {
+  unsigned short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_sign:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_hi_sign (const hi_sign_t *a) {
+  short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_sign:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_si_sign (const si_sign_t *a) {
+  int r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_zero:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_si_zero (const si_zero_t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+
+typedef struct
+{
+  int pad;
+  unsigned long long repr;
+} di_t;
+
+typedef struct
+{
+  int pad;
+  unsigned char repr;
+} qi_di_t;
+
+
+/*
+**atomic_load_di:
+**     ld      [a-z][0-9]+,8\([a-z][0-9]+\)
+**     ret
+*/
+unsigned long long atomic_load_di (const di_t *a) {
+  unsigned long long r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_di:
+**     lbu     [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned long long atomic_load_qi_di (const qi_di_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} t;
+
+
+/*
+**atomic_load_relaxed:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_relaxed (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_acquire:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_acquire (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE);
+  return r;
+}
+
+
+/*
+**atomic_load_seqcst:
+**     fence   rw,rw
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_seqcst (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST);
+  return r;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/load32-zalasr.c 
b/gcc/testsuite/gcc.target/riscv/load32-zalasr.c
new file mode 100644
index 000000000000..9a3756fb66a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/load32-zalasr.c
@@ -0,0 +1,161 @@
+/* { dg-do compile { target rv32 } } */
+/* { dg-options "-march=rv32gc_zalasr -mabi=ilp32" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_zero_t;
+
+typedef struct
+{
+  char pad;
+  signed char repr;
+} qi_sign_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_zero_t;
+
+typedef struct
+{
+  short pad;
+  short repr;
+} hi_sign_t;
+
+typedef struct
+{
+  int pad;
+  int repr;
+} si_sign_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_zero_t;
+
+
+/*
+**atomic_load_qi_zero:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     andi    [a-z][0-9]+,[a-z][0-9]+,0xff
+**     ret
+*/
+unsigned atomic_load_qi_zero (const qi_zero_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_sign:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_qi_sign (const qi_sign_t *a) {
+  signed char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_zero:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     slli    [a-z][0-9]+,[a-z][0-9]+,16
+**     srli    [a-z][0-9]+,[a-z][0-9]+,16
+**     ret
+*/
+unsigned atomic_load_hi_zero (const hi_zero_t *a) {
+  unsigned short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_sign:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_hi_sign (const hi_sign_t *a) {
+  short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_sign:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_si_sign (const si_sign_t *a) {
+  int r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_zero:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_si_zero (const si_zero_t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} t;
+
+
+/*
+**atomic_load_relaxed:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_relaxed (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_acquire:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     lw.aq   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_acquire (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE);
+  return r;
+}
+
+
+/*
+**atomic_load_seqcst:
+**     fence   rw,rw
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_seqcst (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST);
+  return r;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/load32.c 
b/gcc/testsuite/gcc.target/riscv/load32.c
new file mode 100644
index 000000000000..a0729ffd3cd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/load32.c
@@ -0,0 +1,157 @@
+/* { dg-do compile { target rv32 } } */
+/* { dg-options "-march=rv32gc -mabi=ilp32" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Og" "-Oz" } } */
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_zero_t;
+
+typedef struct
+{
+  char pad;
+  signed char repr;
+} qi_sign_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_zero_t;
+
+typedef struct
+{
+  short pad;
+  short repr;
+} hi_sign_t;
+
+typedef struct
+{
+  int pad;
+  int repr;
+} si_sign_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_zero_t;
+
+
+/*
+**atomic_load_qi_zero:
+**     lbu     [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_qi_zero (const qi_zero_t *a) {
+  unsigned char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_qi_sign:
+**     lb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_qi_sign (const qi_sign_t *a) {
+  signed char r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_zero:
+**     lhu     [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_hi_zero (const hi_zero_t *a) {
+  unsigned short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_hi_sign:
+**     lh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_hi_sign (const hi_sign_t *a) {
+  short r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_sign:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+int atomic_load_si_sign (const si_sign_t *a) {
+  int r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_si_zero:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_si_zero (const si_zero_t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} t;
+
+
+/*
+**atomic_load_relaxed:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+unsigned atomic_load_relaxed (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_RELAXED);
+  return r;
+}
+
+
+/*
+**atomic_load_acquire:
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_acquire (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_ACQUIRE);
+  return r;
+}
+
+
+/*
+**atomic_load_seqcst:
+**     fence   rw,rw
+**     lw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   r,rw
+**     ret
+*/
+unsigned atomic_load_seqcst (const t *a) {
+  unsigned r;
+  __atomic_load (&a->repr, &r, __ATOMIC_SEQ_CST);
+  return r;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/store-zalasr.c 
b/gcc/testsuite/gcc.target/riscv/store-zalasr.c
new file mode 100644
index 000000000000..d2f5f0103750
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/store-zalasr.c
@@ -0,0 +1,122 @@
+/* { dg-do compile { target rv64 } } */
+/* { dg-options "-march=rv64gc_zalasr -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_s_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_s_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_s_t;
+
+
+/*
+**atomic_store_qi:
+**     sb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_qi (qi_s_t *a, unsigned char val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_hi:
+**     sh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_hi (hi_s_t *a, unsigned short val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_si:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_si (si_s_t *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned long long repr;
+} di_s_t;
+
+
+/*
+**atomic_store_di:
+**     sd      [a-z][0-9]+,8\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_di (di_s_t *a, unsigned long long val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} s_mm;
+
+
+/*
+**atomic_store_relaxed:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_relaxed (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_release:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     sw.rl   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_release (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELEASE);
+}
+
+
+/*
+**atomic_store_seqcst:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     sw.rl   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_seqcst (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/store.c 
b/gcc/testsuite/gcc.target/riscv/store.c
new file mode 100644
index 000000000000..d71756e92682
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/store.c
@@ -0,0 +1,122 @@
+/* { dg-do compile { target rv64 } } */
+/* { dg-options "-march=rv64gc -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_s_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_s_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_s_t;
+
+
+/*
+**atomic_store_qi:
+**     sb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_qi (qi_s_t *a, unsigned char val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_hi:
+**     sh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_hi (hi_s_t *a, unsigned short val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_si:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_si (si_s_t *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned long long repr;
+} di_s_t;
+
+
+/*
+**atomic_store_di:
+**     sd      [a-z][0-9]+,8\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_di (di_s_t *a, unsigned long long val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} s_mm;
+
+
+/*
+**atomic_store_relaxed:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_relaxed (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_release:
+**     fence   rw,w
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_release (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELEASE);
+}
+
+
+/*
+**atomic_store_seqcst:
+**     fence   rw,w
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   rw,rw
+**     ret
+*/
+void
+atomic_store_seqcst (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/store32-zalasr.c 
b/gcc/testsuite/gcc.target/riscv/store32-zalasr.c
new file mode 100644
index 000000000000..d4e37e7169f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/store32-zalasr.c
@@ -0,0 +1,105 @@
+/* { dg-do compile { target rv32 } } */
+/* { dg-options "-march=rv32gc_zalasr -mabi=ilp32" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_s_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_s_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_s_t;
+
+
+/*
+**atomic_store_qi:
+**     sb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_qi (qi_s_t *a, unsigned char val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_hi:
+**     sh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_hi (hi_s_t *a, unsigned short val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_si:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_si (si_s_t *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} s_mm;
+
+
+/*
+**atomic_store_relaxed:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_relaxed (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_release:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     sw.rl   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_release (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELEASE);
+}
+
+
+/*
+**atomic_store_seqcst:
+**     addi    [a-z][0-9]+,[a-z][0-9]+,4
+**     sw.rl   [a-z][0-9]+,0\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_seqcst (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/store32.c 
b/gcc/testsuite/gcc.target/riscv/store32.c
new file mode 100644
index 000000000000..7818852f9094
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/store32.c
@@ -0,0 +1,106 @@
+/* { dg-do compile { target rv32 } } */
+/* { dg-options "-march=rv32gc -mabi=ilp32" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" } } */
+
+typedef struct
+{
+  char pad;
+  unsigned char repr;
+} qi_s_t;
+
+typedef struct
+{
+  short pad;
+  unsigned short repr;
+} hi_s_t;
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} si_s_t;
+
+
+/*
+**atomic_store_qi:
+**     sb      [a-z][0-9]+,1\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_qi (qi_s_t *a, unsigned char val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_hi:
+**     sh      [a-z][0-9]+,2\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_hi (hi_s_t *a, unsigned short val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_si:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_si (si_s_t *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+
+
+typedef struct
+{
+  int pad;
+  unsigned repr;
+} s_mm;
+
+
+/*
+**atomic_store_relaxed:
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_relaxed (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELAXED);
+}
+
+
+/*
+**atomic_store_release:
+**     fence   rw,w
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     ret
+*/
+void
+atomic_store_release (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_RELEASE);
+}
+
+
+/*
+**atomic_store_seqcst:
+**     fence   rw,w
+**     sw      [a-z][0-9]+,4\([a-z][0-9]+\)
+**     fence   rw,rw
+**     ret
+*/
+void
+atomic_store_seqcst (s_mm *a, unsigned val)
+{
+  __atomic_store (&a->repr, &val, __ATOMIC_SEQ_CST);
+}

Reply via email to