diff mbox series

RISC-V: Add vcreate intrinsics for RVV tuple types

Message ID 20230912020825.12497-1-xuli1@eswincomputing.com
State New
Headers show
Series RISC-V: Add vcreate intrinsics for RVV tuple types | expand

Commit Message

Li Xu Sept. 12, 2023, 2:08 a.m. UTC
From: xuli <xuli1@eswincomputing.com>

gcc/ChangeLog:

        * config/riscv/riscv-vector-builtins-bases.cc (class vcreate):
        (BASE): New class.
        * config/riscv/riscv-vector-builtins-bases.h: Ditto.
        * config/riscv/riscv-vector-builtins-functions.def (vcreate): Add vcreate support.
        * config/riscv/riscv-vector-builtins-shapes.cc (struct vcreate_def): Ditto.
        (SHAPE): Ditto.
        * config/riscv/riscv-vector-builtins-shapes.h: Ditto.
        * config/riscv/riscv-vector-builtins.cc: Add args type.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/base/tuple_create.c: New test.
---
 .../riscv/riscv-vector-builtins-bases.cc      |  40 ++++++
 .../riscv/riscv-vector-builtins-bases.h       |   1 +
 .../riscv/riscv-vector-builtins-functions.def |   1 +
 .../riscv/riscv-vector-builtins-shapes.cc     |  50 +++++++
 .../riscv/riscv-vector-builtins-shapes.h      |   1 +
 gcc/config/riscv/riscv-vector-builtins.cc     |  12 ++
 .../gcc.target/riscv/rvv/base/tuple_create.c  | 123 ++++++++++++++++++
 7 files changed, 228 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c

Comments

juzhe.zhong@rivai.ai Sept. 12, 2023, 2:16 a.m. UTC | #1
Thanks for support it.
LGTM from my side.
Wait for kito's more comments.



juzhe.zhong@rivai.ai
 
From: Li Xu
Date: 2023-09-12 10:08
To: gcc-patches
CC: kito.cheng; palmer; juzhe.zhong; pan2.li; gaofei; wangfeng; xuli
Subject: [PATCH] RISC-V: Add vcreate intrinsics for RVV tuple types
From: xuli <xuli1@eswincomputing.com>
 
gcc/ChangeLog:
 
        * config/riscv/riscv-vector-builtins-bases.cc (class vcreate):
        (BASE): New class.
        * config/riscv/riscv-vector-builtins-bases.h: Ditto.
        * config/riscv/riscv-vector-builtins-functions.def (vcreate): Add vcreate support.
        * config/riscv/riscv-vector-builtins-shapes.cc (struct vcreate_def): Ditto.
        (SHAPE): Ditto.
        * config/riscv/riscv-vector-builtins-shapes.h: Ditto.
        * config/riscv/riscv-vector-builtins.cc: Add args type.
 
gcc/testsuite/ChangeLog:
 
        * gcc.target/riscv/rvv/base/tuple_create.c: New test.
