ewlu / gcc-precommit-ci

2 stars 0 forks source link

Patch Status 26714-RISCV_Support_COREV_XCVMEM_extension-1 #637

Closed github-actions[bot] closed 11 months ago

github-actions[bot] commented 11 months ago

Precommit CI Run information

Logs can be found in the associated Github Actions run: https://github.com/ewlu/gcc-precommit-ci/actions/runs/6812065569

Patch information

Applied patches: 1 -> 1 Associated series: https://patchwork.sourceware.org/project/gcc/list/?series=26714 Last patch applied: https://patchwork.sourceware.org/project/gcc/patch/20231109124219.966619-2-mary.bennett@embecosm.com/ Patch id: 79481

Build Targets

Some targets are built as multilibs. If a build target ends with multilib, please refer to the table below to see all the targets within that multilib. Target name -march string
newlib-rv64gc-lp64d-multilib rv32gc-ilp32d, rv64gc-lp64d
newlib-rv64gcv-lp64d-multilib rv64gcv-lp64d
linux-rv64gcv-lp64d-multilib rv32gcv-ilp32d, rv64gcv-lp64d

Target Information

Target Shorthand -march string
Bitmanip gc_zba_zbb_zbc_zbs

Notes

Testsuite checks are in beta testing stages. Results are unstable and may be inaccurate.

github-actions[bot] commented 11 months ago

Lint Status

The following issues have been found with 26714-RISCV_Support_COREV_XCVMEM_extension-1 using gcc's ./contrib/check_GNU_style.py. Please use your best judgement when resolving these issues. These are only warnings and do not need to be resolved in order to merge your patch. If any of these warnings seem like false-positives that could be guarded against please contact me: patchworks-ci@rivosinc.com.

=== ERROR type #1: blocks of 8 spaces should be replaced with tabs (31 error(s)) ===
gcc/common/config/riscv/riscv-common.cc:1675:12:  {"xcvmem",████████&gcc_options::x_riscv_xcv_subext, MASK_XCVMEM},
gcc/config/riscv/constraints.md:42:0:████████████████████████████████████████████████ MEM_ADDR_SPACE (op))")
gcc/config/riscv/constraints.md:43:0:████████    (not (match_test "((GET_CODE (XEXP (op, 0)) == PLUS
gcc/config/riscv/constraints.md:44:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
gcc/config/riscv/constraints.md:45:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
gcc/config/riscv/constraints.md:46:0:████████████████|| GET_CODE (XEXP (op, 0)) == POST_MODIFY)
gcc/config/riscv/constraints.md:273:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
gcc/config/riscv/constraints.md:274:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 1)) == REG")))
gcc/config/riscv/constraints.md:281:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
gcc/config/riscv/constraints.md:282:0:████████████████&& GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
gcc/config/riscv/corev.md:728:0:████████ (match_operand:ANYI 1 "mem_post_inc" "CV_mem_post"))]
gcc/config/riscv/corev.md:744:0:████████ (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
gcc/config/riscv/corev.md:755:0:████████ (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
gcc/config/riscv/corev.md:766:0:████████ (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
gcc/config/riscv/corev.md:777:0:████████ (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
gcc/config/riscv/corev.md:788:0:████████ (match_operand:ANYI 1 "register_operand" "r"))]
gcc/config/riscv/corev.md:796:0:████████ (match_operand:SF 1 "register_operand" "r"))]
gcc/config/riscv/corev.md:807:0:████████ (match_operand:SF 1 "register_operand" "r"))]
gcc/config/riscv/corev.md:818:0:████████ (match_operand:HF 1 "register_operand" "r"))]
gcc/config/riscv/corev.md:829:0:████████ (match_operand:HF 1 "register_operand" "r"))]
gcc/config/riscv/corev.md:841:0:████████ (match_operand:ANYI 1 "mem_plus_reg" "CV_mem_plus"))]
gcc/config/riscv/corev.md:857:0:████████ (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
gcc/config/riscv/corev.md:868:0:████████ (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
gcc/config/riscv/corev.md:879:0:████████ (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
gcc/config/riscv/corev.md:890:0:████████ (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
gcc/config/riscv/corev.md:909:0:████████(match_operand:SF 1 "register_operand" " r"))]
gcc/config/riscv/corev.md:920:0:████████(match_operand:SF 1 "register_operand" " r"))]
gcc/config/riscv/corev.md:931:0:████████(match_operand:HF 1 "register_operand" " r"))]
gcc/config/riscv/corev.md:942:0:████████(match_operand:HF 1 "register_operand" " r"))]
gcc/config/riscv/predicates.md:240:0:████████████████    && GET_MODE_SIZE (GET_MODE (op)).to_constant () <= 4")))
gcc/config/riscv/riscv.cc:2515:0:████████return addr.type == ADDRESS_REG;

=== ERROR type #2: dot, space, space, end of comment (2 error(s)) ===
gcc/config/riscv/riscv.cc:1365:29:       * or 12-bit immediate.█*/
gcc/config/riscv/riscv.cc:2500:9: * vaild.█*/

