diff mbox series

RISC-V: Add vlm/vsm C/C++ API intrinsics support

Message ID 20230119060749.6812-1-juzhe.zhong@rivai.ai
State New
Headers show
Series RISC-V: Add vlm/vsm C/C++ API intrinsics support | expand

Commit Message

juzhe.zhong@rivai.ai Jan. 19, 2023, 6:07 a.m. UTC
From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>

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.

---
 .../riscv/riscv-vector-builtins-bases.cc      |  6 +-
 .../riscv/riscv-vector-builtins-bases.h       |  2 +
 .../riscv/riscv-vector-builtins-functions.def |  2 +
 .../riscv/riscv-vector-builtins-shapes.cc     |  3 +-
 .../riscv/riscv-vector-builtins-types.def     | 15 ++++
 gcc/config/riscv/riscv-vector-builtins.cc     | 43 ++++++++++-
 gcc/config/riscv/vector.md                    | 23 +++++-
 .../g++.target/riscv/rvv/base/vsm-1.C         | 40 ++++++++++
 gcc/testsuite/g++.target/riscv/rvv/rvv.exp    | 44 +++++++++++
 .../gcc.target/riscv/rvv/base/vlm_vsm-1.c     | 75 +++++++++++++++++++
 .../gcc.target/riscv/rvv/base/vlm_vsm-2.c     | 75 +++++++++++++++++++
 .../gcc.target/riscv/rvv/base/vlm_vsm-3.c     | 75 +++++++++++++++++++
 12 files changed, 395 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C
 create mode 100644 gcc/testsuite/g++.target/riscv/rvv/rvv.exp
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c

Comments

Kito Cheng Jan. 27, 2023, 12:49 p.m. UTC | #1
committed, thanks!

On Thu, Jan 19, 2023 at 2:08 PM <juzhe.zhong@rivai.ai> wrote:

> From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
>
> 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.
>
> ---
>  .../riscv/riscv-vector-builtins-bases.cc      |  6 +-
>  .../riscv/riscv-vector-builtins-bases.h       |  2 +
>  .../riscv/riscv-vector-builtins-functions.def |  2 +
>  .../riscv/riscv-vector-builtins-shapes.cc     |  3 +-
>  .../riscv/riscv-vector-builtins-types.def     | 15 ++++
>  gcc/config/riscv/riscv-vector-builtins.cc     | 43 ++++++++++-
>  gcc/config/riscv/vector.md                    | 23 +++++-
>  .../g++.target/riscv/rvv/base/vsm-1.C         | 40 ++++++++++
>  gcc/testsuite/g++.target/riscv/rvv/rvv.exp    | 44 +++++++++++
>  .../gcc.target/riscv/rvv/base/vlm_vsm-1.c     | 75 +++++++++++++++++++
>  .../gcc.target/riscv/rvv/base/vlm_vsm-2.c     | 75 +++++++++++++++++++
>  .../gcc.target/riscv/rvv/base/vlm_vsm-3.c     | 75 +++++++++++++++++++
>  12 files changed, 395 insertions(+), 8 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/base/vsm-1.C
>  create mode 100644 gcc/testsuite/g++.target/riscv/rvv/rvv.exp
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlm_vsm-3.c
>
> diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc
> b/gcc/config/riscv/riscv-vector-builtins-bases.cc
> index af66b016b49..0da4797d272 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 79684bcb50d..28151a8d8d2 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 e5ebb7d829c..63aa8fe32c8 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 0332c031ce4..76cf14a8cc4 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 6a867c99987..f86d8592c36 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 47e01b647f8..f95fe0d58d5 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)
>      \
> @@ -462,9 +484,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:
> @@ -883,8 +915,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 37cf4d6bcbf..48414e200cf 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)))
>
> @@ -694,7 +694,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
> @@ -709,6 +709,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 00000000000..60656cc353f
> --- /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 00000000000..249530580d7
> --- /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 00000000000..f2f4cc97e1b
> --- /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 00000000000..66e687fd8bf
> --- /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 00000000000..58ca73c10a2
> --- /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 } } */
> --
> 2.36.3
>
>
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index af66b016b49..0da4797d272 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 79684bcb50d..28151a8d8d2 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 e5ebb7d829c..63aa8fe32c8 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 0332c031ce4..76cf14a8cc4 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 6a867c99987..f86d8592c36 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 47e01b647f8..f95fe0d58d5 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)                         \
@@ -462,9 +484,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:
@@ -883,8 +915,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 37cf4d6bcbf..48414e200cf 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)))
 
@@ -694,7 +694,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
@@ -709,6 +709,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 00000000000..60656cc353f
--- /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 00000000000..249530580d7
--- /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 00000000000..f2f4cc97e1b
--- /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 00000000000..66e687fd8bf
--- /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 00000000000..58ca73c10a2
--- /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 } } */