---
.../riscv/riscv-vector-builtins-bases.cc      |  40 ++++++
.../riscv/riscv-vector-builtins-bases.h       |   1 +
.../riscv/riscv-vector-builtins-functions.def |   1 +
.../riscv/riscv-vector-builtins-shapes.cc     |  50 +++++++
.../riscv/riscv-vector-builtins-shapes.h      |   1 +
gcc/config/riscv/riscv-vector-builtins.cc     |  12 ++
.../gcc.target/riscv/rvv/base/tuple_create.c  | 123 ++++++++++++++++++
7 files changed, 228 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
 
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index 8e679f72392..be3df2c1ea2 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -1824,6 +1824,44 @@ public:
   }
};
+class vcreate : public function_base
+{
+public:
+  gimple *fold (gimple_folder &f) const override
+  {
+    unsigned int nargs = gimple_call_num_args (f.call);
+    tree lhs_type = TREE_TYPE (f.lhs);
+
+    /* Replace the call with a clobber of the result (to prevent it from
+       becoming upwards exposed) followed by stores into each individual
+       vector of tuple.
+
+       The fold routines expect the replacement statement to have the
+       same lhs as the original call, so return the clobber statement
+       rather than the final vector store.  */
+    gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
+
+    for (unsigned int i = nargs; i-- > 0; )
+      {
+ tree rhs_vector = gimple_call_arg (f.call, i);
+ tree field = tuple_type_field (TREE_TYPE (f.lhs));
+ tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+ unshare_expr (f.lhs), field, NULL_TREE);
+ tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+   lhs_array, size_int (i),
+   NULL_TREE, NULL_TREE);
+ gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
+ gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
+      }
+    return clobber;
+  }
+
+  rtx expand (function_expander &e) const override
+  {
+    return NULL_RTX;
+  }
+};
+
class read_vl : public function_base
{
public:
@@ -2285,6 +2323,7 @@ static CONSTEXPR const vlmul_ext vlmul_ext_obj;
static CONSTEXPR const vlmul_trunc vlmul_trunc_obj;
static CONSTEXPR const vset vset_obj;
static CONSTEXPR const vget vget_obj;
+static CONSTEXPR const vcreate vcreate_obj;
static CONSTEXPR const read_vl read_vl_obj;
static CONSTEXPR const vleff vleff_obj;
static CONSTEXPR const vlenb vlenb_obj;
@@ -2546,6 +2585,7 @@ BASE (vlmul_ext)
BASE (vlmul_trunc)
BASE (vset)
BASE (vget)
+BASE (vcreate)
BASE (read_vl)
BASE (vleff)
BASE (vlenb)
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
index 69d4562091f..131041ea66f 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.h
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
@@ -267,6 +267,7 @@ extern const function_base *const vlmul_ext;
extern const function_base *const vlmul_trunc;
extern const function_base *const vset;
extern const function_base *const vget;
+extern const function_base *const vcreate;
extern const function_base *const read_vl;
extern const function_base *const vleff;
extern const function_base *const vlenb;
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
index 3ce06dc60b7..18ed2c2b8f6 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -621,6 +621,7 @@ DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_lmul4_x2_ops)
// Tuple types
DEF_RVV_FUNCTION (vset, vset, none_preds, all_v_vset_tuple_ops)
DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_tuple_ops)
+DEF_RVV_FUNCTION (vcreate, vcreate, none_preds, all_v_vcreate_tuple_ops)
DEF_RVV_FUNCTION (vlseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ops)
DEF_RVV_FUNCTION (vsseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ops)
DEF_RVV_FUNCTION (vlsseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ptrdiff_ops)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index f8fdec863e6..0bda934ae16 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -706,6 +706,55 @@ struct vget_def : public misc_def
   }
};
+/* vcreate_def class.  */
+struct vcreate_def : public build_base
+{
+  void build (function_builder &b,
+       const function_group_info &group) const override
+  {
+    for (unsigned int vec_type_idx = 0;
+ group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
+ ++vec_type_idx)
+      {
+   auto_vec<tree, 8> argument_types;
+   function_instance function_instance (group.base_name, *group.base,
+       *group.shape,
+       group.ops_infos.types[vec_type_idx],
+       group.preds[0], &group.ops_infos);
+
+   tree return_type = group.ops_infos.ret.get_tree_type (
+     group.ops_infos.types[vec_type_idx].index);
+
+   if (!return_type)
+     continue;
+
+   machine_mode mode = TYPE_MODE (return_type);
+   unsigned int nf = get_nf (mode);
+
+   for (unsigned int i = 0; i < nf; i++)
+     argument_types.quick_push (
+       function_instance.op_info->args[0].get_tree_type (
+         function_instance.type.index));
+
+   b.add_unique_function (function_instance, (*group.shape), return_type,
+     argument_types);
+     }
+  }
+
+  char *get_name (function_builder &b, const function_instance &instance,
+   bool overloaded_p) const override
+  {
+    if (overloaded_p)
+      return nullptr;
+    b.append_base_name (instance.base_name);
+    b.append_name (operand_suffixes[instance.op_info->op]);
+    vector_type_index ret_type_idx
+      = instance.op_info->ret.get_function_type_index (instance.type.index);
+    b.append_name (type_suffixes[ret_type_idx].vector);
+    return b.finish_name ();
+  }
+};
+
/* read_vl_def class.  */
struct read_vl_def : public function_shape
{
@@ -942,6 +991,7 @@ SHAPE(vundefined, vundefined)
SHAPE(misc, misc)
SHAPE(vset, vset)
SHAPE(vget, vget)
+SHAPE(vcreate, vcreate)
SHAPE(read_vl, read_vl)
SHAPE(fault_load, fault_load)
SHAPE(vlenb, vlenb)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h b/gcc/config/riscv/riscv-vector-builtins-shapes.h
index 92eb8bc9d71..df9884bb572 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
@@ -45,6 +45,7 @@ extern const function_shape *const vundefined;
extern const function_shape *const misc;
extern const function_shape *const vset;
extern const function_shape *const vget;
+extern const function_shape *const vcreate;
extern const function_shape *const read_vl;
extern const function_shape *const fault_load;
extern const function_shape *const vlenb;
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index 6d99f970ead..5318651138a 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -873,6 +873,10 @@ static CONSTEXPR const rvv_arg_type_info tuple_vset_args[]
   = {rvv_arg_type_info (RVV_BASE_vector), rvv_arg_type_info (RVV_BASE_size),
      rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
+/* A list of args for vector_type func (vector_type) function.  */
+static CONSTEXPR const rvv_arg_type_info tuple_vcreate_args[]
+  = {rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
+
/* A list of none preds that will be registered for intrinsic functions.  */
static CONSTEXPR const predication_type_index none_preds[]
   = {PRED_TYPE_none, NUM_PRED_TYPES};
@@ -2497,6 +2501,14 @@ static CONSTEXPR const rvv_op_info tuple_v_scalar_const_ptr_size_ptr_ops
      rvv_arg_type_info (RVV_BASE_vector), /* Return type */
      scalar_const_ptr_size_ptr_args /* Args */};
+/* A static operand information for vector_type func (vector_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info all_v_vcreate_tuple_ops
+  = {tuple_ops,   /* Types */
+     OP_TYPE_v,   /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     tuple_vcreate_args /* Args */};
+
/* A list of all RVV base function types.  */
static CONSTEXPR const function_type_info function_types[] = {
#define DEF_RVV_TYPE_INDEX(                                                    \
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
new file mode 100644
index 00000000000..b252b2f3cd4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
@@ -0,0 +1,123 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat16mf4x2_t test_vcreate_v_f16mf4x2(vfloat16mf4_t v0, vfloat16mf4_t v1) {
+  return __riscv_vcreate_v_f16mf4x2(v0, v1);
+}
+
+vfloat16mf4x3_t test_vcreate_v_f16mf4x3(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2) {
+  return __riscv_vcreate_v_f16mf4x3(v0, v1, v2);
+}
+
+vfloat16mf4x4_t test_vcreate_v_f16mf4x4(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3) {
+  return __riscv_vcreate_v_f16mf4x4(v0, v1, v2, v3);
+}
+
+vfloat16mf4x5_t test_vcreate_v_f16mf4x5(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4) {
+  return __riscv_vcreate_v_f16mf4x5(v0, v1, v2, v3, v4);
+}
+
+vfloat16mf4x6_t test_vcreate_v_f16mf4x6(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5) {
+  return __riscv_vcreate_v_f16mf4x6(v0, v1, v2, v3, v4, v5);
+}
+
+vfloat16mf4x7_t test_vcreate_v_f16mf4x7(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6) {
+  return __riscv_vcreate_v_f16mf4x7(v0, v1, v2, v3, v4, v5, v6);
+}
+
+vfloat16mf4x8_t test_vcreate_v_f16mf4x8(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6, vfloat16mf4_t v7) {
+  return __riscv_vcreate_v_f16mf4x8(v0, v1, v2, v3, v4, v5, v6, v7);
+}
+
+vfloat32m1x2_t test_vcreate_v_f32m1x2(vfloat32m1_t v0, vfloat32m1_t v1) {
+  return __riscv_vcreate_v_f32m1x2(v0, v1);
+}
+
+vfloat32m1x3_t test_vcreate_v_f32m1x3(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2) {
+  return __riscv_vcreate_v_f32m1x3(v0, v1, v2);
+}
+
+vfloat32m1x4_t test_vcreate_v_f32m1x4(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3) {
+  return __riscv_vcreate_v_f32m1x4(v0, v1, v2, v3);
+}
+
+vfloat32m1x5_t test_vcreate_v_f32m1x5(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4) {
+  return __riscv_vcreate_v_f32m1x5(v0, v1, v2, v3, v4);
+}
+
+vfloat32m1x6_t test_vcreate_v_f32m1x6(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5) {
+  return __riscv_vcreate_v_f32m1x6(v0, v1, v2, v3, v4, v5);
+}
+
+vfloat32m1x7_t test_vcreate_v_f32m1x7(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6) {
+  return __riscv_vcreate_v_f32m1x7(v0, v1, v2, v3, v4, v5, v6);
+}
+
+vfloat32m1x8_t test_vcreate_v_f32m1x8(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6, vfloat32m1_t v7) {
+  return __riscv_vcreate_v_f32m1x8(v0, v1, v2, v3, v4, v5, v6, v7);
+}
+
+vfloat64m2x2_t test_vcreate_v_f64m2x2(vfloat64m2_t v0, vfloat64m2_t v1) {
+  return __riscv_vcreate_v_f64m2x2(v0, v1);
+}
+
+vfloat64m2x3_t test_vcreate_v_f64m2x3(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2) {
+  return __riscv_vcreate_v_f64m2x3(v0, v1, v2);
+}
+
+vfloat64m2x4_t test_vcreate_v_f64m2x4(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2, vfloat64m2_t v3) {
+  return __riscv_vcreate_v_f64m2x4(v0, v1, v2, v3);
+}
+
+vfloat64m4x2_t test_vcreate_v_f64m4x2(vfloat64m4_t v0, vfloat64m4_t v1) {
+  return __riscv_vcreate_v_f64m4x2(v0, v1);
+}
+
+vint8m2x2_t test_vcreate_v_i8m2x2(vint8m2_t v0, vint8m2_t v1) {
+  return __riscv_vcreate_v_i8m2x2(v0, v1);
+}
+
+vint8m2x3_t test_vcreate_v_i8m2x3(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2) {
+  return __riscv_vcreate_v_i8m2x3(v0, v1, v2);
+}
+
+vint8m2x4_t test_vcreate_v_i8m2x4(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2, vint8m2_t v3) {
+  return __riscv_vcreate_v_i8m2x4(v0, v1, v2, v3);
+}
+
+vint8m4x2_t test_vcreate_v_i8m4x2(vint8m4_t v0, vint8m4_t v1) {
+  return __riscv_vcreate_v_i8m4x2(v0, v1);
+}
+
+vint16m4x2_t test_vcreate_v_i16m4x2(vint16m4_t v0, vint16m4_t v1) {
+  return __riscv_vcreate_v_i16m4x2(v0, v1);
+}
+
+vint32m4x2_t test_vcreate_v_i32m4x2(vint32m4_t v0, vint32m4_t v1) {
+  return __riscv_vcreate_v_i32m4x2(v0, v1);
+}
+
+vint64m2x2_t test_vcreate_v_i64m2x2(vint64m2_t v0, vint64m2_t v1) {
+  return __riscv_vcreate_v_i64m2x2(v0, v1);
+}
+
+vint64m2x3_t test_vcreate_v_i64m2x3(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2) {
+  return __riscv_vcreate_v_i64m2x3(v0, v1, v2);
+}
+
+vint64m2x4_t test_vcreate_v_i64m2x4(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2, vint64m2_t v3) {
+  return __riscv_vcreate_v_i64m2x4(v0, v1, v2, v3);
+}
+
+/* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero,\s*e16,\s*mf4,\s*t[au],\s*m[au]} 7 } } */
+/* { dg-final { scan-assembler-times {vle16\.v\s+v[0-9]+,\s*0\([0-9ax]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vse16\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vl2re8\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 9 } } */
+/* { dg-final { scan-assembler-times {vl1re32\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vl2re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 18 } } */
+/* { dg-final { scan-assembler-times {vl4re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 2 } } */
+/* { dg-final { scan-assembler-times {vs1r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vs2r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 27 } } */
+/* { dg-final { scan-assembler-times {vs4r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 8 } } */
Kito Cheng Sept. 12, 2023, 2:46 a.m. UTC | #2
LGTM, thanks for implement this :)

On Tue, Sep 12, 2023 at 10:16 AM juzhe.zhong@rivai.ai
<juzhe.zhong@rivai.ai> wrote:
>
> Thanks for support it.
> LGTM from my side.
> Wait for kito's more comments.
>
>
>
> juzhe.zhong@rivai.ai
>
> From: Li Xu
> Date: 2023-09-12 10:08
> To: gcc-patches
> CC: kito.cheng; palmer; juzhe.zhong; pan2.li; gaofei; wangfeng; xuli
> Subject: [PATCH] RISC-V: Add vcreate intrinsics for RVV tuple types
> From: xuli <xuli1@eswincomputing.com>
>
> gcc/ChangeLog:
>
>         * config/riscv/riscv-vector-builtins-bases.cc (class vcreate):
>         (BASE): New class.
>         * config/riscv/riscv-vector-builtins-bases.h: Ditto.
>         * config/riscv/riscv-vector-builtins-functions.def (vcreate): Add vcreate support.
>         * config/riscv/riscv-vector-builtins-shapes.cc (struct vcreate_def): Ditto.
>         (SHAPE): Ditto.
>         * config/riscv/riscv-vector-builtins-shapes.h: Ditto.
>         * config/riscv/riscv-vector-builtins.cc: Add args type.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/rvv/base/tuple_create.c: New test.
> ---
> .../riscv/riscv-vector-builtins-bases.cc      |  40 ++++++
> .../riscv/riscv-vector-builtins-bases.h       |   1 +
> .../riscv/riscv-vector-builtins-functions.def |   1 +
> .../riscv/riscv-vector-builtins-shapes.cc     |  50 +++++++
> .../riscv/riscv-vector-builtins-shapes.h      |   1 +
> gcc/config/riscv/riscv-vector-builtins.cc     |  12 ++
> .../gcc.target/riscv/rvv/base/tuple_create.c  | 123 ++++++++++++++++++
> 7 files changed, 228 insertions(+)
> create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
>
> diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
> index 8e679f72392..be3df2c1ea2 100644
> --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
> +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
> @@ -1824,6 +1824,44 @@ public:
>    }
> };
> +class vcreate : public function_base
> +{
> +public:
> +  gimple *fold (gimple_folder &f) const override
> +  {
> +    unsigned int nargs = gimple_call_num_args (f.call);
> +    tree lhs_type = TREE_TYPE (f.lhs);
> +
> +    /* Replace the call with a clobber of the result (to prevent it from
> +       becoming upwards exposed) followed by stores into each individual
> +       vector of tuple.
> +
> +       The fold routines expect the replacement statement to have the
> +       same lhs as the original call, so return the clobber statement
> +       rather than the final vector store.  */
> +    gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
> +
> +    for (unsigned int i = nargs; i-- > 0; )
> +      {
> + tree rhs_vector = gimple_call_arg (f.call, i);
> + tree field = tuple_type_field (TREE_TYPE (f.lhs));
> + tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
> + unshare_expr (f.lhs), field, NULL_TREE);
> + tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
> +   lhs_array, size_int (i),
> +   NULL_TREE, NULL_TREE);
> + gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
> + gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
> +      }
> +    return clobber;
> +  }
> +
> +  rtx expand (function_expander &e) const override
> +  {
> +    return NULL_RTX;
> +  }
> +};
> +
> class read_vl : public function_base
> {
> public:
> @@ -2285,6 +2323,7 @@ static CONSTEXPR const vlmul_ext vlmul_ext_obj;
> static CONSTEXPR const vlmul_trunc vlmul_trunc_obj;
> static CONSTEXPR const vset vset_obj;
> static CONSTEXPR const vget vget_obj;
> +static CONSTEXPR const vcreate vcreate_obj;
> static CONSTEXPR const read_vl read_vl_obj;
> static CONSTEXPR const vleff vleff_obj;
> static CONSTEXPR const vlenb vlenb_obj;
> @@ -2546,6 +2585,7 @@ BASE (vlmul_ext)
> BASE (vlmul_trunc)
> BASE (vset)
> BASE (vget)
> +BASE (vcreate)
> BASE (read_vl)
> BASE (vleff)
> BASE (vlenb)
> diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
> index 69d4562091f..131041ea66f 100644
> --- a/gcc/config/riscv/riscv-vector-builtins-bases.h
> +++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
> @@ -267,6 +267,7 @@ extern const function_base *const vlmul_ext;
> extern const function_base *const vlmul_trunc;
> extern const function_base *const vset;
> extern const function_base *const vget;
> +extern const function_base *const vcreate;
> extern const function_base *const read_vl;
> extern const function_base *const vleff;
> extern const function_base *const vlenb;
> diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
> index 3ce06dc60b7..18ed2c2b8f6 100644
> --- a/gcc/config/riscv/riscv-vector-builtins-functions.def
> +++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
> @@ -621,6 +621,7 @@ DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_lmul4_x2_ops)
> // Tuple types
> DEF_RVV_FUNCTION (vset, vset, none_preds, all_v_vset_tuple_ops)
> DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_tuple_ops)
> +DEF_RVV_FUNCTION (vcreate, vcreate, none_preds, all_v_vcreate_tuple_ops)
> DEF_RVV_FUNCTION (vlseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ops)
> DEF_RVV_FUNCTION (vsseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ops)
> DEF_RVV_FUNCTION (vlsseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ptrdiff_ops)
> diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
> index f8fdec863e6..0bda934ae16 100644
> --- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
> +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
> @@ -706,6 +706,55 @@ struct vget_def : public misc_def
>    }
> };
> +/* vcreate_def class.  */
> +struct vcreate_def : public build_base
> +{
> +  void build (function_builder &b,
> +       const function_group_info &group) const override
> +  {
> +    for (unsigned int vec_type_idx = 0;
> + group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
> + ++vec_type_idx)
> +      {
> +   auto_vec<tree, 8> argument_types;
> +   function_instance function_instance (group.base_name, *group.base,
> +       *group.shape,
> +       group.ops_infos.types[vec_type_idx],
> +       group.preds[0], &group.ops_infos);
> +
> +   tree return_type = group.ops_infos.ret.get_tree_type (
> +     group.ops_infos.types[vec_type_idx].index);
> +
> +   if (!return_type)
> +     continue;
> +
> +   machine_mode mode = TYPE_MODE (return_type);
> +   unsigned int nf = get_nf (mode);
> +
> +   for (unsigned int i = 0; i < nf; i++)
> +     argument_types.quick_push (
> +       function_instance.op_info->args[0].get_tree_type (
> +         function_instance.type.index));
> +
> +   b.add_unique_function (function_instance, (*group.shape), return_type,
> +     argument_types);
> +     }
> +  }
> +
> +  char *get_name (function_builder &b, const function_instance &instance,
> +   bool overloaded_p) const override
> +  {
> +    if (overloaded_p)
> +      return nullptr;
> +    b.append_base_name (instance.base_name);
> +    b.append_name (operand_suffixes[instance.op_info->op]);
> +    vector_type_index ret_type_idx
> +      = instance.op_info->ret.get_function_type_index (instance.type.index);
> +    b.append_name (type_suffixes[ret_type_idx].vector);
> +    return b.finish_name ();
> +  }
> +};
> +
> /* read_vl_def class.  */
> struct read_vl_def : public function_shape
> {
> @@ -942,6 +991,7 @@ SHAPE(vundefined, vundefined)
> SHAPE(misc, misc)
> SHAPE(vset, vset)
> SHAPE(vget, vget)
> +SHAPE(vcreate, vcreate)
> SHAPE(read_vl, read_vl)
> SHAPE(fault_load, fault_load)
> SHAPE(vlenb, vlenb)
> diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h b/gcc/config/riscv/riscv-vector-builtins-shapes.h
> index 92eb8bc9d71..df9884bb572 100644
> --- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
> +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
> @@ -45,6 +45,7 @@ extern const function_shape *const vundefined;
> extern const function_shape *const misc;
> extern const function_shape *const vset;
> extern const function_shape *const vget;
> +extern const function_shape *const vcreate;
> extern const function_shape *const read_vl;
> extern const function_shape *const fault_load;
> extern const function_shape *const vlenb;
> diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
> index 6d99f970ead..5318651138a 100644
> --- a/gcc/config/riscv/riscv-vector-builtins.cc
> +++ b/gcc/config/riscv/riscv-vector-builtins.cc
> @@ -873,6 +873,10 @@ static CONSTEXPR const rvv_arg_type_info tuple_vset_args[]
>    = {rvv_arg_type_info (RVV_BASE_vector), rvv_arg_type_info (RVV_BASE_size),
>       rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
> +/* A list of args for vector_type func (vector_type) function.  */
> +static CONSTEXPR const rvv_arg_type_info tuple_vcreate_args[]
> +  = {rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
> +
> /* A list of none preds that will be registered for intrinsic functions.  */
> static CONSTEXPR const predication_type_index none_preds[]
>    = {PRED_TYPE_none, NUM_PRED_TYPES};
> @@ -2497,6 +2501,14 @@ static CONSTEXPR const rvv_op_info tuple_v_scalar_const_ptr_size_ptr_ops
>       rvv_arg_type_info (RVV_BASE_vector), /* Return type */
>       scalar_const_ptr_size_ptr_args /* Args */};
> +/* A static operand information for vector_type func (vector_type)
> + * function registration. */
> +static CONSTEXPR const rvv_op_info all_v_vcreate_tuple_ops
> +  = {tuple_ops,   /* Types */
> +     OP_TYPE_v,   /* Suffix */
> +     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
> +     tuple_vcreate_args /* Args */};
> +
> /* A list of all RVV base function types.  */
> static CONSTEXPR const function_type_info function_types[] = {
> #define DEF_RVV_TYPE_INDEX(                                                    \
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
> new file mode 100644
> index 00000000000..b252b2f3cd4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
> @@ -0,0 +1,123 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64 -O3 -Wno-psabi" } */
> +
> +#include "riscv_vector.h"
> +
> +vfloat16mf4x2_t test_vcreate_v_f16mf4x2(vfloat16mf4_t v0, vfloat16mf4_t v1) {
> +  return __riscv_vcreate_v_f16mf4x2(v0, v1);
> +}
> +
> +vfloat16mf4x3_t test_vcreate_v_f16mf4x3(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2) {
> +  return __riscv_vcreate_v_f16mf4x3(v0, v1, v2);
> +}
> +
> +vfloat16mf4x4_t test_vcreate_v_f16mf4x4(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3) {
> +  return __riscv_vcreate_v_f16mf4x4(v0, v1, v2, v3);
> +}
> +
> +vfloat16mf4x5_t test_vcreate_v_f16mf4x5(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4) {
> +  return __riscv_vcreate_v_f16mf4x5(v0, v1, v2, v3, v4);
> +}
> +
> +vfloat16mf4x6_t test_vcreate_v_f16mf4x6(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5) {
> +  return __riscv_vcreate_v_f16mf4x6(v0, v1, v2, v3, v4, v5);
> +}
> +
> +vfloat16mf4x7_t test_vcreate_v_f16mf4x7(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6) {
> +  return __riscv_vcreate_v_f16mf4x7(v0, v1, v2, v3, v4, v5, v6);
> +}
> +
> +vfloat16mf4x8_t test_vcreate_v_f16mf4x8(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6, vfloat16mf4_t v7) {
> +  return __riscv_vcreate_v_f16mf4x8(v0, v1, v2, v3, v4, v5, v6, v7);
> +}
> +
> +vfloat32m1x2_t test_vcreate_v_f32m1x2(vfloat32m1_t v0, vfloat32m1_t v1) {
> +  return __riscv_vcreate_v_f32m1x2(v0, v1);
> +}
> +
> +vfloat32m1x3_t test_vcreate_v_f32m1x3(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2) {
> +  return __riscv_vcreate_v_f32m1x3(v0, v1, v2);
> +}
> +
> +vfloat32m1x4_t test_vcreate_v_f32m1x4(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3) {
> +  return __riscv_vcreate_v_f32m1x4(v0, v1, v2, v3);
> +}
> +
> +vfloat32m1x5_t test_vcreate_v_f32m1x5(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4) {
> +  return __riscv_vcreate_v_f32m1x5(v0, v1, v2, v3, v4);
> +}
> +
> +vfloat32m1x6_t test_vcreate_v_f32m1x6(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5) {
> +  return __riscv_vcreate_v_f32m1x6(v0, v1, v2, v3, v4, v5);
> +}
> +
> +vfloat32m1x7_t test_vcreate_v_f32m1x7(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6) {
> +  return __riscv_vcreate_v_f32m1x7(v0, v1, v2, v3, v4, v5, v6);
> +}
> +
> +vfloat32m1x8_t test_vcreate_v_f32m1x8(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6, vfloat32m1_t v7) {
> +  return __riscv_vcreate_v_f32m1x8(v0, v1, v2, v3, v4, v5, v6, v7);
> +}
> +
> +vfloat64m2x2_t test_vcreate_v_f64m2x2(vfloat64m2_t v0, vfloat64m2_t v1) {
> +  return __riscv_vcreate_v_f64m2x2(v0, v1);
> +}
> +
> +vfloat64m2x3_t test_vcreate_v_f64m2x3(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2) {
> +  return __riscv_vcreate_v_f64m2x3(v0, v1, v2);
> +}
> +
> +vfloat64m2x4_t test_vcreate_v_f64m2x4(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2, vfloat64m2_t v3) {
> +  return __riscv_vcreate_v_f64m2x4(v0, v1, v2, v3);
> +}
> +
> +vfloat64m4x2_t test_vcreate_v_f64m4x2(vfloat64m4_t v0, vfloat64m4_t v1) {
> +  return __riscv_vcreate_v_f64m4x2(v0, v1);
> +}
> +
> +vint8m2x2_t test_vcreate_v_i8m2x2(vint8m2_t v0, vint8m2_t v1) {
> +  return __riscv_vcreate_v_i8m2x2(v0, v1);
> +}
> +
> +vint8m2x3_t test_vcreate_v_i8m2x3(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2) {
> +  return __riscv_vcreate_v_i8m2x3(v0, v1, v2);
> +}
> +
> +vint8m2x4_t test_vcreate_v_i8m2x4(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2, vint8m2_t v3) {
> +  return __riscv_vcreate_v_i8m2x4(v0, v1, v2, v3);
> +}
> +
> +vint8m4x2_t test_vcreate_v_i8m4x2(vint8m4_t v0, vint8m4_t v1) {
> +  return __riscv_vcreate_v_i8m4x2(v0, v1);
> +}
> +
> +vint16m4x2_t test_vcreate_v_i16m4x2(vint16m4_t v0, vint16m4_t v1) {
> +  return __riscv_vcreate_v_i16m4x2(v0, v1);
> +}
> +
> +vint32m4x2_t test_vcreate_v_i32m4x2(vint32m4_t v0, vint32m4_t v1) {
> +  return __riscv_vcreate_v_i32m4x2(v0, v1);
> +}
> +
> +vint64m2x2_t test_vcreate_v_i64m2x2(vint64m2_t v0, vint64m2_t v1) {
> +  return __riscv_vcreate_v_i64m2x2(v0, v1);
> +}
> +
> +vint64m2x3_t test_vcreate_v_i64m2x3(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2) {
> +  return __riscv_vcreate_v_i64m2x3(v0, v1, v2);
> +}
> +
> +vint64m2x4_t test_vcreate_v_i64m2x4(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2, vint64m2_t v3) {
> +  return __riscv_vcreate_v_i64m2x4(v0, v1, v2, v3);
> +}
> +
> +/* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero,\s*e16,\s*mf4,\s*t[au],\s*m[au]} 7 } } */
> +/* { dg-final { scan-assembler-times {vle16\.v\s+v[0-9]+,\s*0\([0-9ax]+\)} 35 } } */
> +/* { dg-final { scan-assembler-times {vse16\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
> +/* { dg-final { scan-assembler-times {vl2re8\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 9 } } */
> +/* { dg-final { scan-assembler-times {vl1re32\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
> +/* { dg-final { scan-assembler-times {vl2re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 18 } } */
> +/* { dg-final { scan-assembler-times {vl4re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 2 } } */
> +/* { dg-final { scan-assembler-times {vs1r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
> +/* { dg-final { scan-assembler-times {vs2r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 27 } } */
> +/* { dg-final { scan-assembler-times {vs4r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 8 } } */
> --
> 2.17.1
>
>
Li Xu Sept. 12, 2023, 3:21 a.m. UTC | #3
Committed, thanks juzhe and kito.
--------------
Li Xu
>LGTM, thanks for implement this :)
>
>On Tue, Sep 12, 2023 at 10:16 AM juzhe.zhong@rivai.ai
><juzhe.zhong@rivai.ai> wrote:
>>
>> Thanks for support it.
>> LGTM from my side.
>> Wait for kito's more comments.
>>
>>
>>
>> juzhe.zhong@rivai.ai
>>
>> From: Li Xu
>> Date: 2023-09-12 10:08
>> To: gcc-patches
>> CC: kito.cheng; palmer; juzhe.zhong; pan2.li; gaofei; wangfeng; xuli
>> Subject: [PATCH] RISC-V: Add vcreate intrinsics for RVV tuple types
>> From: xuli <xuli1@eswincomputing.com>
>>
>> gcc/ChangeLog:
>>
>>         * config/riscv/riscv-vector-builtins-bases.cc (class vcreate):
>>         (BASE): New class.
>>         * config/riscv/riscv-vector-builtins-bases.h: Ditto.
>>         * config/riscv/riscv-vector-builtins-functions.def (vcreate): Add vcreate support.
>>         * config/riscv/riscv-vector-builtins-shapes.cc (struct vcreate_def): Ditto.
>>         (SHAPE): Ditto.
>>         * config/riscv/riscv-vector-builtins-shapes.h: Ditto.
>>         * config/riscv/riscv-vector-builtins.cc: Add args type.
>>
>> gcc/testsuite/ChangeLog:
>>
>>         * gcc.target/riscv/rvv/base/tuple_create.c: New test.
>> ---
>> .../riscv/riscv-vector-builtins-bases.cc      |  40 ++++++
>> .../riscv/riscv-vector-builtins-bases.h       |   1 +
>> .../riscv/riscv-vector-builtins-functions.def |   1 +
>> .../riscv/riscv-vector-builtins-shapes.cc     |  50 +++++++
>> .../riscv/riscv-vector-builtins-shapes.h      |   1 +
>> gcc/config/riscv/riscv-vector-builtins.cc     |  12 ++
>> .../gcc.target/riscv/rvv/base/tuple_create.c  | 123 ++++++++++++++++++
>> 7 files changed, 228 insertions(+)
>> create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
>>
>> diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
>> index 8e679f72392..be3df2c1ea2 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
>> +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
>> @@ -1824,6 +1824,44 @@ public:
>>    }
>> };
>> +class vcreate : public function_base
>> +{
>> +public:
>> +  gimple *fold (gimple_folder &f) const override
>> +  {
>> +    unsigned int nargs = gimple_call_num_args (f.call);
>> +    tree lhs_type = TREE_TYPE (f.lhs);
>> +
>> +    /* Replace the call with a clobber of the result (to prevent it from
>> +       becoming upwards exposed) followed by stores into each individual
>> +       vector of tuple.
>> +
>> +       The fold routines expect the replacement statement to have the
>> +       same lhs as the original call, so return the clobber statement
>> +       rather than the final vector store.  */
>> +    gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
>> +
>> +    for (unsigned int i = nargs; i-- > 0; )
>> +      {
>> + tree rhs_vector = gimple_call_arg (f.call, i);
>> + tree field = tuple_type_field (TREE_TYPE (f.lhs));
>> + tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
>> + unshare_expr (f.lhs), field, NULL_TREE);
>> + tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
>> +   lhs_array, size_int (i),
>> +   NULL_TREE, NULL_TREE);
>> + gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
>> + gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
>> +      }
>> +    return clobber;
>> +  }
>> +
>> +  rtx expand (function_expander &e) const override
>> +  {
>> +    return NULL_RTX;
>> +  }
>> +};
>> +
>> class read_vl : public function_base
>> {
>> public:
>> @@ -2285,6 +2323,7 @@ static CONSTEXPR const vlmul_ext vlmul_ext_obj;
>> static CONSTEXPR const vlmul_trunc vlmul_trunc_obj;
>> static CONSTEXPR const vset vset_obj;
>> static CONSTEXPR const vget vget_obj;
>> +static CONSTEXPR const vcreate vcreate_obj;
>> static CONSTEXPR const read_vl read_vl_obj;
>> static CONSTEXPR const vleff vleff_obj;
>> static CONSTEXPR const vlenb vlenb_obj;
>> @@ -2546,6 +2585,7 @@ BASE (vlmul_ext)
>> BASE (vlmul_trunc)
>> BASE (vset)
>> BASE (vget)
>> +BASE (vcreate)
>> BASE (read_vl)
>> BASE (vleff)
>> BASE (vlenb)
>> diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
>> index 69d4562091f..131041ea66f 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins-bases.h
>> +++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
>> @@ -267,6 +267,7 @@ extern const function_base *const vlmul_ext;
>> extern const function_base *const vlmul_trunc;
>> extern const function_base *const vset;
>> extern const function_base *const vget;
>> +extern const function_base *const vcreate;
>> extern const function_base *const read_vl;
>> extern const function_base *const vleff;
>> extern const function_base *const vlenb;
>> diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
>> index 3ce06dc60b7..18ed2c2b8f6 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins-functions.def
>> +++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
>> @@ -621,6 +621,7 @@ DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_lmul4_x2_ops)
>> // Tuple types
>> DEF_RVV_FUNCTION (vset, vset, none_preds, all_v_vset_tuple_ops)
>> DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_tuple_ops)
>> +DEF_RVV_FUNCTION (vcreate, vcreate, none_preds, all_v_vcreate_tuple_ops)
>> DEF_RVV_FUNCTION (vlseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ops)
>> DEF_RVV_FUNCTION (vsseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ops)
>> DEF_RVV_FUNCTION (vlsseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ptrdiff_ops)
>> diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
>> index f8fdec863e6..0bda934ae16 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
>> +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
>> @@ -706,6 +706,55 @@ struct vget_def : public misc_def
>>    }
>> };
>> +/* vcreate_def class.  */
>> +struct vcreate_def : public build_base
>> +{
>> +  void build (function_builder &b,
>> +       const function_group_info &group) const override
>> +  {
>> +    for (unsigned int vec_type_idx = 0;
>> + group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
>> + ++vec_type_idx)
>> +      {
>> +   auto_vec<tree, 8> argument_types;
>> +   function_instance function_instance (group.base_name, *group.base,
>> +       *group.shape,
>> +       group.ops_infos.types[vec_type_idx],
>> +       group.preds[0], &group.ops_infos);
>> +
>> +   tree return_type = group.ops_infos.ret.get_tree_type (
>> +     group.ops_infos.types[vec_type_idx].index);
>> +
>> +   if (!return_type)
>> +     continue;
>> +
>> +   machine_mode mode = TYPE_MODE (return_type);
>> +   unsigned int nf = get_nf (mode);
>> +
>> +   for (unsigned int i = 0; i < nf; i++)
>> +     argument_types.quick_push (
>> +       function_instance.op_info->args[0].get_tree_type (
>> +         function_instance.type.index));
>> +
>> +   b.add_unique_function (function_instance, (*group.shape), return_type,
>> +     argument_types);
>> +     }
>> +  }
>> +
>> +  char *get_name (function_builder &b, const function_instance &instance,
>> +   bool overloaded_p) const override
>> +  {
>> +    if (overloaded_p)
>> +      return nullptr;
>> +    b.append_base_name (instance.base_name);
>> +    b.append_name (operand_suffixes[instance.op_info->op]);
>> +    vector_type_index ret_type_idx
>> +      = instance.op_info->ret.get_function_type_index (instance.type.index);
>> +    b.append_name (type_suffixes[ret_type_idx].vector);
>> +    return b.finish_name ();
>> +  }
>> +};
>> +
>> /* read_vl_def class.  */
>> struct read_vl_def : public function_shape
>> {
>> @@ -942,6 +991,7 @@ SHAPE(vundefined, vundefined)
>> SHAPE(misc, misc)
>> SHAPE(vset, vset)
>> SHAPE(vget, vget)
>> +SHAPE(vcreate, vcreate)
>> SHAPE(read_vl, read_vl)
>> SHAPE(fault_load, fault_load)
>> SHAPE(vlenb, vlenb)
>> diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h b/gcc/config/riscv/riscv-vector-builtins-shapes.h
>> index 92eb8bc9d71..df9884bb572 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
>> +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
>> @@ -45,6 +45,7 @@ extern const function_shape *const vundefined;
>> extern const function_shape *const misc;
>> extern const function_shape *const vset;
>> extern const function_shape *const vget;
>> +extern const function_shape *const vcreate;
>> extern const function_shape *const read_vl;
>> extern const function_shape *const fault_load;
>> extern const function_shape *const vlenb;
>> diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
>> index 6d99f970ead..5318651138a 100644
>> --- a/gcc/config/riscv/riscv-vector-builtins.cc
>> +++ b/gcc/config/riscv/riscv-vector-builtins.cc
>> @@ -873,6 +873,10 @@ static CONSTEXPR const rvv_arg_type_info tuple_vset_args[]
>>    = {rvv_arg_type_info (RVV_BASE_vector), rvv_arg_type_info (RVV_BASE_size),
>>       rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
>> +/* A list of args for vector_type func (vector_type) function.  */
>> +static CONSTEXPR const rvv_arg_type_info tuple_vcreate_args[]
>> +  = {rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
>> +
>> /* A list of none preds that will be registered for intrinsic functions.  */
>> static CONSTEXPR const predication_type_index none_preds[]
>>    = {PRED_TYPE_none, NUM_PRED_TYPES};
>> @@ -2497,6 +2501,14 @@ static CONSTEXPR const rvv_op_info tuple_v_scalar_const_ptr_size_ptr_ops
>>       rvv_arg_type_info (RVV_BASE_vector), /* Return type */
>>       scalar_const_ptr_size_ptr_args /* Args */};
>> +/* A static operand information for vector_type func (vector_type)
>> + * function registration. */
>> +static CONSTEXPR const rvv_op_info all_v_vcreate_tuple_ops
>> +  = {tuple_ops,   /* Types */
>> +     OP_TYPE_v,   /* Suffix */
>> +     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
>> +     tuple_vcreate_args /* Args */};
>> +
>> /* A list of all RVV base function types.  */
>> static CONSTEXPR const function_type_info function_types[] = {
>> #define DEF_RVV_TYPE_INDEX(                                                    \
>> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
>> new file mode 100644
>> index 00000000000..b252b2f3cd4
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
>> @@ -0,0 +1,123 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64 -O3 -Wno-psabi" } */
>> +
>> +#include "riscv_vector.h"
>> +
>> +vfloat16mf4x2_t test_vcreate_v_f16mf4x2(vfloat16mf4_t v0, vfloat16mf4_t v1) {
>> +  return __riscv_vcreate_v_f16mf4x2(v0, v1);
>> +}
>> +
>> +vfloat16mf4x3_t test_vcreate_v_f16mf4x3(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2) {
>> +  return __riscv_vcreate_v_f16mf4x3(v0, v1, v2);
>> +}
>> +
>> +vfloat16mf4x4_t test_vcreate_v_f16mf4x4(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3) {
>> +  return __riscv_vcreate_v_f16mf4x4(v0, v1, v2, v3);
>> +}
>> +
>> +vfloat16mf4x5_t test_vcreate_v_f16mf4x5(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4) {
>> +  return __riscv_vcreate_v_f16mf4x5(v0, v1, v2, v3, v4);
>> +}
>> +
>> +vfloat16mf4x6_t test_vcreate_v_f16mf4x6(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5) {
>> +  return __riscv_vcreate_v_f16mf4x6(v0, v1, v2, v3, v4, v5);
>> +}
>> +
>> +vfloat16mf4x7_t test_vcreate_v_f16mf4x7(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6) {
>> +  return __riscv_vcreate_v_f16mf4x7(v0, v1, v2, v3, v4, v5, v6);
>> +}
>> +
>> +vfloat16mf4x8_t test_vcreate_v_f16mf4x8(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6, vfloat16mf4_t v7) {
>> +  return __riscv_vcreate_v_f16mf4x8(v0, v1, v2, v3, v4, v5, v6, v7);
>> +}
>> +
>> +vfloat32m1x2_t test_vcreate_v_f32m1x2(vfloat32m1_t v0, vfloat32m1_t v1) {
>> +  return __riscv_vcreate_v_f32m1x2(v0, v1);
>> +}
>> +
>> +vfloat32m1x3_t test_vcreate_v_f32m1x3(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2) {
>> +  return __riscv_vcreate_v_f32m1x3(v0, v1, v2);
>> +}
>> +
>> +vfloat32m1x4_t test_vcreate_v_f32m1x4(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3) {
>> +  return __riscv_vcreate_v_f32m1x4(v0, v1, v2, v3);
>> +}
>> +
>> +vfloat32m1x5_t test_vcreate_v_f32m1x5(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4) {
>> +  return __riscv_vcreate_v_f32m1x5(v0, v1, v2, v3, v4);
>> +}
>> +
>> +vfloat32m1x6_t test_vcreate_v_f32m1x6(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5) {
>> +  return __riscv_vcreate_v_f32m1x6(v0, v1, v2, v3, v4, v5);
>> +}
>> +
>> +vfloat32m1x7_t test_vcreate_v_f32m1x7(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6) {
>> +  return __riscv_vcreate_v_f32m1x7(v0, v1, v2, v3, v4, v5, v6);
>> +}
>> +
>> +vfloat32m1x8_t test_vcreate_v_f32m1x8(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6, vfloat32m1_t v7) {
>> +  return __riscv_vcreate_v_f32m1x8(v0, v1, v2, v3, v4, v5, v6, v7);
>> +}
>> +
>> +vfloat64m2x2_t test_vcreate_v_f64m2x2(vfloat64m2_t v0, vfloat64m2_t v1) {
>> +  return __riscv_vcreate_v_f64m2x2(v0, v1);
>> +}
>> +
>> +vfloat64m2x3_t test_vcreate_v_f64m2x3(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2) {
>> +  return __riscv_vcreate_v_f64m2x3(v0, v1, v2);
>> +}
>> +
>> +vfloat64m2x4_t test_vcreate_v_f64m2x4(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2, vfloat64m2_t v3) {
>> +  return __riscv_vcreate_v_f64m2x4(v0, v1, v2, v3);
>> +}
>> +
>> +vfloat64m4x2_t test_vcreate_v_f64m4x2(vfloat64m4_t v0, vfloat64m4_t v1) {
>> +  return __riscv_vcreate_v_f64m4x2(v0, v1);
>> +}
>> +
>> +vint8m2x2_t test_vcreate_v_i8m2x2(vint8m2_t v0, vint8m2_t v1) {
>> +  return __riscv_vcreate_v_i8m2x2(v0, v1);
>> +}
>> +
>> +vint8m2x3_t test_vcreate_v_i8m2x3(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2) {
>> +  return __riscv_vcreate_v_i8m2x3(v0, v1, v2);
>> +}
>> +
>> +vint8m2x4_t test_vcreate_v_i8m2x4(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2, vint8m2_t v3) {
>> +  return __riscv_vcreate_v_i8m2x4(v0, v1, v2, v3);
>> +}
>> +
>> +vint8m4x2_t test_vcreate_v_i8m4x2(vint8m4_t v0, vint8m4_t v1) {
>> +  return __riscv_vcreate_v_i8m4x2(v0, v1);
>> +}
>> +
>> +vint16m4x2_t test_vcreate_v_i16m4x2(vint16m4_t v0, vint16m4_t v1) {
>> +  return __riscv_vcreate_v_i16m4x2(v0, v1);
>> +}
>> +
>> +vint32m4x2_t test_vcreate_v_i32m4x2(vint32m4_t v0, vint32m4_t v1) {
>> +  return __riscv_vcreate_v_i32m4x2(v0, v1);
>> +}
>> +
>> +vint64m2x2_t test_vcreate_v_i64m2x2(vint64m2_t v0, vint64m2_t v1) {
>> +  return __riscv_vcreate_v_i64m2x2(v0, v1);
>> +}
>> +
>> +vint64m2x3_t test_vcreate_v_i64m2x3(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2) {
>> +  return __riscv_vcreate_v_i64m2x3(v0, v1, v2);
>> +}
>> +
>> +vint64m2x4_t test_vcreate_v_i64m2x4(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2, vint64m2_t v3) {
>> +  return __riscv_vcreate_v_i64m2x4(v0, v1, v2, v3);
>> +}
>> +
>> +/* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero,\s*e16,\s*mf4,\s*t[au],\s*m[au]} 7 } } */
>> +/* { dg-final { scan-assembler-times {vle16\.v\s+v[0-9]+,\s*0\([0-9ax]+\)} 35 } } */
>> +/* { dg-final { scan-assembler-times {vse16\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
>> +/* { dg-final { scan-assembler-times {vl2re8\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 9 } } */
>> +/* { dg-final { scan-assembler-times {vl1re32\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
>> +/* { dg-final { scan-assembler-times {vl2re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 18 } } */
>> +/* { dg-final { scan-assembler-times {vl4re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 2 } } */
>> +/* { dg-final { scan-assembler-times {vs1r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
>> +/* { dg-final { scan-assembler-times {vs2r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 27 } } */
>> +/* { dg-final { scan-assembler-times {vs4r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 8 } } */
>> --
>> 2.17.1
>>
>>
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 8e679f72392..be3df2c1ea2 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -1824,6 +1824,44 @@  public:
   }
 };
 
+class vcreate : public function_base
+{
+public:
+  gimple *fold (gimple_folder &f) const override
+  {
+    unsigned int nargs = gimple_call_num_args (f.call);
+    tree lhs_type = TREE_TYPE (f.lhs);
+
+    /* Replace the call with a clobber of the result (to prevent it from
+       becoming upwards exposed) followed by stores into each individual
+       vector of tuple.
+
+       The fold routines expect the replacement statement to have the
+       same lhs as the original call, so return the clobber statement
+       rather than the final vector store.  */
+    gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
+
+    for (unsigned int i = nargs; i-- > 0; )
+      {
+	tree rhs_vector = gimple_call_arg (f.call, i);
+	tree field = tuple_type_field (TREE_TYPE (f.lhs));
+	tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+				 unshare_expr (f.lhs), field, NULL_TREE);
+	tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+				  lhs_array, size_int (i),
+				  NULL_TREE, NULL_TREE);
+	gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
+	gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
+      }
+    return clobber;
+  }
+
+  rtx expand (function_expander &e) const override
+  {
+    return NULL_RTX;
+  }
+};
+
 class read_vl : public function_base
 {
 public:
@@ -2285,6 +2323,7 @@  static CONSTEXPR const vlmul_ext vlmul_ext_obj;
 static CONSTEXPR const vlmul_trunc vlmul_trunc_obj;
 static CONSTEXPR const vset vset_obj;
 static CONSTEXPR const vget vget_obj;
+static CONSTEXPR const vcreate vcreate_obj;
 static CONSTEXPR const read_vl read_vl_obj;
 static CONSTEXPR const vleff vleff_obj;
 static CONSTEXPR const vlenb vlenb_obj;
@@ -2546,6 +2585,7 @@  BASE (vlmul_ext)
 BASE (vlmul_trunc)
 BASE (vset)
 BASE (vget)
+BASE (vcreate)
 BASE (read_vl)
 BASE (vleff)
 BASE (vlenb)
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
index 69d4562091f..131041ea66f 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.h
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
@@ -267,6 +267,7 @@  extern const function_base *const vlmul_ext;
 extern const function_base *const vlmul_trunc;
 extern const function_base *const vset;
 extern const function_base *const vget;
+extern const function_base *const vcreate;
 extern const function_base *const read_vl;
 extern const function_base *const vleff;
 extern const function_base *const vlenb;
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
index 3ce06dc60b7..18ed2c2b8f6 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -621,6 +621,7 @@  DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_lmul4_x2_ops)
 // Tuple types
 DEF_RVV_FUNCTION (vset, vset, none_preds, all_v_vset_tuple_ops)
 DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_tuple_ops)