=== ERROR type #3: dot, space, space, new sentence (1 error(s)) ===
gcc/config/riscv/riscv.cc:2499:44:/* Check if post inc instructions are valid.█If not, make the address

=== ERROR type #4: lines should not exceed 80 characters (35 error(s)) ===
gcc/config/riscv/constraints.md:41:80:       (and (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
gcc/config/riscv/corev.md:729:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:737:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:746:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:757:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:768:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:779:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:789:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:798:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:809:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:820:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:831:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:842:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:850:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:859:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:870:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:881:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:892:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:902:80:  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
gcc/config/riscv/corev.md:911:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:922:80:   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:933:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/corev.md:944:80:   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
gcc/config/riscv/riscv.cc:1383:80:                  || (TARGET_XCVMEM && riscv_valid_base_register_p (info->offset, mode, strict_p))));
gcc/config/riscv/riscv.cc:2514:80:      if (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)) && riscv_classify_address (&addr, x, mode, strict_p))
gcc/config/riscv/riscv.cc:5639:80:        if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
gcc/config/riscv/riscv.cc:5660:80:        if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
gcc/config/riscv/riscv.md:1765:80:        (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_nonpostinc")))]
gcc/config/riscv/riscv.md:1830:80:  [(set (match_operand:HF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
gcc/config/riscv/riscv.md:2065:80:  [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r,m,  *f,*f,*r,*f,*m,r")
gcc/config/riscv/riscv.md:2077:80:  [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*f,*r,*f,*m,r")
gcc/config/riscv/riscv.md:2100:80:  [(set (match_operand:SI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*f,*r,*m,r")
gcc/config/riscv/riscv.md:2195:80:  [(set (match_operand:SF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
gcc/config/riscv/riscv.md:2231:80:  [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*zmvf,*zmvr,  *r,*r,*m")
gcc/config/riscv/riscv.md:2242:80:  [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")

=== ERROR type #5: there should be exactly one space between function name and parenthesis (1 error(s)) ===
gcc/config/riscv/riscv.opt:418:4:Mask(XCVMEM) Var(riscv_xcv_subext)

Additional information

github-actions[bot] commented 11 months ago

Apply Status

Target Status
Baseline hash: https://github.com/gcc-mirror/gcc/commit/39d81b667373b0033f44702a4b532a4618dde9ff Failed
Tip of tree hash: https://github.com/gcc-mirror/gcc/commit/177ca16b615d285f419cf2ab0337bc01f7be09db Failed

Command

> git am ../patches/*.patch --whitespace=fix -q --3way --empty=drop

Output

.git/rebase-apply/patch:513: indent with spaces.
        return addr.type == ADDRESS_REG;
error: sha1 information is lacking or useless (gcc/common/config/riscv/riscv-common.cc).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 RISC-V: Add support for XCVmem extension in CV32E40P
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
---
 gcc/common/config/riscv/riscv-common.cc       |   2 +
 gcc/config/riscv/constraints.md               |  28 +++
 gcc/config/riscv/corev.md                     | 227 ++++++++++++++++++
 gcc/config/riscv/predicates.md                |  20 +-
 gcc/config/riscv/riscv-protos.h               |  12 +-
 gcc/config/riscv/riscv.cc                     |  48 +++-
 gcc/config/riscv/riscv.h                      |   6 +-
 gcc/config/riscv/riscv.md                     |  46 ++--
 gcc/config/riscv/riscv.opt                    |   2 +
 gcc/doc/sourcebuild.texi                      |   3 +
 .../gcc.target/riscv/cv-mem-lb-compile-1.c    |  23 ++
 .../gcc.target/riscv/cv-mem-lb-compile-2.c    |  24 ++
 .../gcc.target/riscv/cv-mem-lb-compile-3.c    |  16 ++
 .../gcc.target/riscv/cv-mem-lbu-compile-1.c   |  23 ++
 .../gcc.target/riscv/cv-mem-lbu-compile-2.c   |  24 ++
 .../gcc.target/riscv/cv-mem-lbu-compile-3.c   |  16 ++
 .../gcc.target/riscv/cv-mem-lh-compile-1.c    |  23 ++
 .../gcc.target/riscv/cv-mem-lh-compile-2.c    |  24 ++
 .../gcc.target/riscv/cv-mem-lh-compile-3.c    |  16 ++
 .../gcc.target/riscv/cv-mem-lhu-compile-1.c   |  23 ++
 .../gcc.target/riscv/cv-mem-lhu-compile-2.c   |  24 ++
 .../gcc.target/riscv/cv-mem-lhu-compile-3.c   |  16 ++
 .../gcc.target/riscv/cv-mem-lw-compile-1.c    |  38 +++
 .../gcc.target/riscv/cv-mem-lw-compile-2.c    |  38 +++
 .../gcc.target/riscv/cv-mem-lw-compile-3.c    |  22 ++
 .../riscv/cv-mem-operand-compile-1.c          |  19 ++
 .../riscv/cv-mem-operand-compile-2.c          |  20 ++
 .../riscv/cv-mem-operand-compile-3.c          |  28 +++
 .../riscv/cv-mem-operand-compile-4.c          |  21 ++
 .../riscv/cv-mem-operand-compile-5.c          |  25 ++
 .../riscv/cv-mem-operand-compile-6.c          |  21 ++
 .../riscv/cv-mem-operand-compile-7.c          |  24 ++
 .../riscv/cv-mem-operand-compile-8.c          |  18 ++
 .../gcc.target/riscv/cv-mem-sb-compile-1.c    |  36 +++
 .../gcc.target/riscv/cv-mem-sb-compile-2.c    |  38 +++
 .../gcc.target/riscv/cv-mem-sb-compile-3.c    |  30 +++
 .../gcc.target/riscv/cv-mem-sh-compile-1.c    |  36 +++
 .../gcc.target/riscv/cv-mem-sh-compile-2.c    |  38 +++
 .../gcc.target/riscv/cv-mem-sh-compile-3.c    |  30 +++
 .../gcc.target/riscv/cv-mem-sw-compile-1.c    |  36 +++
 .../gcc.target/riscv/cv-mem-sw-compile-2.c    |  38 +++
 .../gcc.target/riscv/cv-mem-sw-compile-3.c    |  30 +++
 gcc/testsuite/lib/target-supports.exp         |  14 ++
 43 files changed, 1216 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-3.c

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 04631e007f0..862674f921b 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -314,6 +314,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"xcvalu", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvelw", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xcvbi", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"xcvmem", ISA_SPEC_CLASS_NONE, 1, 0},

   {"xtheadba", ISA_SPEC_CLASS_NONE, 1, 0},
   {"xtheadbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1671,6 +1672,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"xcvalu",        &gcc_options::x_riscv_xcv_subext, MASK_XCVALU},
   {"xcvelw",        &gcc_options::x_riscv_xcv_subext, MASK_XCVELW},
   {"xcvbi",         &gcc_options::x_riscv_xcv_subext, MASK_XCVBI},
+  {"xcvmem",        &gcc_options::x_riscv_xcv_subext, MASK_XCVMEM},

   {"xtheadba",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBA},
   {"xtheadbb",      &gcc_options::x_riscv_xthead_subext, MASK_XTHEADBB},
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 718b4bd77df..f67bff0940f 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -35,6 +35,17 @@

 ;; General constraints

+(define_memory_constraint "m"
+  "An address that is not base reg + index reg or post modify."
+  (and (match_code "mem")
+       (and (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
+                                                 MEM_ADDR_SPACE (op))")
+            (not (match_test "((GET_CODE (XEXP (op, 0)) == PLUS
+                && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+                && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
+                || GET_CODE (XEXP (op, 0)) == POST_MODIFY)
+       && TARGET_XCVMEM")))))
+
 (define_constraint "I"
   "An I-type 12-bit signed immediate."
   (and (match_code "const_int")
@@ -253,3 +264,20 @@
    A 5-bit signed immediate for CORE-V Immediate Branch."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, -16, 15)")))
+
+(define_constraint "CV_mem_plus"
+  "@internal
+   An address for reg+reg stores and loads"
+  (and (match_code "mem")
+       (match_test "GET_CODE (XEXP (op, 0)) == PLUS
+                && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+                && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG")))
+
+(define_constraint "CV_mem_post"
+  "@internal
+   An address for post-modify or reg+reg stores and loads"
+  (and (match_code "mem")
+       (match_test "(GET_CODE (XEXP (op, 0)) == PLUS
+                && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+                && GET_CODE (XEXP (XEXP (op, 0), 1)) == REG)
+       || GET_CODE (XEXP (op, 0)) == POST_MODIFY")))
diff --git a/gcc/config/riscv/corev.md b/gcc/config/riscv/corev.md
index 7d7b952d817..fef7666e5dd 100644
--- a/gcc/config/riscv/corev.md
+++ b/gcc/config/riscv/corev.md
@@ -720,3 +720,230 @@
   "cv.b%C1imm\t%2,%3,%0"
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
+
+;;CORE-V Post Increment Load/ Store
+;; Post Increment Register-Immediate and Register-Register Load/Store
+(define_insn "cv_load<mode>_postinc"
+   [(set (match_operand:ANYI 0 "register_operand" "=r")
+         (match_operand:ANYI 1 "mem_post_inc" "CV_mem_post"))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+  "cv.<load>\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_load_<optab><SHORT:mode>_postinc"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+     (any_extend:SI (match_operand:SHORT 1 "mem_post_inc" "CV_mem_post")))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+  "cv.<load><u>\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_loadsf_postinc_hardfloat"
+   [(set (match_operand:SF 0 "register_operand" "=r")
+         (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.lw\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_loadsf_postinc_softfloat"
+   [(set (match_operand:SF 0 "register_operand" "=r")
+         (match_operand:SF 1 "mem_post_inc" "CV_mem_post"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.lw\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_loadhf_postinc_hardfloat"
+   [(set (match_operand:HF 0 "register_operand" "=r")
+         (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.lh\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_loadhf_postinc_softfloat"
+   [(set (match_operand:HF 0 "register_operand" "=r")
+         (match_operand:HF 1 "mem_post_inc" "CV_mem_post"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.lh\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_store<mode>_postinc"
+   [(set (match_operand:ANYI 0 "mem_post_inc" "=CV_mem_post")
+         (match_operand:ANYI 1 "register_operand" "r"))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
+  "cv.<store>\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_storesf_postinc_hardfloat"
+   [(set (match_operand:SF 0 "mem_post_inc" "=CV_mem_post")
+         (match_operand:SF 1 "register_operand" "r"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.sw\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_storesf_postinc_softfloat"
+   [(set (match_operand:SF 0 "mem_post_inc" "=CV_mem_post")
+         (match_operand:SF 1 "register_operand" "r"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.sw\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_storehf_postinc_hardfloat"
+   [(set (match_operand:HF 0 "mem_post_inc" "=CV_mem_post")
+         (match_operand:HF 1 "register_operand" "r"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.sh\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_storehf_postinc_softfloat"
+   [(set (match_operand:HF 0 "mem_post_inc" "=CV_mem_post")
+         (match_operand:HF 1 "register_operand" "r"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.sh\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "HF")])
+
+;; Normal Register-Register Load/Store
+(define_insn "cv_load<mode>"
+   [(set (match_operand:ANYI 0 "register_operand" "=r")
+         (match_operand:ANYI 1 "mem_plus_reg" "CV_mem_plus"))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+  "cv.<load>\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_load_<optab><SHORT:mode>"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+     (any_extend:SI (match_operand:SHORT 1 "mem_plus_reg" "CV_mem_plus")))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))"
+  "cv.<load><u>\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_loadsf_hardfloat"
+   [(set (match_operand:SF 0 "register_operand" "=r")
+         (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.lw\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_loadsf_softfloat"
+   [(set (match_operand:SF 0 "register_operand" "=r")
+         (match_operand:SF 1 "mem_plus_reg" "CV_mem_plus"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.lw\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_loadhf_hardfloat"
+   [(set (match_operand:HF 0 "register_operand" "=r")
+         (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.lh\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_loadhf_softfloat"
+   [(set (match_operand:HF 0 "register_operand" "=r")
+         (match_operand:HF 1 "mem_plus_reg" "CV_mem_plus"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[1], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.lh\t%0,%1"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_store<mode>"
+   [(set (match_operand:ANYI 0 "mem_plus_reg" "=CV_mem_plus")
+     (match_operand:ANYI 1 "register_operand" "r"))]
+  "TARGET_XCVMEM && riscv_legitimate_xcvmem_address_p (<MODE>mode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))"
+  "cv.<store>\t%1,%0"
+  [(set_attr "type" "store")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "cv_storesf_hardfloat"
+  [(set (match_operand:SF 0 "mem_plus_reg"     "=CV_mem_plus")
+        (match_operand:SF 1 "register_operand" " r"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.sw\t%1,%0"
+  [(set_attr "move_type" "store")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_storesf_softfloat"
+  [(set (match_operand:SF 0 "mem_plus_reg"     "=CV_mem_plus")
+        (match_operand:SF 1 "register_operand" " r"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (SFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], SFmode)
+       || reg_or_0_operand (operands[1], SFmode))"
+  "cv.sw\t%1,%0"
+  [(set_attr "move_type" "store")
+   (set_attr "mode" "SF")])
+
+(define_insn "cv_storehf_hardfloat"
+  [(set (match_operand:HF 0 "mem_plus_reg"     "=CV_mem_plus")
+        (match_operand:HF 1 "register_operand" " r"))]
+  "TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.sh\t%1,%0"
+  [(set_attr "move_type" "store")
+   (set_attr "mode" "HF")])
+
+(define_insn "cv_storehf_softfloat"
+  [(set (match_operand:HF 0 "mem_plus_reg"     "=CV_mem_plus")
+        (match_operand:HF 1 "register_operand" " r"))]
+  "!TARGET_HARD_FLOAT && TARGET_XCVMEM
+   && riscv_legitimate_xcvmem_address_p (HFmode, XEXP (operands[0], 0), (lra_in_progress || reload_completed))
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  "cv.sh\t%1,%0"
+  [(set_attr "move_type" "store")
+   (set_attr "mode" "HF")])
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 69a6319c2c8..b7ccc6c2239 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -234,8 +234,22 @@
   return false;
 })

+(define_predicate "mem_post_inc"
+  (and (match_code "mem")
+       (match_test "TARGET_XCVMEM && GET_CODE (XEXP (op, 0)) == POST_MODIFY
+                    && GET_MODE_SIZE (GET_MODE (op)).to_constant () <= 4")))
+
+(define_predicate "mem_plus_reg"
+  (and (match_code "mem")
+       (match_test "TARGET_XCVMEM && GET_CODE (XEXP (op, 0)) == PLUS
+           && GET_MODE_SIZE (GET_MODE (op)).to_constant () <= 4
+           && REG_P (XEXP (XEXP (op, 0), 1))
+           && REG_P (XEXP (XEXP (op, 0), 0))")))
+
 (define_predicate "move_operand"
-  (match_operand 0 "general_operand")
+  (and (match_operand 0 "general_operand")
+  (and (not (match_operand 0 "mem_post_inc"))
+       (not (match_operand 0 "mem_plus_reg"))))
 {
   enum riscv_symbol_type symbol_type;

@@ -404,6 +418,10 @@
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), -16, 15)")))

+(define_predicate "nonimmediate_nonpostinc"
+  (and (match_operand 0 "nonimmediate_operand")
+   (not (match_operand 0 "mem_post_inc"))))
+
 ;; Predicates for the V extension.
 (define_special_predicate "vector_length_operand"
   (ior (match_operand 0 "pmode_register_operand")
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index d322b7e80ec..d7085d0338c 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -68,7 +68,8 @@ enum riscv_address_type {
   ADDRESS_REG_WB,
   ADDRESS_LO_SUM,
   ADDRESS_CONST_INT,
-  ADDRESS_SYMBOLIC
+  ADDRESS_SYMBOLIC,
+  ADDRESS_REG_INC
 };

 /* Information about an address described by riscv_address_type.
@@ -91,7 +92,13 @@ enum riscv_address_type {
        is the type of symbol it references.

    ADDRESS_SYMBOLIC
-       SYMBOL_TYPE is the type of symbol that the address references.  */
+       SYMBOL_TYPE is the type of symbol that the address references.
+
+   ADDRESS_REG_INC:
+       A base register + offset address access with post modify side-effect
+       (base register += offset).  The offset is an immediate or index
+       register.
+       */
 struct riscv_address_info {
   enum riscv_address_type type;
   rtx reg;
@@ -101,6 +108,7 @@ struct riscv_address_info {
 };

 /* Routines implemented in riscv.cc.  */
+bool riscv_legitimate_xcvmem_address_p (machine_mode, rtx, bool);
 extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
 extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
 extern int riscv_float_const_rtx_index_for_fli (rtx);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 08ff05dcc3f..b701e1fb08f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1084,7 +1084,7 @@ riscv_regno_mode_ok_for_base_p (int regno,
 enum reg_class
 riscv_index_reg_class ()
 {
-  if (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX)
+  if (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX || TARGET_XCVMEM)
     return GR_REGS;

   return NO_REGS;
@@ -1360,6 +1360,16 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
       info->offset = const0_rtx;
       return riscv_valid_base_register_p (info->reg, mode, strict_p);

+    case POST_MODIFY:
+      /* For instructions using post inc, the offset can either be register
+       * or 12-bit immediate. */
+       info->type = ADDRESS_REG_INC;
+       info->reg = XEXP (x, 0);
+       info->offset = XEXP ((XEXP (x, 1)), 1);
+       return (riscv_valid_base_register_p (info->reg, mode, strict_p)
+       && (riscv_valid_base_register_p (info->offset, mode, strict_p)
+          || riscv_valid_offset_p (info->offset, mode)));
+
     case PLUS:
       /* RVV load/store disallow any offset.  */
       if (riscv_v_ext_mode_p (mode))
@@ -1369,7 +1379,8 @@ riscv_classify_address (struct riscv_address_info *info, rtx x,
       info->reg = XEXP (x, 0);
       info->offset = XEXP (x, 1);
       return (riscv_valid_base_register_p (info->reg, mode, strict_p)
-         && riscv_valid_offset_p (info->offset, mode));
+         && (riscv_valid_offset_p (info->offset, mode)
+         || (TARGET_XCVMEM && riscv_valid_base_register_p (info->offset, mode, strict_p))));

     case LO_SUM:
       /* RVV load/store disallow LO_SUM.  */
@@ -2485,6 +2496,30 @@ riscv_v_adjust_scalable_frame (rtx target, poly_int64 offset, bool epilogue)
   REG_NOTES (insn) = dwarf;
 }

+/* Check if post inc instructions are valid. If not, make the address
+ * vaild. */
+bool
+riscv_legitimate_xcvmem_address_p (machine_mode mode, rtx x, bool strict_p)
+{
+  struct riscv_address_info addr;
+
+  switch (GET_CODE (x))
+    {
+    case POST_MODIFY:
+      if (riscv_classify_address (&addr, x, mode, strict_p))
+   return addr.type == ADDRESS_REG_INC;
+      return false;
+
+    case PLUS:
+      if (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)) && riscv_classify_address (&addr, x, mode, strict_p))
+        return addr.type == ADDRESS_REG;
+      return false;
+
+    default:
+      return false;
+    }
+}
+
 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
    sequence that is valid.  */

