aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJu-Zhe Zhong <juzhe.zhong@rivai.ai>2023-01-19 14:07:49 +0800
committerKito Cheng <kito.cheng@sifive.com>2023-01-27 20:44:37 +0800
commitab39fa8c8fd72cc77f13ece3d6129760edfcfb8a (patch)
tree352f93c7e41cb479f1ca79a356392475612c26f7
parentd324d56221d68bd965ac5fc2c3e0eba48076bf60 (diff)
downloadgcc-ab39fa8c8fd72cc77f13ece3d6129760edfcfb8a.zip
gcc-ab39fa8c8fd72cc77f13ece3d6129760edfcfb8a.tar.gz
gcc-ab39fa8c8fd72cc77f13ece3d6129760edfcfb8a.tar.bz2
RISC-V: Add vlm/vsm C/C++ API intrinsics support
gcc/ChangeLog: * config/riscv/riscv-vector-builtins-bases.cc (BASE): Add vlm/vsm support. * config/riscv/riscv-vector-builtins-bases.h: Ditto. * config/riscv/riscv-vector-builtins-functions.def (vlm): New define. (vsm): Ditto. * config/riscv/riscv-vector-builtins-shapes.cc (struct loadstore_def): Add vlm/vsm support. * config/riscv/riscv-vector-builtins-types.def (DEF_RVV_B_OPS): Ditto. (vbool64_t): Ditto. (vbool32_t): Ditto. (vbool16_t): Ditto. (vbool8_t): Ditto. (vbool4_t): Ditto. (vbool2_t): Ditto. (vbool1_t): Ditto. * config/riscv/riscv-vector-builtins.cc (DEF_RVV_B_OPS): Ditto. (rvv_arg_type_info::get_tree_type): Ditto. (function_expander::use_contiguous_load_insn): Ditto. * config/riscv/vector.md (@pred_store<mode>): Ditto. gcc/testsuite/ChangeLog: * g++.target/riscv/rvv/base/vsm-1.C: New test. * g++.target/riscv/rvv/rvv.exp: New test. * gcc.target/riscv/rvv/base/vlm_vsm-1.c: New test. * gcc.target/riscv/rvv/base/vlm_vsm-2.c: New test. * gcc.target/riscv/rvv/base/vlm_vsm-3.c: New test.
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-bases.cc6
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-bases.h2
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-functions.def2
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-shapes.cc3
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-types.def15
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.cc43
-rw-r--r--gcc/config/riscv/vector.md23
-rw-r--r--gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C40
-rw-r--r--gcc/testsuite/g++.target/riscv/rvv/rvv.exp44
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c75
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c75
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c75
12 files changed, 395 insertions, 8 deletions
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index 5cd8e4d..cf6a060 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -84,7 +84,7 @@ public:
}
};
-/* Implements vle.v/vse.v codegen. */
+/* Implements vle.v/vse.v/vlm.v/vsm.v codegen. */
template <bool STORE_P>
class loadstore : public function_base
{
@@ -116,6 +116,8 @@ static CONSTEXPR const vsetvl<false> vsetvl_obj;
static CONSTEXPR const vsetvl<true> vsetvlmax_obj;
static CONSTEXPR const loadstore<false> vle_obj;
static CONSTEXPR const loadstore<true> vse_obj;
+static CONSTEXPR const loadstore<false> vlm_obj;
+static CONSTEXPR const loadstore<true> vsm_obj;
/* Declare the function base NAME, pointing it to an instance
of class <NAME>_obj. */
@@ -126,5 +128,7 @@ BASE (vsetvl)
BASE (vsetvlmax)
BASE (vle)
BASE (vse)
+BASE (vlm)
+BASE (vsm)
} // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
index 5044f57..7af462b 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.h
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
@@ -28,6 +28,8 @@ extern const function_base *const vsetvl;
extern const function_base *const vsetvlmax;
extern const function_base *const vle;
extern const function_base *const vse;
+extern const function_base *const vlm;
+extern const function_base *const vsm;
}
} // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
index 2b4bd47..8bcaf2e 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -42,5 +42,7 @@ DEF_RVV_FUNCTION (vsetvlmax, vsetvlmax, none_preds, i_none_size_void_ops)
/* 7. Vector Loads and Stores. */
DEF_RVV_FUNCTION (vle, loadstore, full_preds, all_v_scalar_const_ptr_ops)
DEF_RVV_FUNCTION (vse, loadstore, none_m_preds, all_v_scalar_ptr_ops)
+DEF_RVV_FUNCTION (vlm, loadstore, none_preds, b_v_scalar_const_ptr_ops)
+DEF_RVV_FUNCTION (vsm, loadstore, none_preds, b_v_scalar_ptr_ops)
#undef DEF_RVV_FUNCTION
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index e796aa8..896704b 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -116,7 +116,8 @@ struct loadstore_def : public build_base
machine_mode mode = TYPE_MODE (type);
int sew = GET_MODE_BITSIZE (GET_MODE_INNER (mode));
/* vop --> vop<sew>. */
- b.append_sew (sew);
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
+ b.append_sew (sew);
/* vop<sew>_v --> vop<sew>_v_<type>. */
if (!overloaded_p)
diff --git a/gcc/config/riscv/riscv-vector-builtins-types.def b/gcc/config/riscv/riscv-vector-builtins-types.def
index 97d5713..a95fad0 100644
--- a/gcc/config/riscv/riscv-vector-builtins-types.def
+++ b/gcc/config/riscv/riscv-vector-builtins-types.def
@@ -36,6 +36,12 @@ along with GCC; see the file COPYING3. If not see
#define DEF_RVV_F_OPS(TYPE, REQUIRE)
#endif
+/* Use "DEF_RVV_B_OPS" macro include all bool value which will be
+ iterated and registered as intrinsic functions. */
+#ifndef DEF_RVV_B_OPS
+#define DEF_RVV_B_OPS(TYPE, REQUIRE)
+#endif
+
DEF_RVV_I_OPS (vint8mf8_t, RVV_REQUIRE_ZVE64)
DEF_RVV_I_OPS (vint8mf4_t, 0)
DEF_RVV_I_OPS (vint8mf2_t, 0)
@@ -92,6 +98,15 @@ DEF_RVV_F_OPS (vfloat64m2_t, RVV_REQUIRE_ELEN_FP_64)
DEF_RVV_F_OPS (vfloat64m4_t, RVV_REQUIRE_ELEN_FP_64)
DEF_RVV_F_OPS (vfloat64m8_t, RVV_REQUIRE_ELEN_FP_64)
+DEF_RVV_B_OPS (vbool64_t, RVV_REQUIRE_ZVE64)
+DEF_RVV_B_OPS (vbool32_t, 0)
+DEF_RVV_B_OPS (vbool16_t, 0)
+DEF_RVV_B_OPS (vbool8_t, 0)
+DEF_RVV_B_OPS (vbool4_t, 0)
+DEF_RVV_B_OPS (vbool2_t, 0)
+DEF_RVV_B_OPS (vbool1_t, 0)
+
#undef DEF_RVV_I_OPS
#undef DEF_RVV_U_OPS
#undef DEF_RVV_F_OPS
+#undef DEF_RVV_B_OPS
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index e959ba3..9023930 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -141,6 +141,12 @@ static const rvv_type_info all_ops[] = {
#include "riscv-vector-builtins-types.def"
{NUM_VECTOR_TYPES, 0}};
+/* A list of all bool will be registered for intrinsic functions. */
+static const rvv_type_info b_ops[] = {
+#define DEF_RVV_B_OPS(TYPE, REQUIRE) {VECTOR_TYPE_##TYPE, REQUIRE},
+#include "riscv-vector-builtins-types.def"
+ {NUM_VECTOR_TYPES, 0}};
+
static CONSTEXPR const rvv_arg_type_info rvv_arg_type_info_end
= rvv_arg_type_info (NUM_BASE_TYPES);
@@ -205,6 +211,22 @@ static CONSTEXPR const rvv_op_info all_v_scalar_ptr_ops
rvv_arg_type_info (RVV_BASE_void), /* Return type */
scalar_ptr_args /* Args */};
+/* A static operand information for vector_type func (const scalar_type *)
+ * function registration. */
+static CONSTEXPR const rvv_op_info b_v_scalar_const_ptr_ops
+ = {b_ops, /* Types */
+ OP_TYPE_v, /* Suffix */
+ rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+ scalar_const_ptr_args /* Args */};
+
+/* A static operand information for void func (scalar_type *, vector_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info b_v_scalar_ptr_ops
+ = {b_ops, /* Types */
+ OP_TYPE_v, /* Suffix */
+ rvv_arg_type_info (RVV_BASE_void), /* Return type */
+ scalar_ptr_args /* Args */};
+
/* A list of all RVV intrinsic functions. */
static function_group_info function_groups[] = {
#define DEF_RVV_FUNCTION(NAME, SHAPE, PREDS, OPS_INFO) \
@@ -463,9 +485,19 @@ rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const
case RVV_BASE_vector_ptr:
return builtin_types[type_idx].vector_ptr;
case RVV_BASE_scalar_ptr:
- return builtin_types[type_idx].scalar_ptr;
+ /* According to the latest rvv-intrinsic-doc, it defines vsm.v intrinsic:
+ __riscv_vsm (uint8_t *base, vbool1_t value, size_t vl). */
+ if (type_idx >= VECTOR_TYPE_vbool64_t && type_idx <= VECTOR_TYPE_vbool1_t)
+ return builtin_types[VECTOR_TYPE_vuint8mf8_t].scalar_ptr;
+ else
+ return builtin_types[type_idx].scalar_ptr;
case RVV_BASE_scalar_const_ptr:
- return builtin_types[type_idx].scalar_const_ptr;
+ /* According to the latest rvv-intrinsic-doc, it defines vlm.v intrinsic:
+ __riscv_vlm_v_b1 (const uint8_t *base, size_t vl). */
+ if (type_idx >= VECTOR_TYPE_vbool64_t && type_idx <= VECTOR_TYPE_vbool1_t)
+ return builtin_types[VECTOR_TYPE_vuint8mf8_t].scalar_const_ptr;
+ else
+ return builtin_types[type_idx].scalar_const_ptr;
case RVV_BASE_void:
return void_type_node;
case RVV_BASE_size:
@@ -884,8 +916,11 @@ function_expander::use_contiguous_load_insn (insn_code icode)
for (int argno = arg_offset; argno < call_expr_nargs (exp); argno++)
add_input_operand (argno);
- add_input_operand (Pmode, get_tail_policy_for_pred (pred));
- add_input_operand (Pmode, get_mask_policy_for_pred (pred));
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
+ {
+ add_input_operand (Pmode, get_tail_policy_for_pred (pred));
+ add_input_operand (Pmode, get_mask_policy_for_pred (pred));
+ }
add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX));
return generate_insn (icode);
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 1dd81ae..8c60eb2 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -198,7 +198,7 @@
;; The index of operand[] to get the merge op.
(define_attr "merge_op_idx" ""
- (cond [(eq_attr "type" "vlde,vimov,vfmov,vldm,vstm,vlds,vmalu")
+ (cond [(eq_attr "type" "vlde,vimov,vfmov,vldm,vlds,vmalu")
(const_int 2)]
(const_int INVALID_ATTRIBUTE)))
@@ -715,7 +715,7 @@
(reg:SI VL_REGNUM)
(reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
(match_operand:VB 3 "vector_move_operand" " m, vr, vr, Wc0, Wc1")
- (match_operand:VB 2 "vector_merge_operand" " vu, vu0, vu, vu, vu")))]
+ (match_operand:VB 2 "vector_merge_operand" " vu, vu, vu, vu, vu")))]
"TARGET_VECTOR"
"@
vlm.v\t%0,%3
@@ -730,6 +730,25 @@
[(set_attr "type" "vldm,vstm,vimov,vmalu,vmalu")
(set_attr "mode" "<MODE>")])
+;; Dedicated pattern for vsm.v instruction since we can't reuse pred_mov pattern to include
+;; memory operand as input which will produce inferior codegen.
+(define_insn "@pred_store<mode>"
+ [(set (match_operand:VB 0 "memory_operand" "+m")
+ (if_then_else:VB
+ (unspec:VB
+ [(match_operand:VB 1 "vector_mask_operand" "Wc1")
+ (match_operand 3 "vector_length_operand" " rK")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ (match_operand:VB 2 "register_operand" " vr")
+ (match_dup 0)))]
+ "TARGET_VECTOR"
+ "vsm.v\t%2,%0"
+ [(set_attr "type" "vstm")
+ (set_attr "mode" "<MODE>")
+ (set (attr "avl_type") (symbol_ref "riscv_vector::NONVLMAX"))
+ (set_attr "vl_op_idx" "3")])
+
;; -------------------------------------------------------------------------------
;; ---- Predicated Broadcast
;; -------------------------------------------------------------------------------
diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C b/gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C
new file mode 100644
index 0000000..60656cc
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+void test___riscv_vsm_v_b1_vl(uint8_t *base, vbool1_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b2_vl(uint8_t *base, vbool2_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b4_vl(uint8_t *base, vbool4_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b8_vl(uint8_t *base, vbool8_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b16_vl(uint8_t *base, vbool16_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b32_vl(uint8_t *base, vbool32_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+void test___riscv_vsm_v_b64_vl(uint8_t *base, vbool64_t value, size_t vl) {
+ __riscv_vsm(base, value, vl);
+}
+
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
diff --git a/gcc/testsuite/g++.target/riscv/rvv/rvv.exp b/gcc/testsuite/g++.target/riscv/rvv/rvv.exp
new file mode 100644
index 0000000..2495305
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/rvv/rvv.exp
@@ -0,0 +1,44 @@
+# Copyright (C) 2023-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Test the front-end for C++.
+# We don't need to test back-end code-gen in RV32 system for C++
+# Because it is already tested in C.
+# Exit immediately if this isn't a RISC-V target.
+if ![istarget riscv*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+set gcc_march "rv64gcv_zfh"
+if [istarget riscv32-*-*] then {
+ set gcc_march "rv32gcv_zfh"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set CFLAGS "-march=$gcc_march -O3"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/base/*.C]] \
+ "" $CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c
new file mode 100644
index 0000000..f2f4cc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+vbool1_t test___riscv_vlm_v_b1_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b1(base, vl);
+}
+
+void test___riscv_vsm_v_b1_vl(uint8_t *base, vbool1_t value, size_t vl) {
+ __riscv_vsm_v_b1(base, value, vl);
+}
+
+vbool2_t test___riscv_vlm_v_b2_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b2(base, vl);
+}
+
+void test___riscv_vsm_v_b2_vl(uint8_t *base, vbool2_t value, size_t vl) {
+ __riscv_vsm_v_b2(base, value, vl);
+}
+
+vbool4_t test___riscv_vlm_v_b4_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b4(base, vl);
+}
+
+void test___riscv_vsm_v_b4_vl(uint8_t *base, vbool4_t value, size_t vl) {
+ __riscv_vsm_v_b4(base, value, vl);
+}
+
+vbool8_t test___riscv_vlm_v_b8_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b8(base, vl);
+}
+
+void test___riscv_vsm_v_b8_vl(uint8_t *base, vbool8_t value, size_t vl) {
+ __riscv_vsm_v_b8(base, value, vl);
+}
+
+vbool16_t test___riscv_vlm_v_b16_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b16(base, vl);
+}
+
+void test___riscv_vsm_v_b16_vl(uint8_t *base, vbool16_t value, size_t vl) {
+ __riscv_vsm_v_b16(base, value, vl);
+}
+
+vbool32_t test___riscv_vlm_v_b32_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b32(base, vl);
+}
+
+void test___riscv_vsm_v_b32_vl(uint8_t *base, vbool32_t value, size_t vl) {
+ __riscv_vsm_v_b32(base, value, vl);
+}
+
+vbool64_t test___riscv_vlm_v_b64_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b64(base, vl);
+}
+
+void test___riscv_vsm_v_b64_vl(uint8_t *base, vbool64_t value, size_t vl) {
+ __riscv_vsm_v_b64(base, value, vl);
+}
+
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c
new file mode 100644
index 0000000..66e687f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+vbool1_t test___riscv_vlm_v_b1_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b1(base, 31);
+}
+
+void test___riscv_vsm_v_b1_vl(uint8_t *base, vbool1_t value, size_t vl) {
+ __riscv_vsm_v_b1(base, value, 31);
+}
+
+vbool2_t test___riscv_vlm_v_b2_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b2(base, 31);
+}
+
+void test___riscv_vsm_v_b2_vl(uint8_t *base, vbool2_t value, size_t vl) {
+ __riscv_vsm_v_b2(base, value, 31);
+}
+
+vbool4_t test___riscv_vlm_v_b4_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b4(base, 31);
+}
+
+void test___riscv_vsm_v_b4_vl(uint8_t *base, vbool4_t value, size_t vl) {
+ __riscv_vsm_v_b4(base, value, 31);
+}
+
+vbool8_t test___riscv_vlm_v_b8_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b8(base, 31);
+}
+
+void test___riscv_vsm_v_b8_vl(uint8_t *base, vbool8_t value, size_t vl) {
+ __riscv_vsm_v_b8(base, value, 31);
+}
+
+vbool16_t test___riscv_vlm_v_b16_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b16(base, 31);
+}
+
+void test___riscv_vsm_v_b16_vl(uint8_t *base, vbool16_t value, size_t vl) {
+ __riscv_vsm_v_b16(base, value, 31);
+}
+
+vbool32_t test___riscv_vlm_v_b32_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b32(base, 31);
+}
+
+void test___riscv_vsm_v_b32_vl(uint8_t *base, vbool32_t value, size_t vl) {
+ __riscv_vsm_v_b32(base, value, 31);
+}
+
+vbool64_t test___riscv_vlm_v_b64_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b64(base, 31);
+}
+
+void test___riscv_vsm_v_b64_vl(uint8_t *base, vbool64_t value, size_t vl) {
+ __riscv_vsm_v_b64(base, value, 31);
+}
+
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*31,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c
new file mode 100644
index 0000000..58ca73c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+
+#include "riscv_vector.h"
+
+vbool1_t test___riscv_vlm_v_b1_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b1(base, 32);
+}
+
+void test___riscv_vsm_v_b1_vl(uint8_t *base, vbool1_t value, size_t vl) {
+ __riscv_vsm_v_b1(base, value, 32);
+}
+
+vbool2_t test___riscv_vlm_v_b2_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b2(base, 32);
+}
+
+void test___riscv_vsm_v_b2_vl(uint8_t *base, vbool2_t value, size_t vl) {
+ __riscv_vsm_v_b2(base, value, 32);
+}
+
+vbool4_t test___riscv_vlm_v_b4_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b4(base, 32);
+}
+
+void test___riscv_vsm_v_b4_vl(uint8_t *base, vbool4_t value, size_t vl) {
+ __riscv_vsm_v_b4(base, value, 32);
+}
+
+vbool8_t test___riscv_vlm_v_b8_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b8(base, 32);
+}
+
+void test___riscv_vsm_v_b8_vl(uint8_t *base, vbool8_t value, size_t vl) {
+ __riscv_vsm_v_b8(base, value, 32);
+}
+
+vbool16_t test___riscv_vlm_v_b16_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b16(base, 32);
+}
+
+void test___riscv_vsm_v_b16_vl(uint8_t *base, vbool16_t value, size_t vl) {
+ __riscv_vsm_v_b16(base, value, 32);
+}
+
+vbool32_t test___riscv_vlm_v_b32_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b32(base, 32);
+}
+
+void test___riscv_vsm_v_b32_vl(uint8_t *base, vbool32_t value, size_t vl) {
+ __riscv_vsm_v_b32(base, value, 32);
+}
+
+vbool64_t test___riscv_vlm_v_b64_vl(const uint8_t *base, size_t vl) {
+ return __riscv_vlm_v_b64(base, 32);
+}
+
+void test___riscv_vsm_v_b64_vl(uint8_t *base, vbool64_t value, size_t vl) {
+ __riscv_vsm_v_b64(base, value, 32);
+}
+
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*m1,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf2,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf4,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vlm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */
+/* { dg-final { scan-assembler-times {vsetvli\s+zero,\s*[a-x0-9]+,\s*e8,\s*mf8,\s*t[au],\s*m[au]\s+vsm\.v\s+v[0-9]+,\s*0\([a-x0-9]+\)} 1 } } */