+DEF_RVV_FUNCTION (vcreate, vcreate, none_preds, all_v_vcreate_tuple_ops)
 DEF_RVV_FUNCTION (vlseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ops)
 DEF_RVV_FUNCTION (vsseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ops)
 DEF_RVV_FUNCTION (vlsseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ptrdiff_ops)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index f8fdec863e6..0bda934ae16 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -706,6 +706,55 @@  struct vget_def : public misc_def
   }
 };
 
+/* vcreate_def class.  */
+struct vcreate_def : public build_base
+{
+  void build (function_builder &b,
+	      const function_group_info &group) const override
+  {
+    for (unsigned int vec_type_idx = 0;
+	 group.ops_infos.types[vec_type_idx].index != NUM_VECTOR_TYPES;
+	 ++vec_type_idx)
+      {
+	  auto_vec<tree, 8> argument_types;
+	  function_instance function_instance (group.base_name, *group.base,
+					      *group.shape,
+					      group.ops_infos.types[vec_type_idx],
+					      group.preds[0], &group.ops_infos);
+
+	  tree return_type = group.ops_infos.ret.get_tree_type (
+	    group.ops_infos.types[vec_type_idx].index);
+
+	  if (!return_type)
+	    continue;
+
+	  machine_mode mode = TYPE_MODE (return_type);
+	  unsigned int nf = get_nf (mode);
+
+	  for (unsigned int i = 0; i < nf; i++)
+	    argument_types.quick_push (
+	      function_instance.op_info->args[0].get_tree_type (
+	        function_instance.type.index));
+
+	  b.add_unique_function (function_instance, (*group.shape), return_type,
+	    argument_types);
+     }
+  }
+
+  char *get_name (function_builder &b, const function_instance &instance,
+		  bool overloaded_p) const override
+  {
+    if (overloaded_p)
+      return nullptr;
+    b.append_base_name (instance.base_name);
+    b.append_name (operand_suffixes[instance.op_info->op]);
+    vector_type_index ret_type_idx
+      = instance.op_info->ret.get_function_type_index (instance.type.index);
+    b.append_name (type_suffixes[ret_type_idx].vector);
+    return b.finish_name ();
+  }
+};
+
 /* read_vl_def class.  */
 struct read_vl_def : public function_shape
 {
@@ -942,6 +991,7 @@  SHAPE(vundefined, vundefined)
 SHAPE(misc, misc)
 SHAPE(vset, vset)
 SHAPE(vget, vget)
+SHAPE(vcreate, vcreate)
 SHAPE(read_vl, read_vl)
 SHAPE(fault_load, fault_load)
 SHAPE(vlenb, vlenb)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h b/gcc/config/riscv/riscv-vector-builtins-shapes.h
index 92eb8bc9d71..df9884bb572 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
@@ -45,6 +45,7 @@  extern const function_shape *const vundefined;
 extern const function_shape *const misc;
 extern const function_shape *const vset;
 extern const function_shape *const vget;
+extern const function_shape *const vcreate;
 extern const function_shape *const read_vl;
 extern const function_shape *const fault_load;
 extern const function_shape *const vlenb;
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index 6d99f970ead..5318651138a 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -873,6 +873,10 @@  static CONSTEXPR const rvv_arg_type_info tuple_vset_args[]
   = {rvv_arg_type_info (RVV_BASE_vector), rvv_arg_type_info (RVV_BASE_size),
      rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
 
+/* A list of args for vector_type func (vector_type) function.  */
+static CONSTEXPR const rvv_arg_type_info tuple_vcreate_args[]
+  = {rvv_arg_type_info (RVV_BASE_tuple_subpart), rvv_arg_type_info_end};
+
 /* A list of none preds that will be registered for intrinsic functions.  */
 static CONSTEXPR const predication_type_index none_preds[]
   = {PRED_TYPE_none, NUM_PRED_TYPES};
@@ -2497,6 +2501,14 @@  static CONSTEXPR const rvv_op_info tuple_v_scalar_const_ptr_size_ptr_ops
      rvv_arg_type_info (RVV_BASE_vector), /* Return type */
      scalar_const_ptr_size_ptr_args /* Args */};
 
+/* A static operand information for vector_type func (vector_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info all_v_vcreate_tuple_ops
+  = {tuple_ops,				  /* Types */
+     OP_TYPE_v,				  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     tuple_vcreate_args /* Args */};
+
 /* A list of all RVV base function types.  */
 static CONSTEXPR const function_type_info function_types[] = {
 #define DEF_RVV_TYPE_INDEX(                                                    \
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
new file mode 100644
index 00000000000..b252b2f3cd4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/tuple_create.c
@@ -0,0 +1,123 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+vfloat16mf4x2_t test_vcreate_v_f16mf4x2(vfloat16mf4_t v0, vfloat16mf4_t v1) {
+  return __riscv_vcreate_v_f16mf4x2(v0, v1);
+}
+
+vfloat16mf4x3_t test_vcreate_v_f16mf4x3(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2) {
+  return __riscv_vcreate_v_f16mf4x3(v0, v1, v2);
+}
+
+vfloat16mf4x4_t test_vcreate_v_f16mf4x4(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3) {
+  return __riscv_vcreate_v_f16mf4x4(v0, v1, v2, v3);
+}
+
+vfloat16mf4x5_t test_vcreate_v_f16mf4x5(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4) {
+  return __riscv_vcreate_v_f16mf4x5(v0, v1, v2, v3, v4);
+}
+
+vfloat16mf4x6_t test_vcreate_v_f16mf4x6(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5) {
+  return __riscv_vcreate_v_f16mf4x6(v0, v1, v2, v3, v4, v5);
+}
+
+vfloat16mf4x7_t test_vcreate_v_f16mf4x7(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6) {
+  return __riscv_vcreate_v_f16mf4x7(v0, v1, v2, v3, v4, v5, v6);
+}
+
+vfloat16mf4x8_t test_vcreate_v_f16mf4x8(vfloat16mf4_t v0, vfloat16mf4_t v1, vfloat16mf4_t v2, vfloat16mf4_t v3, vfloat16mf4_t v4, vfloat16mf4_t v5, vfloat16mf4_t v6, vfloat16mf4_t v7) {
+  return __riscv_vcreate_v_f16mf4x8(v0, v1, v2, v3, v4, v5, v6, v7);
+}
+
+vfloat32m1x2_t test_vcreate_v_f32m1x2(vfloat32m1_t v0, vfloat32m1_t v1) {
+  return __riscv_vcreate_v_f32m1x2(v0, v1);
+}
+
+vfloat32m1x3_t test_vcreate_v_f32m1x3(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2) {
+  return __riscv_vcreate_v_f32m1x3(v0, v1, v2);
+}
+
+vfloat32m1x4_t test_vcreate_v_f32m1x4(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3) {
+  return __riscv_vcreate_v_f32m1x4(v0, v1, v2, v3);
+}
+
+vfloat32m1x5_t test_vcreate_v_f32m1x5(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4) {
+  return __riscv_vcreate_v_f32m1x5(v0, v1, v2, v3, v4);
+}
+
+vfloat32m1x6_t test_vcreate_v_f32m1x6(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5) {
+  return __riscv_vcreate_v_f32m1x6(v0, v1, v2, v3, v4, v5);
+}
+
+vfloat32m1x7_t test_vcreate_v_f32m1x7(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6) {
+  return __riscv_vcreate_v_f32m1x7(v0, v1, v2, v3, v4, v5, v6);
+}
+
+vfloat32m1x8_t test_vcreate_v_f32m1x8(vfloat32m1_t v0, vfloat32m1_t v1, vfloat32m1_t v2, vfloat32m1_t v3, vfloat32m1_t v4, vfloat32m1_t v5, vfloat32m1_t v6, vfloat32m1_t v7) {
+  return __riscv_vcreate_v_f32m1x8(v0, v1, v2, v3, v4, v5, v6, v7);
+}
+
+vfloat64m2x2_t test_vcreate_v_f64m2x2(vfloat64m2_t v0, vfloat64m2_t v1) {
+  return __riscv_vcreate_v_f64m2x2(v0, v1);
+}
+
+vfloat64m2x3_t test_vcreate_v_f64m2x3(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2) {
+  return __riscv_vcreate_v_f64m2x3(v0, v1, v2);
+}
+
+vfloat64m2x4_t test_vcreate_v_f64m2x4(vfloat64m2_t v0, vfloat64m2_t v1, vfloat64m2_t v2, vfloat64m2_t v3) {
+  return __riscv_vcreate_v_f64m2x4(v0, v1, v2, v3);
+}
+
+vfloat64m4x2_t test_vcreate_v_f64m4x2(vfloat64m4_t v0, vfloat64m4_t v1) {
+  return __riscv_vcreate_v_f64m4x2(v0, v1);
+}
+
+vint8m2x2_t test_vcreate_v_i8m2x2(vint8m2_t v0, vint8m2_t v1) {
+  return __riscv_vcreate_v_i8m2x2(v0, v1);
+}
+
+vint8m2x3_t test_vcreate_v_i8m2x3(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2) {
+  return __riscv_vcreate_v_i8m2x3(v0, v1, v2);
+}
+
+vint8m2x4_t test_vcreate_v_i8m2x4(vint8m2_t v0, vint8m2_t v1, vint8m2_t v2, vint8m2_t v3) {
+  return __riscv_vcreate_v_i8m2x4(v0, v1, v2, v3);
+}
+
+vint8m4x2_t test_vcreate_v_i8m4x2(vint8m4_t v0, vint8m4_t v1) {
+  return __riscv_vcreate_v_i8m4x2(v0, v1);
+}
+
+vint16m4x2_t test_vcreate_v_i16m4x2(vint16m4_t v0, vint16m4_t v1) {
+  return __riscv_vcreate_v_i16m4x2(v0, v1);
+}
+
+vint32m4x2_t test_vcreate_v_i32m4x2(vint32m4_t v0, vint32m4_t v1) {
+  return __riscv_vcreate_v_i32m4x2(v0, v1);
+}
+
+vint64m2x2_t test_vcreate_v_i64m2x2(vint64m2_t v0, vint64m2_t v1) {
+  return __riscv_vcreate_v_i64m2x2(v0, v1);
+}
+
+vint64m2x3_t test_vcreate_v_i64m2x3(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2) {
+  return __riscv_vcreate_v_i64m2x3(v0, v1, v2);
+}
+
+vint64m2x4_t test_vcreate_v_i64m2x4(vint64m2_t v0, vint64m2_t v1, vint64m2_t v2, vint64m2_t v3) {
+  return __riscv_vcreate_v_i64m2x4(v0, v1, v2, v3);
+}
+
+/* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero,\s*e16,\s*mf4,\s*t[au],\s*m[au]} 7 } } */
+/* { dg-final { scan-assembler-times {vle16\.v\s+v[0-9]+,\s*0\([0-9ax]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vse16\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vl2re8\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 9 } } */
+/* { dg-final { scan-assembler-times {vl1re32\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vl2re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 18 } } */
+/* { dg-final { scan-assembler-times {vl4re64\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 2 } } */
+/* { dg-final { scan-assembler-times {vs1r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 35 } } */
+/* { dg-final { scan-assembler-times {vs2r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 27 } } */
+/* { dg-final { scan-assembler-times {vs4r\.v\s+v[0-9]+,\s*0\([a-x][0-9]+\)} 8 } } */