@@ -5601,7 +5636,8 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
     switch (addr.type)
       {
       case ADDRESS_REG:
-   output_addr_const (file, riscv_strip_unspec_address (addr.offset));
+   if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
+   else output_addr_const (file, riscv_strip_unspec_address (addr.offset));
    fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
    return;

@@ -5619,6 +5655,12 @@ riscv_print_operand_address (FILE *file, machine_mode mode ATTRIBUTE_UNUSED, rtx
    output_addr_const (file, riscv_strip_unspec_address (x));
    return;

+      case ADDRESS_REG_INC:
+   fprintf (file, "(%s),", reg_names[REGNO (addr.reg)]);
+   if (REG_P (addr.offset)) fprintf (file, "%s", reg_names[REGNO (addr.offset)]);
+   else output_addr_const (file, addr.offset);
+   return;
+
       default:
    gcc_unreachable ();
       }
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 1e9813b4f39..185e7d6ce23 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -44,6 +44,8 @@ along with GCC; see the file COPYING3.  If not see
 #define RISCV_TUNE_STRING_DEFAULT "rocket"
 #endif

+#define TARGET_MEM_CONSTRAINT 'w'
+
 extern const char *riscv_expand_arch (int argc, const char **argv);
 extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv);
 extern const char *riscv_default_mtune (int argc, const char **argv);
@@ -1197,7 +1199,9 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
    e.g. RVVMF64BI vs RVVMF1BI on zvl512b, which is [1, 1] vs [64, 64].  */
 #define MAX_POLY_VARIANT 64

-#define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
+#define HAVE_POST_MODIFY_DISP (TARGET_XTHEADMEMIDX || TARGET_XCVMEM)
 #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX

+#define HAVE_POST_MODIFY_REG TARGET_XCVMEM
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 168c8665a7a..5c9ea62d943 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1663,13 +1663,13 @@

 (define_expand "zero_extendsidi2"
   [(set (match_operand:DI 0 "register_operand")
-   (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
+   (zero_extend:DI (match_operand:SI 1 "nonimmediate_nonpostinc")))]
   "TARGET_64BIT")

 (define_insn_and_split "*zero_extendsidi2_internal"
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
    (zero_extend:DI
-       (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
   "TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
    && !(register_operand (operands[1], SImode)
         && reg_or_subregno (operands[1]) == VL_REGNUM)"
@@ -1691,13 +1691,13 @@
 (define_expand "zero_extendhi<GPR:mode>2"
   [(set (match_operand:GPR    0 "register_operand")
    (zero_extend:GPR
-       (match_operand:HI 1 "nonimmediate_operand")))]
+       (match_operand:HI 1 "nonimmediate_nonpostinc")))]
   "")

 (define_insn_and_split "*zero_extendhi<GPR:mode>2"
   [(set (match_operand:GPR    0 "register_operand"     "=r,r")
    (zero_extend:GPR
-       (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:HI 1 "nonimmediate_nonpostinc" " r,m")))]
   "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
   "@
    #
@@ -1720,13 +1720,13 @@
 (define_expand "zero_extendqi<SUPERQI:mode>2"
   [(set (match_operand:SUPERQI    0 "register_operand")
    (zero_extend:SUPERQI
-       (match_operand:QI 1 "nonimmediate_operand")))]
+       (match_operand:QI 1 "nonimmediate_nonpostinc")))]
   "")

 (define_insn "*zero_extendqi<SUPERQI:mode>2_internal"
   [(set (match_operand:SUPERQI 0 "register_operand"    "=r,r")
    (zero_extend:SUPERQI
-       (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:QI 1 "nonimmediate_nonpostinc" " r,m")))]
   "!TARGET_XTHEADMEMIDX"
   "@
    andi\t%0,%1,0xff
@@ -1745,13 +1745,13 @@
 (define_expand "extendsidi2"
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
    (sign_extend:DI
-       (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
   "TARGET_64BIT")

 (define_insn "*extendsidi2_internal"
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
    (sign_extend:DI
-       (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:SI 1 "nonimmediate_nonpostinc" " r,m")))]
   "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
   "@
    sext.w\t%0,%1
@@ -1762,13 +1762,13 @@

 (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
   [(set (match_operand:SUPERQI 0 "register_operand")
-   (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
+   (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_nonpostinc")))]
   "")

 (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
   [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
    (sign_extend:SUPERQI
-       (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+       (match_operand:SHORT 1 "nonimmediate_nonpostinc" " r,m")))]
   "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
   "@
    #
@@ -1827,7 +1827,7 @@
 })

 (define_insn "*movhf_hardfloat"
-  [(set (match_operand:HF 0 "nonimmediate_operand" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
+  [(set (match_operand:HF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
    (match_operand:HF 1 "move_operand"         " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
   "TARGET_ZFHMIN
    && (register_operand (operands[0], HFmode)
@@ -1838,7 +1838,7 @@
    (set_attr "mode" "HF")])

 (define_insn "*movhf_softfloat"
-  [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
+  [(set (match_operand:HF 0 "nonimmediate_nonpostinc" "=f, r,r,m,*f,*r")
    (match_operand:HF 1 "move_operand"         " f,Gr,m,r,*r,*f"))]
   "!TARGET_ZFHMIN
    && (register_operand (operands[0], HFmode)
@@ -2062,7 +2062,7 @@
 })

 (define_insn "*movdi_32bit"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,  *f,*f,*r,*f,*m,r")
+  [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r,m,  *f,*f,*r,*f,*m,r")
    (match_operand:DI 1 "move_operand"         " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
   "!TARGET_64BIT
    && (register_operand (operands[0], DImode)
@@ -2074,7 +2074,7 @@
    (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])

 (define_insn "*movdi_64bit"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m,  *f,*f,*r,*f,*m,r")
+  [(set (match_operand:DI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*f,*r,*f,*m,r")
    (match_operand:DI 1 "move_operand"         " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))]
   "TARGET_64BIT
    && (register_operand (operands[0], DImode)
@@ -2097,7 +2097,7 @@
 })

 (define_insn "*movsi_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,  *f,*f,*r,*m,r")
+  [(set (match_operand:SI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*f,*r,*m,r")
    (match_operand:SI 1 "move_operand"         " r,T,m,rJ,*r*J,*m,*f,*f,vp"))]
   "(register_operand (operands[0], SImode)
     || reg_or_0_operand (operands[1], SImode))
@@ -2126,7 +2126,7 @@
 })

 (define_insn "*movhi_internal"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m,  *f,*r,r")
+  [(set (match_operand:HI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*r,r")
    (match_operand:HI 1 "move_operand"     " r,T,m,rJ,*r*J,*f,vp"))]
   "(register_operand (operands[0], HImode)
     || reg_or_0_operand (operands[1], HImode))"
@@ -2170,7 +2170,7 @@
 })

 (define_insn "*movqi_internal"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m,  *f,*r,r")
+  [(set (match_operand:QI 0 "nonimmediate_nonpostinc" "=r,r,r, m,  *f,*r,r")
    (match_operand:QI 1 "move_operand"         " r,I,m,rJ,*r*J,*f,vp"))]
   "(register_operand (operands[0], QImode)
     || reg_or_0_operand (operands[1], QImode))"
@@ -2192,7 +2192,7 @@
 })

 (define_insn "*movsf_hardfloat"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
+  [(set (match_operand:SF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
    (match_operand:SF 1 "move_operand"         " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
   "TARGET_HARD_FLOAT
    && (register_operand (operands[0], SFmode)
@@ -2203,7 +2203,7 @@
    (set_attr "mode" "SF")])

 (define_insn "*movsf_softfloat"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
+  [(set (match_operand:SF 0 "nonimmediate_nonpostinc" "= r,r,m")
    (match_operand:SF 1 "move_operand"         " Gr,m,r"))]
   "!TARGET_HARD_FLOAT
    && (register_operand (operands[0], SFmode)
@@ -2228,7 +2228,7 @@
 ;; In RV32, we lack fmv.x.d and fmv.d.x.  Go through memory instead.
 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
 (define_insn "*movdf_hardfloat_rv32"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,   f,f,f,m,m,*zmvf,*zmvr,  *r,*r,*m")
+  [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*zmvf,*zmvr,  *r,*r,*m")
    (match_operand:DF 1 "move_operand"         " f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*m,*r"))]
   "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
    && (register_operand (operands[0], DFmode)
@@ -2239,7 +2239,7 @@
    (set_attr "mode" "DF")])

 (define_insn "*movdf_hardfloat_rv64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
+  [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
    (match_operand:DF 1 "move_operand"         " f,zfli,G,m,f,G,*r,*f,*r*G,*m,*r"))]
   "TARGET_64BIT && TARGET_DOUBLE_FLOAT
    && (register_operand (operands[0], DFmode)
@@ -2250,7 +2250,7 @@
    (set_attr "mode" "DF")])

 (define_insn "*movdf_softfloat"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
+  [(set (match_operand:DF 0 "nonimmediate_nonpostinc" "= r,r, m")
    (match_operand:DF 1 "move_operand"         " rG,m,rG"))]
   "!TARGET_DOUBLE_FLOAT
    && (register_operand (operands[0], DFmode)
@@ -2297,7 +2297,7 @@
    (set_attr "mode" "DF")])

 (define_split
-  [(set (match_operand:MOVE64 0 "nonimmediate_operand")
+  [(set (match_operand:MOVE64 0 "nonimmediate_nonpostinc")
    (match_operand:MOVE64 1 "move_operand"))]
   "reload_completed
    && riscv_split_64bit_move_p (operands[0], operands[1])"
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index d06c0f8f416..5076d049d9f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -415,6 +415,8 @@ Mask(XCVELW) Var(riscv_xcv_subext)

 Mask(XCVBI) Var(riscv_xcv_subext)

+Mask(XCVMEM) Var(riscv_xcv_subext)
+
 TargetVariable
 int riscv_xthead_subext

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 6fee1144238..cd3e58a2508 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2487,6 +2487,9 @@ Test system has support for the CORE-V ELW extension.
 @item cv_bi
 Test system has support for the CORE-V BI extension.

+@item cv_mem
+Test system has support for the CORE-V MEM extension.
+
 @end table

 @subsubsection Other hardware attributes
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-1.c
new file mode 100644
index 00000000000..1850eaa8f92
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n)
+{
+  int char_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    char_sum += array_char[i];
+  }
+
+  return char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-2.c
new file mode 100644
index 00000000000..3d3ad6d43a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n, int j)
+{
+  int char_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    char_sum += *array_char;
+    array_char+=j*sizeof(array_char);
+  }
+
+  return char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-3.c
new file mode 100644
index 00000000000..358e34455d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lb-compile-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooQIsigned (signed char* array_char, int i, int j)
+{
+  return array_char[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-1.c
new file mode 100644
index 00000000000..1edc4402fa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n)
+{
+  int uns_char_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    uns_char_sum += array_uchar[i];
+  }
+
+  return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-2.c
new file mode 100644
index 00000000000..182e7e6ae96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n, int j)
+{
+  int uns_char_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    uns_char_sum += *array_uchar;
+    array_uchar+=j*sizeof(array_uchar);
+  }
+
+  return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-3.c
new file mode 100644
index 00000000000..00099c15b6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lbu-compile-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooQIunsigned (unsigned char* array_uchar, int i, int j)
+{
+  return array_uchar[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lbu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-1.c
new file mode 100644
index 00000000000..a7e74e8978e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n)
+{
+  int short_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    short_sum += array_short[i];
+  }
+
+  return short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-2.c
new file mode 100644
index 00000000000..4ec9672d6ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n, int j)
+{
+  int short_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    short_sum += *array_short;
+    array_short+=j*sizeof(array_short);
+  }
+
+  return short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-3.c
new file mode 100644
index 00000000000..3a9b1a1deb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lh-compile-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int i, int j)
+{
+  return array_short[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-1.c
new file mode 100644
index 00000000000..19963fa706e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n)
+{
+  int uns_short_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    uns_short_sum += array_ushort[i];
+  }
+
+  return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-2.c
new file mode 100644
index 00000000000..9669e575511
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n, int j)
+{
+  int uns_short_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    uns_short_sum += *array_ushort;
+    array_ushort+=j*sizeof(array_ushort);
+  }
+
+  return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-3.c
new file mode 100644
index 00000000000..baa2731aba2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lhu-compile-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int i, int j)
+{
+  return array_ushort[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lhu\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-1.c
new file mode 100644
index 00000000000..3d61fc0f01c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* We don't generate for some optimization levels. TODO: should support for Os,
+   Oz and Og */
+/* { dg-skip-if "" { *-*-* }  { "-O0" "-Os" "-Oz" "-Og" } { "" } } */
+
+/*
+ * Test for post-inc register-immediate loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n)
+{
+  int int_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    int_sum += array_int[i];
+  }
+
+  return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n)
+{
+  int uns_int_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    uns_int_sum += array_uint[i];
+  }
+
+  return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),4" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-2.c
new file mode 100644
index 00000000000..9909981c373
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n, int j)
+{
+  int int_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    int_sum += *array_int;
+    array_int+=j*sizeof(array_int);
+  }
+
+  return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n, int j)
+{
+  int uns_int_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    uns_int_sum += *array_uint;
+    array_uint+=j*sizeof(array_uint);
+  }
+
+  return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-3.c
new file mode 100644
index 00000000000..8864927de9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-lw-compile-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register loads.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i, int j)
+{
+  return array_int[i+j];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i, int j)
+{
+  return array_uint[i+j];
+}
+
+/* { dg-final { scan-assembler-times "cv\\.lw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-1.c
new file mode 100644
index 00000000000..05204b41573
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2" } */
+
+/*
+ * Test for illegal XCVmem specific operand.
+ * Pattern: `(mem:DF (plus:SI (reg reg)))`.
+ */
+
+struct {
+  double a[3];
+} * b;
+int c;
+
+int
+foo (void)
+{
+  b[0].a[c] -= b[0].a[c];
+}
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-2.c
new file mode 100644
index 00000000000..373915f73d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2" } */
+
+/*
+ * Test for illegal XCVmem specific operand.
+ * Pattern: `(mem:DF (post_modify:SI (reg reg)))`.
+ */
+
+int bar (double);
+
+int
+foo (void)
+{
+  double *b;
+  int c = 0;
+  for (;; c++)
+    bar (b[c]);
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-3.c
new file mode 100644
index 00000000000..c622d60cd2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-3.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -g -O2 -Wno-int-conversion" } */
+
+/*
+ * Test for illegal XCVmem specific operand in loads.
+ * Instruction `lbu reg,reg(reg)`.
+ */
+
+int a;
+int bar (char);
+
+int
+foo (void)
+{
+  short *d;
+  char *e = (char *)foo;
+  for (;;) {
+    char c = d++;
+    bar (c);
+    short b = e[0] + b;
+    if (b)
+      a = 5;
+    e += 2;
+  }
+}
+
+/* { dg-final { scan-assembler-not "lbu\t\[a-z\]\[0-99\],\[a-z\]\[0-99\]\\(\[a-z\]\[0-99\]\\)" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-4.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-4.c
new file mode 100644
index 00000000000..4922f9667d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32if_xcvmem" } */
+
+/*
+ * Test for illegal XCVmem specific operand in flw.
+ * Error: illegal operands `flw fa5,a5(a4)'
+ */
+
+int b, e;
+float *m;
+
+int
+foo (void) {
+  m[1] = m[b];
+  m[b] = e;
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "flw\tfa5,a5\\(a4\\)" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-5.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-5.c
new file mode 100644
index 00000000000..140486ce20b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-5.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32" } */
+
+/*
+ * Tests that stores can generate regular reg:imm operands.
+ */
+
+int a[1];
+int b, c, d, e, f;
+float g;
+
+int
+foo (void)
+{
+  int h;
+  for (;; d++)
+    switch (c) {
+    case 8:
+      g = e == f;
+      a[h + d] = g;
+      g = e < f;
+      b = g;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-6.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-6.c
new file mode 100644
index 00000000000..8d6113971a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-6.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+
+/*
+ * Test for illegal XCVmem specific operands in lw.
+ */
+
+int
+fooSIsigned (signed int* array_int)
+{
+  return array_int [3];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint)
+{
+  return array_uint [3];
+}
+
+/* { dg-final { scan-assembler-not "cv\\.lw\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-7.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-7.c
new file mode 100644
index 00000000000..dc61d859988
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-7.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for illegal XCVmem specific operands in register-immediate sw.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i)
+{
+  array_int [3] = i;
+  return array_int [3];
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i)
+{
+  array_uint [3] = i;
+  return array_uint [3];
+}
+
+/* { dg-final { scan-assembler-not "cv\\.sw\t" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-8.c b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-8.c
new file mode 100644
index 00000000000..da7f5166fe7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-operand-compile-8.c
@@ -0,0 +1,18 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem" } */
+
+/*
+ * Test for illegal XCVmem specific operand in sw.
+ */
+
+int a;
+float *b;
+
+int
+foo (void)
+{
+  int c;
+  for (c = 0; c < 10; c++)
+    b[c] = a;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-1.c
new file mode 100644
index 00000000000..596283f41e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n)
+{
+  int char_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_char[i] += char_sum;
+  }
+
+  return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n)
+{
+  int uns_char_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_uchar[i] += uns_char_sum;
+  }
+
+  return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),1" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-2.c
new file mode 100644
index 00000000000..f907eca2fbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int n, int j)
+{
+  int char_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_char += char_sum;
+    array_char+=j*sizeof(array_char);
+  }
+
+  return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int n, int j)
+{
+  int uns_char_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_uchar += uns_char_sum;
+    array_uchar+=j*sizeof(array_uchar);
+  }
+
+  return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-3.c
new file mode 100644
index 00000000000..822573d13af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sb-compile-3.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops -fno-tree-vectorize" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooQIsigned (signed char* array_char, int i, int j)
+{
+  int char_sum = 1;
+
+  array_char[i+j] += char_sum;
+
+  return char_sum;
+}
+
+int
+fooQIunsigned (unsigned char* array_uchar, int i, int j)
+{
+  int uns_char_sum = 1;
+
+  array_uchar[i+j] += uns_char_sum;
+
+  return uns_char_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sb\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-1.c
new file mode 100644
index 00000000000..036836cc419
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n)
+{
+  int short_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_short[i] += short_sum;
+  }
+
+  return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n)
+{
+  int uns_short_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_ushort[i] += uns_short_sum;
+  }
+
+  return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),2" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-2.c
new file mode 100644
index 00000000000..c761137395f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int n, int j)
+{
+  int short_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_short += short_sum;
+    array_short+=j*sizeof(array_short);
+  }
+
+  return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int n, int j)
+{
+  int uns_short_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_ushort += uns_short_sum;
+    array_ushort+=j*sizeof(array_ushort);
+  }
+
+  return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-3.c
new file mode 100644
index 00000000000..3d8e07f9093
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sh-compile-3.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooHIsigned (signed short int* array_short, int i, int j)
+{
+  int short_sum = 1;
+
+  array_short[i+j] = short_sum;
+
+  return short_sum;
+}
+
+int
+fooHIunsigned (unsigned short int* array_ushort, int i, int j)
+{
+  int uns_short_sum = 1;
+
+  array_ushort[i+j] += uns_short_sum;
+
+  return uns_short_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sh\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-1.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-1.c
new file mode 100644
index 00000000000..230022761cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-immediate saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n)
+{
+  int int_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_int[i] += int_sum;
+  }
+
+  return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n)
+{
+  int uns_int_sum = 1;
+
+  for(int i=0; i<n; i++)
+  {
+    array_uint[i] += uns_int_sum;
+  }
+
+  return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),4" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-2.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-2.c
new file mode 100644
index 00000000000..fc5fcba22ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-2.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Os" "-Oz" "-Og" } } */
+
+/*
+ * Test for post-inc register-register saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int n, int j)
+{
+  int int_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_int += int_sum;
+    array_int+=j*sizeof(array_int);
+  }
+
+  return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int n, int j)
+{
+  int uns_int_sum = 1;
+
+  for(int i=0; i<n; i+=j)
+  {
+    *array_uint += uns_int_sum;
+    array_uint+=j*sizeof(array_uint);
+  }
+
+  return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\),\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-3.c b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-3.c
new file mode 100644
index 00000000000..c709f2e5fc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cv-mem-sw-compile-3.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target cv_mem } */
+/* { dg-options "-march=rv32i_xcvmem -mabi=ilp32 -fno-unroll-loops" } */
+/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */
+
+/*
+ * Test for normal register-register saves.
+ */
+
+int
+fooSIsigned (signed int* array_int, int i, int j)
+{
+  int int_sum = 1;
+
+  array_int[i+j] = int_sum;
+
+  return int_sum;
+}
+
+int
+fooSIunsigned (unsigned int* array_uint, int i, int j)
+{
+  int uns_int_sum = 1;
+
+  array_uint[i+j] = uns_int_sum;
+
+  return uns_int_sum;
+}
+
+/* { dg-final { scan-assembler-times "cv\\.sw\t\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\),(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\(\(\?\:t\[0-6\]\|a\[0-7\]\|s\[1-11\]\)\\)" 2 } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 0eae746e848..949fd413ff5 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -13111,6 +13111,20 @@ proc check_effective_target_cv_bi { } {
     } "-march=rv32i_xcvbi" ]
 }

+# Return 1 if the CORE-V MEM extension is available.
+proc check_effective_target_cv_mem { } {
+    if { !([istarget riscv*-*-*]) } {
+         return 0
+     }
+    return [check_no_compiler_messages cv_mem object {
+        void foo (void)
+        {
+          asm ("cv.lw t0, (t1), 4");
+        }
+    } "-march=rv32i_xcvmem" ]
+}
+
+
 proc check_effective_target_loongarch_sx { } {
     return [check_no_compiler_messages loongarch_lsx assembly {
        #if !defined(__loongarch_sx)

Additional information