public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RISC-V: Add RVV intrinsic basic framework.
@ 2022-10-17  8:20 juzhe.zhong
  2022-10-21  4:23 ` Kito Cheng
  0 siblings, 1 reply; 2+ messages in thread
From: juzhe.zhong @ 2022-10-17  8:20 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, Ju-Zhe Zhong

From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>

gcc/ChangeLog:

	* config.gcc: Add gt files since function_instance is GTY ((user)).
	* config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV intrinsic framework.
	(riscv_builtin_decl): Ditto.
	(riscv_expand_builtin): Ditto.
	* config/riscv/riscv-protos.h (builtin_decl): New function.
	(expand_builtin): Ditto.
	(enum riscv_builtin_class): New enum to classify RVV intrinsic and RISC-V general built-in.
	* config/riscv/riscv-vector-builtins.cc (class GTY): New declaration.
	(struct registered_function_hasher): New struct.
	(DEF_RVV_OP_TYPE): New macro.
	(DEF_RVV_TYPE): Ditto.
	(DEF_RVV_PRED_TYPE): Ditto.
	(GTY): New declaration.
	(add_attribute): New function.
	(check_required_extensions): Ditto.
	(rvv_arg_type_info::get_tree_type): Ditto.
	(function_instance::function_instance): Ditto.
	(function_instance::operator==): Ditto.
	(function_instance::any_type_float_p): Ditto.
	(function_instance::get_return_type): Ditto.
	(function_instance::get_arg_type): Ditto.
	(function_instance::hash): Ditto.
	(function_instance::call_properties): Ditto.
	(function_instance::reads_global_state_p): Ditto.
	(function_instance::modifies_global_state_p): Ditto.
	(function_instance::could_trap_p): Ditto.
	(function_builder::function_builder): Ditto.
	(function_builder::~function_builder): Ditto.
	(function_builder::allocate_argument_types): Ditto.
	(function_builder::register_function_group): Ditto.
	(function_builder::append_name): Ditto.
	(function_builder::finish_name): Ditto.
	(function_builder::get_attributes): Ditto.
	(function_builder::add_function): Ditto.
	(function_builder::add_unique_function): Ditto.
	(function_call_info::function_call_info): Ditto.
	(function_expander::function_expander): Ditto.
	(function_expander::add_input_operand): Ditto.
	(function_expander::generate_insn): Ditto.
	(registered_function_hasher::hash): Ditto.
	(registered_function_hasher::equal): Ditto.
	(builtin_decl): Ditto.
	(expand_builtin): Ditto.
	(gt_ggc_mx): Define for using GCC garbage collect.
	(gt_pch_nx): Define for using GCC garbage collect.
	* config/riscv/riscv-vector-builtins.def (DEF_RVV_OP_TYPE): New macro.
	(DEF_RVV_PRED_TYPE): Ditto.
	(vbool64_t): Add suffix.
	(vbool32_t): Ditto.
	(vbool16_t): Ditto.
	(vbool8_t): Ditto.
	(vbool4_t): Ditto.
	(vbool2_t): Ditto.
	(vbool1_t): Ditto.
	(vint8mf8_t): Ditto.
	(vuint8mf8_t): Ditto.
	(vint8mf4_t): Ditto.
	(vuint8mf4_t): Ditto.
	(vint8mf2_t): Ditto.
	(vuint8mf2_t): Ditto.
	(vint8m1_t): Ditto.
	(vuint8m1_t): Ditto.
	(vint8m2_t): Ditto.
	(vuint8m2_t): Ditto.
	(vint8m4_t): Ditto.
	(vuint8m4_t): Ditto.
	(vint8m8_t): Ditto.
	(vuint8m8_t): Ditto.
	(vint16mf4_t): Ditto.
	(vuint16mf4_t): Ditto.
	(vint16mf2_t): Ditto.
	(vuint16mf2_t): Ditto.
	(vint16m1_t): Ditto.
	(vuint16m1_t): Ditto.
	(vint16m2_t): Ditto.
	(vuint16m2_t): Ditto.
	(vint16m4_t): Ditto.
	(vuint16m4_t): Ditto.
	(vint16m8_t): Ditto.
	(vuint16m8_t): Ditto.
	(vint32mf2_t): Ditto.
	(vuint32mf2_t): Ditto.
	(vint32m1_t): Ditto.
	(vuint32m1_t): Ditto.
	(vint32m2_t): Ditto.
	(vuint32m2_t): Ditto.
	(vint32m4_t): Ditto.
	(vuint32m4_t): Ditto.
	(vint32m8_t): Ditto.
	(vuint32m8_t): Ditto.
	(vint64m1_t): Ditto.
	(vuint64m1_t): Ditto.
	(vint64m2_t): Ditto.
	(vuint64m2_t): Ditto.
	(vint64m4_t): Ditto.
	(vuint64m4_t): Ditto.
	(vint64m8_t): Ditto.
	(vuint64m8_t): Ditto.
	(vfloat32mf2_t): Ditto.
	(vfloat32m1_t): Ditto.
	(vfloat32m2_t): Ditto.
	(vfloat32m4_t): Ditto.
	(vfloat32m8_t): Ditto.
	(vfloat64m1_t): Ditto.
	(vfloat64m2_t): Ditto.
	(vfloat64m4_t): Ditto.
	(vfloat64m8_t): Ditto.
	(vv): Ditto.
	(vx): Ditto.
	(v): Ditto.
	(wv): Ditto.
	(wx): Ditto.
	(x_x_v): Ditto.
	(vf2): Ditto.
	(vf4): Ditto.
	(vf8): Ditto.
	(vvm): Ditto.
	(vxm): Ditto.
	(x_x_w): Ditto.
	(v_v): Ditto.
	(v_x): Ditto.
	(vs): Ditto.
	(mm): Ditto.
	(m): Ditto.
	(vf): Ditto.
	(vm): Ditto.
	(wf): Ditto.
	(vfm): Ditto.
	(v_f): Ditto.
	(ta): Ditto.
	(tu): Ditto.
	(ma): Ditto.
	(mu): Ditto.
	(tama): Ditto.
	(tamu): Ditto.
	(tuma): Ditto.
	(tumu): Ditto.
	(tam): Ditto.
	(tum): Ditto.
	* config/riscv/riscv-vector-builtins.h (GCC_RISCV_VECTOR_BUILTINS_H): New macro.
	(RVV_REQUIRE_RV64BIT): Ditto.
	(RVV_REQUIRE_ZVE64): Ditto.
	(RVV_REQUIRE_ELEN_FP_32): Ditto.
	(RVV_REQUIRE_ELEN_FP_64): Ditto.
	(enum operand_type_index): New enum.
	(DEF_RVV_OP_TYPE): New macro.
	(enum predication_type_index): New enum.
	(DEF_RVV_PRED_TYPE): New macro.
	(enum rvv_base_type): New enum.
	(struct rvv_builtin_suffixes): New struct.
	(struct rvv_arg_type_info): Ditto.
	(struct rvv_type_info): Ditto.
	(struct rvv_op_info): Ditto.
	(class registered_function): New class.
	(class function_base): Ditto.
	(class function_shape): Ditto.
	(struct function_group_info): New struct.
	(class GTY): New class.
	(class function_builder): Ditto.
	(class function_call_info): Ditto.
	(function_call_info::function_returns_void_p): New function.
	(class function_expander): New class.
	(function_instance::operator!=): New function.
	(function_expander::expand): Ditto.
	(function_expander::add_input_operand): Ditto.
	(function_base::call_properties): Ditto.

---
 gcc/config.gcc                             |   2 +
 gcc/config/riscv/riscv-builtins.cc         |  44 +-
 gcc/config/riscv/riscv-protos.h            |  17 +
 gcc/config/riscv/riscv-vector-builtins.cc  | 475 ++++++++++++++++++++-
 gcc/config/riscv/riscv-vector-builtins.def | 245 ++++++++---
 gcc/config/riscv/riscv-vector-builtins.h   | 363 ++++++++++++++++
 6 files changed, 1065 insertions(+), 81 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 8d5972fecf7..486e8790544 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -519,6 +519,8 @@ riscv*)
 	extra_objs="${extra_objs} riscv-vector-builtins.o"
 	d_target_objs="riscv-d.o"
 	extra_headers="riscv_vector.h"
+	target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
+	target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.h"
 	;;
 rs6000*-*-*)
 	extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 14865d70955..9930340d32b 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -223,7 +223,10 @@ riscv_init_builtins (void)
 	{
 	  tree type = riscv_build_function_type (d->prototype);
 	  riscv_builtin_decls[i]
-	    = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL);
+	    = add_builtin_function (d->name, type,
+				    (i << RISCV_BUILTIN_SHIFT)
+				      + RISCV_BUILTIN_GENERAL,
+				    BUILT_IN_MD, NULL, NULL);
 	  riscv_builtin_decl_index[d->icode] = i;
 	}
     }
@@ -234,9 +237,18 @@ riscv_init_builtins (void)
 tree
 riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
 {
-  if (code >= ARRAY_SIZE (riscv_builtins))
-    return error_mark_node;
-  return riscv_builtin_decls[code];
+  unsigned int subcode = code >> RISCV_BUILTIN_SHIFT;
+  switch (code & RISCV_BUILTIN_CLASS)
+    {
+    case RISCV_BUILTIN_GENERAL:
+      if (subcode >= ARRAY_SIZE (riscv_builtins))
+	return error_mark_node;
+      return riscv_builtin_decls[subcode];
+
+    case RISCV_BUILTIN_VECTOR:
+      return riscv_vector::builtin_decl (subcode, initialize_p);
+    }
+  return error_mark_node;
 }
 
 /* Take argument ARGNO from EXP's argument list and convert it into
@@ -303,15 +315,23 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
-  const struct riscv_builtin_description *d = &riscv_builtins[fcode];
-
-  switch (d->builtin_type)
+  unsigned int subcode = fcode >> RISCV_BUILTIN_SHIFT;
+  switch (fcode & RISCV_BUILTIN_CLASS)
     {
-    case RISCV_BUILTIN_DIRECT:
-      return riscv_expand_builtin_direct (d->icode, target, exp, true);
-
-    case RISCV_BUILTIN_DIRECT_NO_TARGET:
-      return riscv_expand_builtin_direct (d->icode, target, exp, false);
+      case RISCV_BUILTIN_VECTOR:
+        return riscv_vector::expand_builtin (subcode, exp, target);
+      case RISCV_BUILTIN_GENERAL: {
+	const struct riscv_builtin_description *d = &riscv_builtins[subcode];
+
+	switch (d->builtin_type)
+	  {
+	  case RISCV_BUILTIN_DIRECT:
+	    return riscv_expand_builtin_direct (d->icode, target, exp, true);
+
+	  case RISCV_BUILTIN_DIRECT_NO_TARGET:
+	    return riscv_expand_builtin_direct (d->icode, target, exp, false);
+	  }
+      }
     }
 
   gcc_unreachable ();
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index a44b34d1278..f8c9932ff89 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -124,6 +124,23 @@ extern const char *mangle_builtin_type (const_tree);
 extern bool verify_type_context (location_t, type_context_kind, const_tree, bool);
 #endif
 extern void handle_pragma_vector (void);
+extern tree builtin_decl (unsigned, bool);
+extern rtx expand_builtin (unsigned int, tree, rtx);
 }
 
+/* We classify builtin types into two classes:
+   1. General builtin class which is defined in riscv_builtins.
+   2. Vector builtin class which is a special builtin architecture
+      that implement intrinsic short into "pragma".  */
+enum riscv_builtin_class
+{
+  RISCV_BUILTIN_GENERAL,
+  RISCV_BUILTIN_VECTOR
+};
+
+const unsigned int RISCV_BUILTIN_SHIFT = 1;
+
+/* Mask that selects the riscv_builtin_class part of a function code.  */
+const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1;
+
 #endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index 55d45651618..5c20788b3ab 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -66,13 +66,55 @@ struct vector_type_info
   const char *mangled_name;
 };
 
-/* Information about each RVV type.  */
+/* Describes a function decl.  */
+class GTY (()) registered_function
+{
+public:
+  function_instance GTY ((skip)) instance;
+
+  /* The decl itself.  */
+  tree GTY ((skip)) decl;
+};
+
+/* Hash traits for registered_function.  */
+struct registered_function_hasher : nofree_ptr_hash<registered_function>
+{
+  typedef function_instance compare_type;
+
+  static hashval_t hash (value_type);
+  static bool equal (value_type, const compare_type &);
+};
+
+/* Static information about each RVV type.  */
 static CONSTEXPR const vector_type_info vector_types[] = {
 #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, ARGS...)                          \
   {#NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME},
 #include "riscv-vector-builtins.def"
 };
 
+/* Static information about operand suffix for each RVV type.  */
+const char *const operand_suffixes[NUM_OP_TYPES] = {
+  "", /* OP_TYPE_none.  */
+#define DEF_RVV_OP_TYPE(NAME) "_" # NAME,
+#include "riscv-vector-builtins.def"
+};
+
+/* Static information about type suffix for each RVV type.  */
+const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1] = {
+#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE,         \
+		     VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX,    \
+		     VSETVL_SUFFIX)                                            \
+  {#VECTOR_SUFFIX, #SCALAR_SUFFIX, #VSETVL_SUFFIX},
+#include "riscv-vector-builtins.def"
+};
+
+/* Static information about predication suffix for each RVV type.  */
+const char *const predication_suffixes[NUM_PRED_TYPES] = {
+  "", /* PRED_TYPE_none.  */
+#define DEF_RVV_PRED_TYPE(NAME) "_" # NAME,
+#include "riscv-vector-builtins.def"
+};
+
 /* The RVV types, with their built-in
    "__rvv..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
    yields a null tree.  */
@@ -82,6 +124,14 @@ static GTY (()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
 extern GTY (()) rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
 rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
 
+/* The list of all registered function decls, indexed by code.  */
+static GTY (()) vec<registered_function *, va_gc> *registered_functions;
+
+/* All registered function decls, hashed on the function_instance
+   that they implement.  This is used for looking up implementations of
+   overloaded functions.  */
+static hash_table<registered_function_hasher> *function_table;
+
 /* RAII class for enabling enough RVV features to define the built-in
    types and implement the riscv_vector.h pragma.
 
@@ -118,6 +168,13 @@ rvv_switcher::~rvv_switcher ()
 	  sizeof (have_regs_of_mode));
 }
 
+/* Add attribute NAME to ATTRS.  */
+static tree
+add_attribute (const char *name, tree attrs)
+{
+  return tree_cons (get_identifier (name), NULL_TREE, attrs);
+}
+
 /* Add type attributes to builtin type tree, currently only the mangled name. */
 static void
 add_vector_type_attribute (tree type, const char *mangled_name)
@@ -215,6 +272,7 @@ static void
 register_vector_type (vector_type_index type)
 {
   tree vectype = abi_vector_types[type];
+
   /* When vectype is NULL, the corresponding builtin type
      is disabled according to '-march'.  */
   if (!vectype)
@@ -237,6 +295,386 @@ register_vector_type (vector_type_index type)
   builtin_types[type].vector_ptr = build_pointer_type (vectype);
 }
 
+/* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are
+   enabled.  */
+static bool
+check_required_extensions (uint64_t required_extensions)
+{
+  uint64_t riscv_isa_flags = 0;
+
+  if (TARGET_VECTOR_ELEN_FP_32)
+    riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32;
+  if (TARGET_VECTOR_ELEN_FP_64)
+    riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64;
+  if (TARGET_MIN_VLEN > 32)
+    riscv_isa_flags |= RVV_REQUIRE_ZVE64;
+  if (TARGET_64BIT)
+    riscv_isa_flags |= RVV_REQUIRE_RV64BIT;
+
+  uint64_t missing_extensions = required_extensions & ~riscv_isa_flags;
+  if (missing_extensions != 0)
+    return false;
+  return true;
+}
+
+tree
+rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const
+{
+  switch (base_type)
+    {
+    case RVV_BASE_vector:
+      return builtin_types[type_idx].vector;
+    case RVV_BASE_scalar:
+      return builtin_types[type_idx].scalar;
+    case RVV_BASE_vector_ptr:
+      return builtin_types[type_idx].vector_ptr;
+    case RVV_BASE_scalar_ptr:
+      return builtin_types[type_idx].scalar_ptr;
+    case RVV_BASE_scalar_const_ptr:
+      return builtin_types[type_idx].scalar_const_ptr;
+    case RVV_BASE_void:
+      return void_type_node;
+    case RVV_BASE_size:
+      return size_type_node;
+    case RVV_BASE_ptrdiff:
+      return ptrdiff_type_node;
+    case RVV_BASE_unsigned_long:
+      return long_unsigned_type_node;
+    case RVV_BASE_long:
+      return long_integer_type_node;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+function_instance::function_instance (const char *base_name_in,
+				      const function_base *base_in,
+				      const function_shape *shape_in,
+				      rvv_type_info type_in,
+				      predication_type_index pred_in,
+				      const rvv_op_info *op_info_in)
+  : base_name (base_name_in), base (base_in), shape (shape_in), type (type_in),
+    pred (pred_in), op_info (op_info_in)
+{
+}
+
+bool
+function_instance::operator== (const function_instance &other) const
+{
+  for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
+    if (op_info->args[i].base_type != other.op_info->args[i].base_type)
+      return false;
+  return (base == other.base && shape == other.shape
+	  && type.index == other.type.index && op_info->op == other.op_info->op
+	  && pred == other.pred
+	  && op_info->ret.base_type == other.op_info->ret.base_type);
+}
+
+bool
+function_instance::any_type_float_p () const
+{
+  if (FLOAT_MODE_P (TYPE_MODE (get_return_type ())))
+    return true;
+
+  for (int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
+    if (FLOAT_MODE_P (TYPE_MODE (get_arg_type (i))))
+      return true;
+
+  return false;
+}
+
+tree
+function_instance::get_return_type () const
+{
+  return op_info->ret.get_tree_type (type.index);
+}
+
+tree
+function_instance::get_arg_type (unsigned opno) const
+{
+  return op_info->args[opno].get_tree_type (type.index);
+}
+
+/* Return a hash code for a function_instance.  */
+hashval_t
+function_instance::hash () const
+{
+  inchash::hash h;
+  /* BASE uniquely determines BASE_NAME, so we don't need to hash both.  */
+  h.add_ptr (base);
+  h.add_ptr (shape);
+  h.add_int (type.index);
+  h.add_int (op_info->op);
+  h.add_int (pred);
+  h.add_int (op_info->ret.base_type);
+  for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
+    h.add_int (op_info->args[i].base_type);
+  return h.end ();
+}
+
+/* Return a set of CP_* flags that describe what the function could do,
+   taking the command-line flags into account.  */
+unsigned int
+function_instance::call_properties () const
+{
+  unsigned int flags = base->call_properties (*this);
+
+  /* -fno-trapping-math means that we can assume any FP exceptions
+     are not user-visible.  */
+  if (!flag_trapping_math)
+    flags &= ~CP_RAISE_FP_EXCEPTIONS;
+
+  return flags;
+}
+
+/* Return true if calls to the function could read some form of
+   global state.  */
+bool
+function_instance::reads_global_state_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Preserve any dependence on rounding mode, flush to zero mode, etc.
+     There is currently no way of turning this off; in particular,
+     -fno-rounding-math (which is the default) means that we should make
+     the usual assumptions about rounding mode, which for intrinsics means
+     acting as the instructions do.  */
+  if (flags & CP_READ_FPCR)
+    return true;
+
+  /* Handle direct reads of global state.  */
+  return flags & (CP_READ_MEMORY | CP_READ_CSR);
+}
+
+/* Return true if calls to the function could modify some form of
+   global state.  */
+bool
+function_instance::modifies_global_state_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Preserve any exception state written back to the FPCR,
+     unless -fno-trapping-math says this is unnecessary.  */
+  if (flags & CP_RAISE_FP_EXCEPTIONS)
+    return true;
+
+  /* Handle direct modifications of global state.  */
+  return flags & (CP_WRITE_MEMORY | CP_WRITE_CSR);
+}
+
+/* Return true if calls to the function could raise a signal.  */
+bool
+function_instance::could_trap_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Handle functions that could raise SIGFPE.  */
+  if (flags & CP_RAISE_FP_EXCEPTIONS)
+    return true;
+
+  /* Handle functions that could raise SIGBUS or SIGSEGV.  */
+  if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
+    return true;
+
+  return false;
+}
+
+function_builder::function_builder ()
+{
+  m_direct_overloads = lang_GNU_CXX ();
+  gcc_obstack_init (&m_string_obstack);
+}
+
+function_builder::~function_builder ()
+{
+  obstack_free (&m_string_obstack, NULL);
+}
+
+/* Allocate arguments of the function.  */
+void
+function_builder::allocate_argument_types (const function_instance &instance,
+					   vec<tree> &argument_types) const
+{
+  for (unsigned int i = 0;
+       instance.op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
+    argument_types.quick_push (
+      instance.op_info->args[i].get_tree_type (instance.type.index));
+}
+
+/* Register all the functions in GROUP.  */
+void
+function_builder::register_function_group (const function_group_info &group)
+{
+  (*group.shape)->build (*this, group);
+}
+
+/* Add NAME to the end of the function name being built.  */
+void
+function_builder::append_name (const char *name)
+{
+  obstack_grow (&m_string_obstack, name, strlen (name));
+}
+
+/* Zero-terminate and complete the function name being built.  */
+char *
+function_builder::finish_name ()
+{
+  obstack_1grow (&m_string_obstack, 0);
+  return (char *) obstack_finish (&m_string_obstack);
+}
+
+/* Return the appropriate function attributes for INSTANCE.  */
+tree
+function_builder::get_attributes (const function_instance &instance)
+{
+  tree attrs = NULL_TREE;
+
+  if (!instance.modifies_global_state_p ())
+    {
+      if (instance.reads_global_state_p ())
+	attrs = add_attribute ("pure", attrs);
+      else
+	attrs = add_attribute ("const", attrs);
+    }
+
+  if (!flag_non_call_exceptions || !instance.could_trap_p ())
+    attrs = add_attribute ("nothrow", attrs);
+
+  return add_attribute ("leaf", attrs);
+}
+
+/* Add a function called NAME with type FNTYPE and attributes ATTRS.
+   INSTANCE describes what the function does.  */
+registered_function &
+function_builder::add_function (const function_instance &instance,
+				const char *name, tree fntype, tree attrs,
+				bool placeholder_p)
+{
+  unsigned int code = vec_safe_length (registered_functions);
+  code = (code << RISCV_BUILTIN_SHIFT) + RISCV_BUILTIN_VECTOR;
+
+  /* We need to be able to generate placeholders to enusre that we have a
+     consistent numbering scheme for function codes between the C and C++
+     frontends, so that everything ties up in LTO.
+
+     Currently, tree-streamer-in.c:unpack_ts_function_decl_value_fields
+     validates that tree nodes returned by TARGET_BUILTIN_DECL are non-NULL and
+     some node other than error_mark_node. This is a holdover from when builtin
+     decls were streamed by code rather than by value.
+
+     Ultimately, we should be able to remove this validation of BUILT_IN_MD
+     nodes and remove the target hook. For now, however, we need to appease the
+     validation and return a non-NULL, non-error_mark_node node, so we
+     arbitrarily choose integer_zero_node.  */
+  tree decl = placeholder_p
+		? integer_zero_node
+		: simulate_builtin_function_decl (input_location, name, fntype,
+						  code, NULL, attrs);
+
+  registered_function &rfn = *ggc_alloc<registered_function> ();
+  rfn.instance = instance;
+  rfn.decl = decl;
+  vec_safe_push (registered_functions, &rfn);
+
+  return rfn;
+}
+
+/* Add a built-in function for INSTANCE, with the argument types given
+   by ARGUMENT_TYPES and the return type given by RETURN_TYPE. NAME is
+   the "full" name for C function. OVERLOAD_NAME is the "short" name for
+   C++ overloaded function. OVERLOAD_NAME can be nullptr because some
+   instance doesn't have C++ overloaded function.  */
+void
+function_builder::add_unique_function (const function_instance &instance,
+				       const function_shape *shape,
+				       tree return_type,
+				       vec<tree> &argument_types)
+{
+  /* Do not add this function if it is invalid.  */
+  if (!check_required_extensions (instance.type.required_extensions))
+    return;
+
+  /* Add the function under its full (unique) name.  */
+  char *name = shape->get_name (*this, instance, false);
+  tree fntype
+    = build_function_type_array (return_type, argument_types.length (),
+				 argument_types.address ());
+  tree attrs = get_attributes (instance);
+  registered_function &rfn
+    = add_function (instance, name, fntype, attrs, false);
+
+  /* Enter the function into the hash table.  */
+  hashval_t hash = instance.hash ();
+  registered_function **rfn_slot
+    = function_table->find_slot_with_hash (instance, hash, INSERT);
+  gcc_assert (!*rfn_slot);
+  *rfn_slot = &rfn;
+
+  /* Also add the function under its overloaded alias, if we want
+     a separate decl for each instance of an overloaded function.  */
+  char *overload_name = shape->get_name (*this, instance, true);
+  if (overload_name)
+    {
+      /* Attribute lists shouldn't be shared.  */
+      tree attrs = get_attributes (instance);
+      bool placeholder_p = !m_direct_overloads;
+      add_function (instance, overload_name, fntype, attrs, placeholder_p);
+    }
+  obstack_free (&m_string_obstack, name);
+}
+
+function_call_info::function_call_info (location_t location_in,
+					const function_instance &instance_in,
+					tree fndecl_in)
+  : function_instance (instance_in), location (location_in), fndecl (fndecl_in)
+{}
+
+function_expander::function_expander (const function_instance &instance,
+				      tree fndecl_in, tree exp_in,
+				      rtx target_in)
+  : function_call_info (EXPR_LOCATION (exp_in), instance, fndecl_in),
+    exp (exp_in), target (target_in), opno (0)
+{
+  if (!function_returns_void_p ())
+    create_output_operand (&m_ops[opno++], target, TYPE_MODE (TREE_TYPE (exp)));
+}
+
+/* Take argument ARGNO from EXP's argument list and convert it into
+   an expand operand.  Store the operand in *M_OPS.  */
+void
+function_expander::add_input_operand (unsigned argno)
+{
+  tree arg = CALL_EXPR_ARG (exp, argno);
+  rtx x = expand_normal (arg);
+  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
+}
+
+/* Generate instruction ICODE, given that its operands have already
+   been added to M_OPS.  Return the value of the first operand.  */
+rtx
+function_expander::generate_insn (insn_code icode)
+{
+  gcc_assert (opno == insn_data[icode].n_generator_args);
+  if (!maybe_expand_insn (icode, opno, m_ops))
+    {
+      error ("invalid argument to built-in function");
+      return NULL_RTX;
+    }
+  return function_returns_void_p () ? const0_rtx : m_ops[0].value;
+}
+
+inline hashval_t
+registered_function_hasher::hash (value_type value)
+{
+  return value->instance.hash ();
+}
+
+inline bool
+registered_function_hasher::equal (value_type value, const compare_type &key)
+{
+  return value->instance == key;
+}
+
 /* If TYPE is a built-in type defined by the RVV ABI, return the mangled name,
    otherwise return NULL.  */
 const char *
@@ -356,4 +794,39 @@ handle_pragma_vector ()
     register_vector_type ((enum vector_type_index) type_i);
 }
 
+/* Return the function decl with RVV function subcode CODE, or error_mark_node
+   if no such function exists.  */
+tree
+builtin_decl (unsigned int code, bool)
+{
+  if (code >= vec_safe_length (registered_functions))
+    return error_mark_node;
+
+  return (*registered_functions)[code]->decl;
+}
+
+/* Expand a call to the RVV function with subcode CODE.  EXP is the call
+   expression and TARGET is the preferred location for the result.
+   Return the value of the lhs.  */
+rtx
+expand_builtin (unsigned int code, tree exp, rtx target)
+{
+  registered_function &rfn = *(*registered_functions)[code];
+  return function_expander (rfn.instance, rfn.decl, exp, target).expand ();
+}
+
 } // end namespace riscv_vector
+
+inline void
+gt_ggc_mx (function_instance *)
+{}
+
+inline void
+gt_pch_nx (function_instance *)
+{}
+
+inline void
+gt_pch_nx (function_instance *, gt_pointer_operator, void *)
+{}
+
+#include "gt-riscv-vector-builtins.h"
diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def
index 83603fedd57..b7a633ed376 100644
--- a/gcc/config/riscv/riscv-vector-builtins.def
+++ b/gcc/config/riscv/riscv-vector-builtins.def
@@ -19,181 +19,290 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 /* Use "DEF_RVV_TYPE" macro to define RVV datatype builtins.
-   1.The 1 argument is the name exposed to users.
+   1.The 'NAME' argument is the name exposed to users.
      For example, "vint32m1_t".
-   2.The 2 argument is the length of ABI-name.
+   2.The 'NCHARS' argument is the length of ABI-name.
      For example, length of "__rvv_int32m1_t" is 15.
-   3.The 3 argument is the ABI-name. For example, "__rvv_int32m1_t".
-   4.The 4 argument is associated scalar type which is used in
+   3.The 'ABI_NAME' argument is the ABI-name. For example, "__rvv_int32m1_t".
+   4.The 'SCALAR_TYPE' argument is associated scalar type which is used in
      "build_vector_type_for_mode". For "vint32m1_t", we use "intSI_type_node" in
      RV64. Otherwise, we use "long_integer_type_node".
-   5.The 5 and 6 argument are the machine modes of corresponding RVV type used
-     in "build_vector_type_for_mode". For "vint32m1_t", we use VNx2SImode when
-     TARGET_MIN_VLEN > 32. Otherwise the machine mode is VNx1SImode.  */
+   5.The 'VECTOR_MODE' is the machine modes of corresponding RVV type used
+     in "build_vector_type_for_mode" when TARGET_MIN_VLEN > 32.
+     For example: VECTOR_MODE = VNx2SI for "vint32m1_t".
+   6.The 'VECTOR_MODE_MIN_VLEN_32' is the machine modes of corresponding RVV
+     type used in "build_vector_type_for_mode" when TARGET_MIN_VLEN = 32. For
+     example: VECTOR_MODE_MIN_VLEN_32 = VNx1SI for "vint32m1_t".
+   7.The 'VECTOR_SUFFIX' define mode suffix for vector type.
+     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vector = i32m1.
+   8.The 'SCALAR_SUFFIX' define mode suffix for scalar type.
+     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].scalar = i32.
+   9.The 'VSETVL_SUFFIX' define mode suffix for vsetvli instruction.
+     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vsetvl = e32m1.
+*/
 
 #ifndef DEF_RVV_TYPE
 #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE,         \
-		     VECTOR_MODE_MIN_VLEN_32)
+		     VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX,    \
+		     VSETVL_SUFFIX)
+#endif
+
+/* Use "DEF_RVV_OP_TYPE" macro to define RVV operand types.
+   The 'NAME' will be concatenated into intrinsic function name.  */
+#ifndef DEF_RVV_OP_TYPE
+#define DEF_RVV_OP_TYPE(NAME)
+#endif
+
+/* Use "DEF_RVV_PRED_TYPE" macro to define RVV predication types.
+   The 'NAME' will be concatenated into intrinsic function name.  */
+#ifndef DEF_RVV_PRED_TYPE
+#define DEF_RVV_PRED_TYPE(NAME)
 #endif
 
 /* SEW/LMUL = 64:
    Only enable when TARGET_MIN_VLEN > 32 and machine mode = VNx1BImode.  */
-DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID)
+DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID, _b64, , )
 /* SEW/LMUL = 32:
    Machine mode = VNx2BImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx1BImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI)
+DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI, _b32, , )
 /* SEW/LMUL = 16:
    Machine mode = VNx2BImode when TARGET_MIN_VLEN = 32.
    Machine mode = VNx4BImode when TARGET_MIN_VLEN > 32.  */
-DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI)
+DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI, _b16, , )
 /* SEW/LMUL = 8:
    Machine mode = VNx8BImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx4BImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI)
+DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI, _b8, , )
 /* SEW/LMUL = 4:
    Machine mode = VNx16BImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx8BImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI)
+DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI, _b4, , )
 /* SEW/LMUL = 2:
    Machine mode = VNx32BImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx16BImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI)
+DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI, _b2, , )
 /* SEW/LMUL = 1:
    Machine mode = VNx64BImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx32BImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI)
+DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI, _b1, , )
 
 /* LMUL = 1/8:
    Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1QImode.  */
-DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID)
-DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID)
+DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID, _i8mf8, _i8,
+	      _e8mf8)
+DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID,
+	      _u8mf8, _u8, _e8mf8)
 /* LMUL = 1/4:
    Machine mode = VNx2QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx1QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI)
-DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI)
+DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI, _i8mf4,
+	      _i8, _e8mf4)
+DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI,
+	      _u8mf4, _u8, _e8mf4)
 /* LMUL = 1/2:
    Machine mode = VNx4QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx2QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI)
-DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI)
+DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI, _i8mf2,
+	      _i8, _e8mf2)
+DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI,
+	      _u8mf2, _u8, _e8mf2)
 /* LMUL = 1:
    Machine mode = VNx8QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx4QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI)
-DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI)
+DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI, _i8m1, _i8,
+	      _e8m1)
+DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI,
+	      _u8m1, _u8, _e8m1)
 /* LMUL = 2:
    Machine mode = VNx16QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx8QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI)
-DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI)
+DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI, _i8m2, _i8,
+	      _e8m2)
+DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI,
+	      _u8m2, _u8, _e8m2)
 /* LMUL = 4:
    Machine mode = VNx32QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx16QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI)
-DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI)
+DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI, _i8m4,
+	      _i8, _e8m4)
+DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI,
+	      _u8m4, _u8, _e8m4)
 /* LMUL = 8:
    Machine mode = VNx64QImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx32QImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI)
-DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI)
+DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI, _i8m8,
+	      _i8, _e8m8)
+DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI,
+	      _u8m8, _u8, _e8m8)
 
 /* LMUL = 1/4:
    Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1HImode.  */
-DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID)
-DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID)
+DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID, _i16mf4,
+	      _i16, _e16mf4)
+DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID,
+	      _u16mf4, _u16, _e16mf4)
 /* LMUL = 1/2:
    Machine mode = VNx2HImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx1HImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI)
+DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI, _i16mf2,
+	      _i16, _e16mf2)
 DEF_RVV_TYPE (vuint16mf2_t, 17, __rvv_uint16mf2_t, unsigned_intHI, VNx2HI,
-	      VNx1HI)
+	      VNx1HI, _u16mf2, _u16, _e16mf2)
 /* LMUL = 1:
    Machine mode = VNx4HImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx2HImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI)
-DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI)
+DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI, _i16m1,
+	      _i16, _e16m1)
+DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI,
+	      _u16m1, _u16, _e16m1)
 /* LMUL = 2:
    Machine mode = VNx8HImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx4HImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI)
-DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI)
+DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI, _i16m2,
+	      _i16, _e16m2)
+DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI,
+	      _u16m2, _u16, _e16m2)
 /* LMUL = 4:
    Machine mode = VNx16HImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx8HImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI)
+DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI, _i16m4,
+	      _i16, _e16m4)
 DEF_RVV_TYPE (vuint16m4_t, 16, __rvv_uint16m4_t, unsigned_intHI, VNx16HI,
-	      VNx8HI)
+	      VNx8HI, _u16m4, _u16, _e16m4)
 /* LMUL = 8:
    Machine mode = VNx32HImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx16HImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI)
+DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI, _i16m8,
+	      _i16, _e16m8)
 DEF_RVV_TYPE (vuint16m8_t, 16, __rvv_uint16m8_t, unsigned_intHI, VNx32HI,
-	      VNx16HI)
+	      VNx16HI, _u16m8, _u16, _e16m8)
 
 /* LMUL = 1/2:
    Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SImode.  */
-DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID)
-DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID)
+DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID, _i32mf2,
+	      _i32, _e32mf2)
+DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID,
+	      _u32mf2, _u32, _e32mf2)
 /* LMUL = 1:
    Machine mode = VNx2SImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx1SImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI)
-DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI)
+DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI, _i32m1,
+	      _i32, _e32m1)
+DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI,
+	      _u32m1, _u32, _e32m1)
 /* LMUL = 2:
    Machine mode = VNx4SImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx2SImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI)
-DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI)
+DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI, _i32m2,
+	      _i32, _e32m2)
+DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI,
+	      _u32m2, _u32, _e32m2)
 /* LMUL = 4:
    Machine mode = VNx8SImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx4SImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI)
-DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI)
+DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI, _i32m4,
+	      _i32, _e32m4)
+DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI,
+	      _u32m4, _u32, _e32m4)
 /* LMUL = 8:
    Machine mode = VNx16SImode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx8SImode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI)
+DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI, _i32m8,
+	      _i32, _e32m8)
 DEF_RVV_TYPE (vuint32m8_t, 16, __rvv_uint32m8_t, unsigned_int32, VNx16SI,
-	      VNx8SI)
+	      VNx8SI, _u32m8, _u32, _e32m8)
 
 /* SEW = 64:
    Disable when TARGET_MIN_VLEN > 32.  */
-DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID)
-DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID)
-DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID)
-DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID)
-DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID)
-DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID)
-DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID)
-DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID)
+DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID, _i64m1,
+	      _i64, _e64m1)
+DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID,
+	      _u64m1, _u64, _e64m1)
+DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID, _i64m2,
+	      _i64, _e64m2)
+DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID,
+	      _u64m2, _u64, _e64m2)
+DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID, _i64m4,
+	      _i64, _e64m4)
+DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID,
+	      _u64m4, _u64, _e64m4)
+DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID, _i64m8,
+	      _i64, _e64m8)
+DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID,
+	      _u64m8, _u64, _e64m8)
 
 /* LMUL = 1/2:
    Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SFmode.  */
-DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID)
+DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID,
+	      _f32mf2, _f32, _e32mf2)
 /* LMUL = 1:
    Machine mode = VNx2SFmode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx1SFmode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF)
+DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF,
+	      _f32m1, _f32, _e32m1)
 /* LMUL = 2:
    Machine mode = VNx4SFmode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx2SFmode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF)
+DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF,
+	      _f32m2, _f32, _e32m2)
 /* LMUL = 4:
    Machine mode = VNx8SFmode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx4SFmode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF)
+DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF,
+	      _f32m4, _f32, _e32m4)
 /* LMUL = 8:
    Machine mode = VNx16SFmode when TARGET_MIN_VLEN > 32.
    Machine mode = VNx8SFmode when TARGET_MIN_VLEN = 32.  */
-DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF)
+DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF,
+	      _f32m8, _f32, _e32m8)
 
 /* SEW = 64:
    Disable when TARGET_VECTOR_FP64.  */
-DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID)
-DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID)
-DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID)
-DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID)
+DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID, _f64m1,
+	      _f64, _e64m1)
+DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID, _f64m2,
+	      _f64, _e64m2)
+DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID, _f64m4,
+	      _f64, _e64m4)
+DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID, _f64m8,
+	      _f64, _e64m8)
+
+DEF_RVV_OP_TYPE (vv)
+DEF_RVV_OP_TYPE (vx)
+DEF_RVV_OP_TYPE (v)
+DEF_RVV_OP_TYPE (wv)
+DEF_RVV_OP_TYPE (wx)
+DEF_RVV_OP_TYPE (x_x_v)
+DEF_RVV_OP_TYPE (vf2)
+DEF_RVV_OP_TYPE (vf4)
+DEF_RVV_OP_TYPE (vf8)
+DEF_RVV_OP_TYPE (vvm)
+DEF_RVV_OP_TYPE (vxm)
+DEF_RVV_OP_TYPE (x_x_w)
+DEF_RVV_OP_TYPE (v_v)
+DEF_RVV_OP_TYPE (v_x)
+DEF_RVV_OP_TYPE (vs)
+DEF_RVV_OP_TYPE (mm)
+DEF_RVV_OP_TYPE (m)
+DEF_RVV_OP_TYPE (vf)
+DEF_RVV_OP_TYPE (vm)
+DEF_RVV_OP_TYPE (wf)
+DEF_RVV_OP_TYPE (vfm)
+DEF_RVV_OP_TYPE (v_f)
+
+DEF_RVV_PRED_TYPE (ta)
+DEF_RVV_PRED_TYPE (tu)
+DEF_RVV_PRED_TYPE (ma)
+DEF_RVV_PRED_TYPE (mu)
+DEF_RVV_PRED_TYPE (tama)
+DEF_RVV_PRED_TYPE (tamu)
+DEF_RVV_PRED_TYPE (tuma)
+DEF_RVV_PRED_TYPE (tumu)
+DEF_RVV_PRED_TYPE (m)
+DEF_RVV_PRED_TYPE (tam)
+DEF_RVV_PRED_TYPE (tum)
 
+#undef DEF_RVV_PRED_TYPE
+#undef DEF_RVV_OP_TYPE
 #undef DEF_RVV_TYPE
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
index ea67da9905c..425da12326c 100644
--- a/gcc/config/riscv/riscv-vector-builtins.h
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -21,8 +21,101 @@
 #ifndef GCC_RISCV_VECTOR_BUILTINS_H
 #define GCC_RISCV_VECTOR_BUILTINS_H
 
+/* The full name of an RVV intrinsic function is the concatenation of:
+
+   - the base name ("vadd", etc.)
+   - the operand suffix ("_vv", "_vx", etc.)
+   - the type suffix ("_i32m1", "_i32mf2", etc.)
+   - the predication suffix ("_tamu", "_tumu", etc.)
+
+   Each piece of information is individually useful, so we retain this
+   classification throughout:
+
+   - function_base represents the base name.
+
+   - operand_type_index can be used as an index to get operand suffix.
+
+   - rvv_op_info can be used as an index to get argument suffix.
+
+   - predication_type_index can be used as an index to get predication suffix.
+
+   In addition to its unique full name, a function may have a shorter
+   overloaded alias.  This alias removes pieces of the suffixes that
+   can be inferred from the arguments, such as by shortening the mode
+   suffix or dropping some of the type suffixes.  The base name and the
+   predication suffix stay the same.
+
+   - The function_instance class describes contains all properties of each
+     individual function. Such these information will be used by
+     function_builder, function_base, function_shape, gimple_folder,
+     function_expander, etc.
+
+   - The function_builder class provides several helper function to add an
+     intrinsic function.
+
+   - The function_shape class describes how that instruction has been presented
+     at the language level:
+
+      1. Determine the function name for C and C++ overload function which can
+	 be recognized by compiler at language level for each instruction
+	 according to members of function_instance (base name, operand suffix,
+	 type suffix, predication suffix, etc.).
+
+      2. Specify the arguments type and return type of each function to
+	 describe how that instruction has presented at language level.
+
+   - The function_base describes how the underlying instruction behaves.
+
+   The static list of functions uses function_group to describe a group
+   of related functions.  The function_builder class is responsible for
+   expanding this static description into a list of individual functions
+   and registering the associated built-in functions.  function_instance
+   describes one of these individual functions in terms of the properties
+   described above.
+
+   The classes involved in compiling a function call are:
+
+   - function_resolver, which resolves an overloaded function call to a
+     specific function_instance and its associated function decl.
+
+   - function_checker, which checks whether the values of the arguments
+     conform to the RVV ISA specification.
+
+   - gimple_folder, which tries to fold a function call at the gimple level
+
+   - function_expander, which expands a function call into rtl instructions
+
+   function_resolver and function_checker operate at the language level
+   and so are associated with the function_shape.  gimple_folder and
+   function_expander are concerned with the behavior of the function
+   and so are associated with the function_base.  */
+
 namespace riscv_vector {
 
+/* Flags that describe what a function might do, in addition to reading
+   its arguments and returning a result.  */
+static const unsigned int CP_READ_FPCR = 1U << 0;
+static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
+static const unsigned int CP_READ_MEMORY = 1U << 2;
+static const unsigned int CP_WRITE_MEMORY = 1U << 3;
+static const unsigned int CP_READ_CSR = 1U << 4;
+static const unsigned int CP_WRITE_CSR = 1U << 5;
+
+/* Bit values used to identify required extensions for RVV intrinsics.  */
+#define RVV_REQUIRE_RV64BIT (1 << 0)	/* Require RV64.  */
+#define RVV_REQUIRE_ZVE64 (1 << 1)	/* Require TARGET_MIN_VLEN > 32.  */
+#define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32.  */
+#define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64.  */
+
+/* Enumerates the RVV operand types.  */
+enum operand_type_index
+{
+  OP_TYPE_none,
+#define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
+#include "riscv-vector-builtins.def"
+  NUM_OP_TYPES
+};
+
 /* Enumerates the RVV types, together called
    "vector types" for brevity.  */
 enum vector_type_index
@@ -32,6 +125,31 @@ enum vector_type_index
   NUM_VECTOR_TYPES
 };
 
+/* Enumerates the RVV governing predication types.  */
+enum predication_type_index
+{
+  PRED_TYPE_none,
+#define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
+#include "riscv-vector-builtins.def"
+  NUM_PRED_TYPES
+};
+
+/* Enumerates the RVV base types.  */
+enum rvv_base_type
+{
+  RVV_BASE_vector,
+  RVV_BASE_scalar,
+  RVV_BASE_vector_ptr,
+  RVV_BASE_scalar_ptr,
+  RVV_BASE_scalar_const_ptr,
+  RVV_BASE_void,
+  RVV_BASE_size,
+  RVV_BASE_ptrdiff,
+  RVV_BASE_unsigned_long,
+  RVV_BASE_long,
+  NUM_BASE_TYPES
+};
+
 /* Builtin types that are used to register RVV intrinsics.  */
 struct GTY (()) rvv_builtin_types_t
 {
@@ -42,6 +160,251 @@ struct GTY (()) rvv_builtin_types_t
   tree scalar_const_ptr;
 };
 
+/* Builtin suffix that are used to register RVV intrinsics.  */
+struct rvv_builtin_suffixes
+{
+  const char *vector;
+  const char *scalar;
+  const char *vsetvl;
+};
+
+/* RVV Builtin argument information.  */
+struct rvv_arg_type_info
+{
+  CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
+    : base_type (base_type_in)
+  {}
+  enum rvv_base_type base_type;
+
+  tree get_tree_type (vector_type_index) const;
+};
+
+/* Static information for each operand.  */
+struct rvv_type_info
+{
+  enum vector_type_index index;
+  uint64_t required_extensions;
+};
+
+/* RVV Builtin operands information.  */
+struct rvv_op_info
+{
+  const rvv_type_info *types;
+  const operand_type_index op;
+  rvv_arg_type_info ret;
+  const rvv_arg_type_info *args;
+};
+
+class registered_function;
+class function_base;
+class function_shape;
+
+/* Static information about a set of functions.  */
+struct function_group_info
+{
+  /* The base name, as a string.  */
+  const char *base_name;
+
+  /* Describes the behavior associated with the function base name.  */
+  const function_base *const *base;
+
+  /* The shape of the functions, as described above the class definition.
+     It's possible to have entries with the same base name but different
+     shapes.  */
+  const function_shape *const *shape;
+
+  /* A list of the available operand types, predication types,
+     and of the available operand datatype.
+     The function supports every combination of the two.
+     The list of predication is terminated by two NUM_PRED_TYPES,
+     while the list of operand info is terminated by NUM_BASE_TYPES.
+     The list of these type suffix is lexicographically ordered based
+     on the index value.  */
+  const predication_type_index *preds;
+  const rvv_op_info ops_infos;
+};
+
+class GTY ((user)) function_instance
+{
+public:
+  function_instance (const char *, const function_base *,
+		     const function_shape *, rvv_type_info,
+		     predication_type_index, const rvv_op_info *);
+
+  bool operator== (const function_instance &) const;
+  bool operator!= (const function_instance &) const;
+  hashval_t hash () const;
+
+  unsigned int call_properties () const;
+  bool reads_global_state_p () const;
+  bool modifies_global_state_p () const;
+  bool could_trap_p () const;
+
+  /* Return true if return type or arguments are floating point type.  */
+  bool any_type_float_p () const;
+
+  tree get_return_type () const;
+  tree get_arg_type (unsigned opno) const;
+
+  /* The properties of the function.  (The explicit "enum"s are required
+     for gengtype.)  */
+  const char *base_name;
+  const function_base *base;
+  const function_shape *shape;
+  rvv_type_info type;
+  enum predication_type_index pred;
+  const rvv_op_info *op_info;
+};
+
+/* A class for building and registering function decls.  */
+class function_builder
+{
+public:
+  function_builder ();
+  ~function_builder ();
+
+  void allocate_argument_types (const function_instance &, vec<tree> &) const;
+  void add_unique_function (const function_instance &, const function_shape *,
+			    tree, vec<tree> &);
+  void register_function_group (const function_group_info &);
+  void append_name (const char *);
+  char *finish_name ();
+
+private:
+  tree get_attributes (const function_instance &);
+
+  registered_function &add_function (const function_instance &, const char *,
+				     tree, tree, bool);
+
+  /* True if we should create a separate decl for each instance of an
+     overloaded function, instead of using function_builder.  */
+  bool m_direct_overloads;
+
+  /* Used for building up function names.  */
+  obstack m_string_obstack;
+};
+
+/* A base class for handling calls to built-in functions.  */
+class function_call_info : public function_instance
+{
+public:
+  function_call_info (location_t, const function_instance &, tree);
+
+  bool function_returns_void_p ();
+
+  /* The location of the call.  */
+  location_t location;
+
+  /* The FUNCTION_DECL that is being called.  */
+  tree fndecl;
+};
+
+/* Return true if the function has no return value.  */
+inline bool
+function_call_info::function_returns_void_p ()
+{
+  return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+}
+
+/* A class for expanding a function call into RTL.  */
+class function_expander : public function_call_info
+{
+public:
+  function_expander (const function_instance &, tree, tree, rtx);
+  rtx expand ();
+
+  void add_input_operand (machine_mode, rtx);
+  void add_input_operand (unsigned argno);
+  rtx generate_insn (insn_code);
+
+  /* The function call expression.  */
+  tree exp;
+
+  /* For functions that return a value, this is the preferred location
+     of that value.  It could be null or could have a different mode
+     from the function return type.  */
+  rtx target;
+
+  /* The number of the operands.  */
+  int opno;
+
+private:
+  /* Used to build up the operands to an instruction.  */
+  struct expand_operand m_ops[MAX_RECOG_OPERANDS];
+};
+
+/* Provides information about a particular function base name, and handles
+   tasks related to the base name.  */
+class function_base
+{
+public:
+  /* Return a set of CP_* flags that describe what the function might do,
+     in addition to reading its arguments and returning a result.  */
+  virtual unsigned int call_properties (const function_instance &) const;
+
+  /* Expand the given call into rtl.  Return the result of the function,
+     or an arbitrary value if the function doesn't return a result.  */
+  virtual rtx expand (function_expander &) const = 0;
+};
+
+/* Classifies functions into "shapes" base on:
+
+   - Base name of the intrinsic function.
+
+   - Operand types list.
+
+   - Argument type list.
+
+   - Predication type list.  */
+class function_shape
+{
+public:
+  /* Shape the function name according to function_instance.  */
+  virtual char *get_name (function_builder &, const function_instance &,
+			  bool) const
+    = 0;
+
+  /* Define all functions associated with the given group.  */
+  virtual void build (function_builder &, const function_group_info &) const
+    = 0;
+};
+
+extern const char *const operand_suffixes[NUM_OP_TYPES];
+extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
+extern const char *const predication_suffixes[NUM_PRED_TYPES];
+extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
+
+inline bool
+function_instance::operator!= (const function_instance &other) const
+{
+  return !operator== (other);
+}
+
+/* Expand the call and return its lhs.  */
+inline rtx
+function_expander::expand ()
+{
+  return base->expand (*this);
+}
+
+/* Create op and add it into M_OPS and increase OPNO.  */
+inline void
+function_expander::add_input_operand (machine_mode mode, rtx op)
+{
+  create_input_operand (&m_ops[opno++], op, mode);
+}
+
+/* Default implementation of function_base::call_properties, with conservatively
+   correct behavior for floating-point instructions.  */
+inline unsigned int
+function_base::call_properties (const function_instance &instance) const
+{
+  unsigned int flags = 0;
+  if (instance.any_type_float_p ())
+    return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
+  return flags;
+}
+
 } // end namespace riscv_vector
 
 #endif
-- 
2.36.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] RISC-V: Add RVV intrinsic basic framework.
  2022-10-17  8:20 [PATCH] RISC-V: Add RVV intrinsic basic framework juzhe.zhong
@ 2022-10-21  4:23 ` Kito Cheng
  0 siblings, 0 replies; 2+ messages in thread
From: Kito Cheng @ 2022-10-21  4:23 UTC (permalink / raw)
  To: juzhe.zhong; +Cc: gcc-patches

Verified, committed to trunk.

On Mon, Oct 17, 2022 at 4:21 PM <juzhe.zhong@rivai.ai> wrote:
>
> From: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
>
> gcc/ChangeLog:
>
>         * config.gcc: Add gt files since function_instance is GTY ((user)).
>         * config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV intrinsic framework.
>         (riscv_builtin_decl): Ditto.
>         (riscv_expand_builtin): Ditto.
>         * config/riscv/riscv-protos.h (builtin_decl): New function.
>         (expand_builtin): Ditto.
>         (enum riscv_builtin_class): New enum to classify RVV intrinsic and RISC-V general built-in.
>         * config/riscv/riscv-vector-builtins.cc (class GTY): New declaration.
>         (struct registered_function_hasher): New struct.
>         (DEF_RVV_OP_TYPE): New macro.
>         (DEF_RVV_TYPE): Ditto.
>         (DEF_RVV_PRED_TYPE): Ditto.
>         (GTY): New declaration.
>         (add_attribute): New function.
>         (check_required_extensions): Ditto.
>         (rvv_arg_type_info::get_tree_type): Ditto.
>         (function_instance::function_instance): Ditto.
>         (function_instance::operator==): Ditto.
>         (function_instance::any_type_float_p): Ditto.
>         (function_instance::get_return_type): Ditto.
>         (function_instance::get_arg_type): Ditto.
>         (function_instance::hash): Ditto.
>         (function_instance::call_properties): Ditto.
>         (function_instance::reads_global_state_p): Ditto.
>         (function_instance::modifies_global_state_p): Ditto.
>         (function_instance::could_trap_p): Ditto.
>         (function_builder::function_builder): Ditto.
>         (function_builder::~function_builder): Ditto.
>         (function_builder::allocate_argument_types): Ditto.
>         (function_builder::register_function_group): Ditto.
>         (function_builder::append_name): Ditto.
>         (function_builder::finish_name): Ditto.
>         (function_builder::get_attributes): Ditto.
>         (function_builder::add_function): Ditto.
>         (function_builder::add_unique_function): Ditto.
>         (function_call_info::function_call_info): Ditto.
>         (function_expander::function_expander): Ditto.
>         (function_expander::add_input_operand): Ditto.
>         (function_expander::generate_insn): Ditto.
>         (registered_function_hasher::hash): Ditto.
>         (registered_function_hasher::equal): Ditto.
>         (builtin_decl): Ditto.
>         (expand_builtin): Ditto.
>         (gt_ggc_mx): Define for using GCC garbage collect.
>         (gt_pch_nx): Define for using GCC garbage collect.
>         * config/riscv/riscv-vector-builtins.def (DEF_RVV_OP_TYPE): New macro.
>         (DEF_RVV_PRED_TYPE): Ditto.
>         (vbool64_t): Add suffix.
>         (vbool32_t): Ditto.
>         (vbool16_t): Ditto.
>         (vbool8_t): Ditto.
>         (vbool4_t): Ditto.
>         (vbool2_t): Ditto.
>         (vbool1_t): Ditto.
>         (vint8mf8_t): Ditto.
>         (vuint8mf8_t): Ditto.
>         (vint8mf4_t): Ditto.
>         (vuint8mf4_t): Ditto.
>         (vint8mf2_t): Ditto.
>         (vuint8mf2_t): Ditto.
>         (vint8m1_t): Ditto.
>         (vuint8m1_t): Ditto.
>         (vint8m2_t): Ditto.
>         (vuint8m2_t): Ditto.
>         (vint8m4_t): Ditto.
>         (vuint8m4_t): Ditto.
>         (vint8m8_t): Ditto.
>         (vuint8m8_t): Ditto.
>         (vint16mf4_t): Ditto.
>         (vuint16mf4_t): Ditto.
>         (vint16mf2_t): Ditto.
>         (vuint16mf2_t): Ditto.
>         (vint16m1_t): Ditto.
>         (vuint16m1_t): Ditto.
>         (vint16m2_t): Ditto.
>         (vuint16m2_t): Ditto.
>         (vint16m4_t): Ditto.
>         (vuint16m4_t): Ditto.
>         (vint16m8_t): Ditto.
>         (vuint16m8_t): Ditto.
>         (vint32mf2_t): Ditto.
>         (vuint32mf2_t): Ditto.
>         (vint32m1_t): Ditto.
>         (vuint32m1_t): Ditto.
>         (vint32m2_t): Ditto.
>         (vuint32m2_t): Ditto.
>         (vint32m4_t): Ditto.
>         (vuint32m4_t): Ditto.
>         (vint32m8_t): Ditto.
>         (vuint32m8_t): Ditto.
>         (vint64m1_t): Ditto.
>         (vuint64m1_t): Ditto.
>         (vint64m2_t): Ditto.
>         (vuint64m2_t): Ditto.
>         (vint64m4_t): Ditto.
>         (vuint64m4_t): Ditto.
>         (vint64m8_t): Ditto.
>         (vuint64m8_t): Ditto.
>         (vfloat32mf2_t): Ditto.
>         (vfloat32m1_t): Ditto.
>         (vfloat32m2_t): Ditto.
>         (vfloat32m4_t): Ditto.
>         (vfloat32m8_t): Ditto.
>         (vfloat64m1_t): Ditto.
>         (vfloat64m2_t): Ditto.
>         (vfloat64m4_t): Ditto.
>         (vfloat64m8_t): Ditto.
>         (vv): Ditto.
>         (vx): Ditto.
>         (v): Ditto.
>         (wv): Ditto.
>         (wx): Ditto.
>         (x_x_v): Ditto.
>         (vf2): Ditto.
>         (vf4): Ditto.
>         (vf8): Ditto.
>         (vvm): Ditto.
>         (vxm): Ditto.
>         (x_x_w): Ditto.
>         (v_v): Ditto.
>         (v_x): Ditto.
>         (vs): Ditto.
>         (mm): Ditto.
>         (m): Ditto.
>         (vf): Ditto.
>         (vm): Ditto.
>         (wf): Ditto.
>         (vfm): Ditto.
>         (v_f): Ditto.
>         (ta): Ditto.
>         (tu): Ditto.
>         (ma): Ditto.
>         (mu): Ditto.
>         (tama): Ditto.
>         (tamu): Ditto.
>         (tuma): Ditto.
>         (tumu): Ditto.
>         (tam): Ditto.
>         (tum): Ditto.
>         * config/riscv/riscv-vector-builtins.h (GCC_RISCV_VECTOR_BUILTINS_H): New macro.
>         (RVV_REQUIRE_RV64BIT): Ditto.
>         (RVV_REQUIRE_ZVE64): Ditto.
>         (RVV_REQUIRE_ELEN_FP_32): Ditto.
>         (RVV_REQUIRE_ELEN_FP_64): Ditto.
>         (enum operand_type_index): New enum.
>         (DEF_RVV_OP_TYPE): New macro.
>         (enum predication_type_index): New enum.
>         (DEF_RVV_PRED_TYPE): New macro.
>         (enum rvv_base_type): New enum.
>         (struct rvv_builtin_suffixes): New struct.
>         (struct rvv_arg_type_info): Ditto.
>         (struct rvv_type_info): Ditto.
>         (struct rvv_op_info): Ditto.
>         (class registered_function): New class.
>         (class function_base): Ditto.
>         (class function_shape): Ditto.
>         (struct function_group_info): New struct.
>         (class GTY): New class.
>         (class function_builder): Ditto.
>         (class function_call_info): Ditto.
>         (function_call_info::function_returns_void_p): New function.
>         (class function_expander): New class.
>         (function_instance::operator!=): New function.
>         (function_expander::expand): Ditto.
>         (function_expander::add_input_operand): Ditto.
>         (function_base::call_properties): Ditto.
>
> ---
>  gcc/config.gcc                             |   2 +
>  gcc/config/riscv/riscv-builtins.cc         |  44 +-
>  gcc/config/riscv/riscv-protos.h            |  17 +
>  gcc/config/riscv/riscv-vector-builtins.cc  | 475 ++++++++++++++++++++-
>  gcc/config/riscv/riscv-vector-builtins.def | 245 ++++++++---
>  gcc/config/riscv/riscv-vector-builtins.h   | 363 ++++++++++++++++
>  6 files changed, 1065 insertions(+), 81 deletions(-)
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 8d5972fecf7..486e8790544 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -519,6 +519,8 @@ riscv*)
>         extra_objs="${extra_objs} riscv-vector-builtins.o"
>         d_target_objs="riscv-d.o"
>         extra_headers="riscv_vector.h"
> +       target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
> +       target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.h"
>         ;;
>  rs6000*-*-*)
>         extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
> diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
> index 14865d70955..9930340d32b 100644
> --- a/gcc/config/riscv/riscv-builtins.cc
> +++ b/gcc/config/riscv/riscv-builtins.cc
> @@ -223,7 +223,10 @@ riscv_init_builtins (void)
>         {
>           tree type = riscv_build_function_type (d->prototype);
>           riscv_builtin_decls[i]
> -           = add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL, NULL);
> +           = add_builtin_function (d->name, type,
> +                                   (i << RISCV_BUILTIN_SHIFT)
> +                                     + RISCV_BUILTIN_GENERAL,
> +                                   BUILT_IN_MD, NULL, NULL);
>           riscv_builtin_decl_index[d->icode] = i;
>         }
>      }
> @@ -234,9 +237,18 @@ riscv_init_builtins (void)
>  tree
>  riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
>  {
> -  if (code >= ARRAY_SIZE (riscv_builtins))
> -    return error_mark_node;
> -  return riscv_builtin_decls[code];
> +  unsigned int subcode = code >> RISCV_BUILTIN_SHIFT;
> +  switch (code & RISCV_BUILTIN_CLASS)
> +    {
> +    case RISCV_BUILTIN_GENERAL:
> +      if (subcode >= ARRAY_SIZE (riscv_builtins))
> +       return error_mark_node;
> +      return riscv_builtin_decls[subcode];
> +
> +    case RISCV_BUILTIN_VECTOR:
> +      return riscv_vector::builtin_decl (subcode, initialize_p);
> +    }
> +  return error_mark_node;
>  }
>
>  /* Take argument ARGNO from EXP's argument list and convert it into
> @@ -303,15 +315,23 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
>  {
>    tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
>    unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
> -  const struct riscv_builtin_description *d = &riscv_builtins[fcode];
> -
> -  switch (d->builtin_type)
> +  unsigned int subcode = fcode >> RISCV_BUILTIN_SHIFT;
> +  switch (fcode & RISCV_BUILTIN_CLASS)
>      {
> -    case RISCV_BUILTIN_DIRECT:
> -      return riscv_expand_builtin_direct (d->icode, target, exp, true);
> -
> -    case RISCV_BUILTIN_DIRECT_NO_TARGET:
> -      return riscv_expand_builtin_direct (d->icode, target, exp, false);
> +      case RISCV_BUILTIN_VECTOR:
> +        return riscv_vector::expand_builtin (subcode, exp, target);
> +      case RISCV_BUILTIN_GENERAL: {
> +       const struct riscv_builtin_description *d = &riscv_builtins[subcode];
> +
> +       switch (d->builtin_type)
> +         {
> +         case RISCV_BUILTIN_DIRECT:
> +           return riscv_expand_builtin_direct (d->icode, target, exp, true);
> +
> +         case RISCV_BUILTIN_DIRECT_NO_TARGET:
> +           return riscv_expand_builtin_direct (d->icode, target, exp, false);
> +         }
> +      }
>      }
>
>    gcc_unreachable ();
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index a44b34d1278..f8c9932ff89 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -124,6 +124,23 @@ extern const char *mangle_builtin_type (const_tree);
>  extern bool verify_type_context (location_t, type_context_kind, const_tree, bool);
>  #endif
>  extern void handle_pragma_vector (void);
> +extern tree builtin_decl (unsigned, bool);
> +extern rtx expand_builtin (unsigned int, tree, rtx);
>  }
>
> +/* We classify builtin types into two classes:
> +   1. General builtin class which is defined in riscv_builtins.
> +   2. Vector builtin class which is a special builtin architecture
> +      that implement intrinsic short into "pragma".  */
> +enum riscv_builtin_class
> +{
> +  RISCV_BUILTIN_GENERAL,
> +  RISCV_BUILTIN_VECTOR
> +};
> +
> +const unsigned int RISCV_BUILTIN_SHIFT = 1;
> +
> +/* Mask that selects the riscv_builtin_class part of a function code.  */
> +const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1;
> +
>  #endif /* ! GCC_RISCV_PROTOS_H */
> diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
> index 55d45651618..5c20788b3ab 100644
> --- a/gcc/config/riscv/riscv-vector-builtins.cc
> +++ b/gcc/config/riscv/riscv-vector-builtins.cc
> @@ -66,13 +66,55 @@ struct vector_type_info
>    const char *mangled_name;
>  };
>
> -/* Information about each RVV type.  */
> +/* Describes a function decl.  */
> +class GTY (()) registered_function
> +{
> +public:
> +  function_instance GTY ((skip)) instance;
> +
> +  /* The decl itself.  */
> +  tree GTY ((skip)) decl;
> +};
> +
> +/* Hash traits for registered_function.  */
> +struct registered_function_hasher : nofree_ptr_hash<registered_function>
> +{
> +  typedef function_instance compare_type;
> +
> +  static hashval_t hash (value_type);
> +  static bool equal (value_type, const compare_type &);
> +};
> +
> +/* Static information about each RVV type.  */
>  static CONSTEXPR const vector_type_info vector_types[] = {
>  #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, ARGS...)                          \
>    {#NAME, #ABI_NAME, "u" #NCHARS #ABI_NAME},
>  #include "riscv-vector-builtins.def"
>  };
>
> +/* Static information about operand suffix for each RVV type.  */
> +const char *const operand_suffixes[NUM_OP_TYPES] = {
> +  "", /* OP_TYPE_none.  */
> +#define DEF_RVV_OP_TYPE(NAME) "_" # NAME,
> +#include "riscv-vector-builtins.def"
> +};
> +
> +/* Static information about type suffix for each RVV type.  */
> +const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1] = {
> +#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE,         \
> +                    VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX,    \
> +                    VSETVL_SUFFIX)                                            \
> +  {#VECTOR_SUFFIX, #SCALAR_SUFFIX, #VSETVL_SUFFIX},
> +#include "riscv-vector-builtins.def"
> +};
> +
> +/* Static information about predication suffix for each RVV type.  */
> +const char *const predication_suffixes[NUM_PRED_TYPES] = {
> +  "", /* PRED_TYPE_none.  */
> +#define DEF_RVV_PRED_TYPE(NAME) "_" # NAME,
> +#include "riscv-vector-builtins.def"
> +};
> +
>  /* The RVV types, with their built-in
>     "__rvv..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
>     yields a null tree.  */
> @@ -82,6 +124,14 @@ static GTY (()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
>  extern GTY (()) rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
>  rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
>
> +/* The list of all registered function decls, indexed by code.  */
> +static GTY (()) vec<registered_function *, va_gc> *registered_functions;
> +
> +/* All registered function decls, hashed on the function_instance
> +   that they implement.  This is used for looking up implementations of
> +   overloaded functions.  */
> +static hash_table<registered_function_hasher> *function_table;
> +
>  /* RAII class for enabling enough RVV features to define the built-in
>     types and implement the riscv_vector.h pragma.
>
> @@ -118,6 +168,13 @@ rvv_switcher::~rvv_switcher ()
>           sizeof (have_regs_of_mode));
>  }
>
> +/* Add attribute NAME to ATTRS.  */
> +static tree
> +add_attribute (const char *name, tree attrs)
> +{
> +  return tree_cons (get_identifier (name), NULL_TREE, attrs);
> +}
> +
>  /* Add type attributes to builtin type tree, currently only the mangled name. */
>  static void
>  add_vector_type_attribute (tree type, const char *mangled_name)
> @@ -215,6 +272,7 @@ static void
>  register_vector_type (vector_type_index type)
>  {
>    tree vectype = abi_vector_types[type];
> +
>    /* When vectype is NULL, the corresponding builtin type
>       is disabled according to '-march'.  */
>    if (!vectype)
> @@ -237,6 +295,386 @@ register_vector_type (vector_type_index type)
>    builtin_types[type].vector_ptr = build_pointer_type (vectype);
>  }
>
> +/* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are
> +   enabled.  */
> +static bool
> +check_required_extensions (uint64_t required_extensions)
> +{
> +  uint64_t riscv_isa_flags = 0;
> +
> +  if (TARGET_VECTOR_ELEN_FP_32)
> +    riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32;
> +  if (TARGET_VECTOR_ELEN_FP_64)
> +    riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64;
> +  if (TARGET_MIN_VLEN > 32)
> +    riscv_isa_flags |= RVV_REQUIRE_ZVE64;
> +  if (TARGET_64BIT)
> +    riscv_isa_flags |= RVV_REQUIRE_RV64BIT;
> +
> +  uint64_t missing_extensions = required_extensions & ~riscv_isa_flags;
> +  if (missing_extensions != 0)
> +    return false;
> +  return true;
> +}
> +
> +tree
> +rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const
> +{
> +  switch (base_type)
> +    {
> +    case RVV_BASE_vector:
> +      return builtin_types[type_idx].vector;
> +    case RVV_BASE_scalar:
> +      return builtin_types[type_idx].scalar;
> +    case RVV_BASE_vector_ptr:
> +      return builtin_types[type_idx].vector_ptr;
> +    case RVV_BASE_scalar_ptr:
> +      return builtin_types[type_idx].scalar_ptr;
> +    case RVV_BASE_scalar_const_ptr:
> +      return builtin_types[type_idx].scalar_const_ptr;
> +    case RVV_BASE_void:
> +      return void_type_node;
> +    case RVV_BASE_size:
> +      return size_type_node;
> +    case RVV_BASE_ptrdiff:
> +      return ptrdiff_type_node;
> +    case RVV_BASE_unsigned_long:
> +      return long_unsigned_type_node;
> +    case RVV_BASE_long:
> +      return long_integer_type_node;
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
> +function_instance::function_instance (const char *base_name_in,
> +                                     const function_base *base_in,
> +                                     const function_shape *shape_in,
> +                                     rvv_type_info type_in,
> +                                     predication_type_index pred_in,
> +                                     const rvv_op_info *op_info_in)
> +  : base_name (base_name_in), base (base_in), shape (shape_in), type (type_in),
> +    pred (pred_in), op_info (op_info_in)
> +{
> +}
> +
> +bool
> +function_instance::operator== (const function_instance &other) const
> +{
> +  for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
> +    if (op_info->args[i].base_type != other.op_info->args[i].base_type)
> +      return false;
> +  return (base == other.base && shape == other.shape
> +         && type.index == other.type.index && op_info->op == other.op_info->op
> +         && pred == other.pred
> +         && op_info->ret.base_type == other.op_info->ret.base_type);
> +}
> +
> +bool
> +function_instance::any_type_float_p () const
> +{
> +  if (FLOAT_MODE_P (TYPE_MODE (get_return_type ())))
> +    return true;
> +
> +  for (int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
> +    if (FLOAT_MODE_P (TYPE_MODE (get_arg_type (i))))
> +      return true;
> +
> +  return false;
> +}
> +
> +tree
> +function_instance::get_return_type () const
> +{
> +  return op_info->ret.get_tree_type (type.index);
> +}
> +
> +tree
> +function_instance::get_arg_type (unsigned opno) const
> +{
> +  return op_info->args[opno].get_tree_type (type.index);
> +}
> +
> +/* Return a hash code for a function_instance.  */
> +hashval_t
> +function_instance::hash () const
> +{
> +  inchash::hash h;
> +  /* BASE uniquely determines BASE_NAME, so we don't need to hash both.  */
> +  h.add_ptr (base);
> +  h.add_ptr (shape);
> +  h.add_int (type.index);
> +  h.add_int (op_info->op);
> +  h.add_int (pred);
> +  h.add_int (op_info->ret.base_type);
> +  for (unsigned int i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
> +    h.add_int (op_info->args[i].base_type);
> +  return h.end ();
> +}
> +
> +/* Return a set of CP_* flags that describe what the function could do,
> +   taking the command-line flags into account.  */
> +unsigned int
> +function_instance::call_properties () const
> +{
> +  unsigned int flags = base->call_properties (*this);
> +
> +  /* -fno-trapping-math means that we can assume any FP exceptions
> +     are not user-visible.  */
> +  if (!flag_trapping_math)
> +    flags &= ~CP_RAISE_FP_EXCEPTIONS;
> +
> +  return flags;
> +}
> +
> +/* Return true if calls to the function could read some form of
> +   global state.  */
> +bool
> +function_instance::reads_global_state_p () const
> +{
> +  unsigned int flags = call_properties ();
> +
> +  /* Preserve any dependence on rounding mode, flush to zero mode, etc.
> +     There is currently no way of turning this off; in particular,
> +     -fno-rounding-math (which is the default) means that we should make
> +     the usual assumptions about rounding mode, which for intrinsics means
> +     acting as the instructions do.  */
> +  if (flags & CP_READ_FPCR)
> +    return true;
> +
> +  /* Handle direct reads of global state.  */
> +  return flags & (CP_READ_MEMORY | CP_READ_CSR);
> +}
> +
> +/* Return true if calls to the function could modify some form of
> +   global state.  */
> +bool
> +function_instance::modifies_global_state_p () const
> +{
> +  unsigned int flags = call_properties ();
> +
> +  /* Preserve any exception state written back to the FPCR,
> +     unless -fno-trapping-math says this is unnecessary.  */
> +  if (flags & CP_RAISE_FP_EXCEPTIONS)
> +    return true;
> +
> +  /* Handle direct modifications of global state.  */
> +  return flags & (CP_WRITE_MEMORY | CP_WRITE_CSR);
> +}
> +
> +/* Return true if calls to the function could raise a signal.  */
> +bool
> +function_instance::could_trap_p () const
> +{
> +  unsigned int flags = call_properties ();
> +
> +  /* Handle functions that could raise SIGFPE.  */
> +  if (flags & CP_RAISE_FP_EXCEPTIONS)
> +    return true;
> +
> +  /* Handle functions that could raise SIGBUS or SIGSEGV.  */
> +  if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
> +    return true;
> +
> +  return false;
> +}
> +
> +function_builder::function_builder ()
> +{
> +  m_direct_overloads = lang_GNU_CXX ();
> +  gcc_obstack_init (&m_string_obstack);
> +}
> +
> +function_builder::~function_builder ()
> +{
> +  obstack_free (&m_string_obstack, NULL);
> +}
> +
> +/* Allocate arguments of the function.  */
> +void
> +function_builder::allocate_argument_types (const function_instance &instance,
> +                                          vec<tree> &argument_types) const
> +{
> +  for (unsigned int i = 0;
> +       instance.op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
> +    argument_types.quick_push (
> +      instance.op_info->args[i].get_tree_type (instance.type.index));
> +}
> +
> +/* Register all the functions in GROUP.  */
> +void
> +function_builder::register_function_group (const function_group_info &group)
> +{
> +  (*group.shape)->build (*this, group);
> +}
> +
> +/* Add NAME to the end of the function name being built.  */
> +void
> +function_builder::append_name (const char *name)
> +{
> +  obstack_grow (&m_string_obstack, name, strlen (name));
> +}
> +
> +/* Zero-terminate and complete the function name being built.  */
> +char *
> +function_builder::finish_name ()
> +{
> +  obstack_1grow (&m_string_obstack, 0);
> +  return (char *) obstack_finish (&m_string_obstack);
> +}
> +
> +/* Return the appropriate function attributes for INSTANCE.  */
> +tree
> +function_builder::get_attributes (const function_instance &instance)
> +{
> +  tree attrs = NULL_TREE;
> +
> +  if (!instance.modifies_global_state_p ())
> +    {
> +      if (instance.reads_global_state_p ())
> +       attrs = add_attribute ("pure", attrs);
> +      else
> +       attrs = add_attribute ("const", attrs);
> +    }
> +
> +  if (!flag_non_call_exceptions || !instance.could_trap_p ())
> +    attrs = add_attribute ("nothrow", attrs);
> +
> +  return add_attribute ("leaf", attrs);
> +}
> +
> +/* Add a function called NAME with type FNTYPE and attributes ATTRS.
> +   INSTANCE describes what the function does.  */
> +registered_function &
> +function_builder::add_function (const function_instance &instance,
> +                               const char *name, tree fntype, tree attrs,
> +                               bool placeholder_p)
> +{
> +  unsigned int code = vec_safe_length (registered_functions);
> +  code = (code << RISCV_BUILTIN_SHIFT) + RISCV_BUILTIN_VECTOR;
> +
> +  /* We need to be able to generate placeholders to enusre that we have a
> +     consistent numbering scheme for function codes between the C and C++
> +     frontends, so that everything ties up in LTO.
> +
> +     Currently, tree-streamer-in.c:unpack_ts_function_decl_value_fields
> +     validates that tree nodes returned by TARGET_BUILTIN_DECL are non-NULL and
> +     some node other than error_mark_node. This is a holdover from when builtin
> +     decls were streamed by code rather than by value.
> +
> +     Ultimately, we should be able to remove this validation of BUILT_IN_MD
> +     nodes and remove the target hook. For now, however, we need to appease the
> +     validation and return a non-NULL, non-error_mark_node node, so we
> +     arbitrarily choose integer_zero_node.  */
> +  tree decl = placeholder_p
> +               ? integer_zero_node
> +               : simulate_builtin_function_decl (input_location, name, fntype,
> +                                                 code, NULL, attrs);
> +
> +  registered_function &rfn = *ggc_alloc<registered_function> ();
> +  rfn.instance = instance;
> +  rfn.decl = decl;
> +  vec_safe_push (registered_functions, &rfn);
> +
> +  return rfn;
> +}
> +
> +/* Add a built-in function for INSTANCE, with the argument types given
> +   by ARGUMENT_TYPES and the return type given by RETURN_TYPE. NAME is
> +   the "full" name for C function. OVERLOAD_NAME is the "short" name for
> +   C++ overloaded function. OVERLOAD_NAME can be nullptr because some
> +   instance doesn't have C++ overloaded function.  */
> +void
> +function_builder::add_unique_function (const function_instance &instance,
> +                                      const function_shape *shape,
> +                                      tree return_type,
> +                                      vec<tree> &argument_types)
> +{
> +  /* Do not add this function if it is invalid.  */
> +  if (!check_required_extensions (instance.type.required_extensions))
> +    return;
> +
> +  /* Add the function under its full (unique) name.  */
> +  char *name = shape->get_name (*this, instance, false);
> +  tree fntype
> +    = build_function_type_array (return_type, argument_types.length (),
> +                                argument_types.address ());
> +  tree attrs = get_attributes (instance);
> +  registered_function &rfn
> +    = add_function (instance, name, fntype, attrs, false);
> +
> +  /* Enter the function into the hash table.  */
> +  hashval_t hash = instance.hash ();
> +  registered_function **rfn_slot
> +    = function_table->find_slot_with_hash (instance, hash, INSERT);
> +  gcc_assert (!*rfn_slot);
> +  *rfn_slot = &rfn;
> +
> +  /* Also add the function under its overloaded alias, if we want
> +     a separate decl for each instance of an overloaded function.  */
> +  char *overload_name = shape->get_name (*this, instance, true);
> +  if (overload_name)
> +    {
> +      /* Attribute lists shouldn't be shared.  */
> +      tree attrs = get_attributes (instance);
> +      bool placeholder_p = !m_direct_overloads;
> +      add_function (instance, overload_name, fntype, attrs, placeholder_p);
> +    }
> +  obstack_free (&m_string_obstack, name);
> +}
> +
> +function_call_info::function_call_info (location_t location_in,
> +                                       const function_instance &instance_in,
> +                                       tree fndecl_in)
> +  : function_instance (instance_in), location (location_in), fndecl (fndecl_in)
> +{}
> +
> +function_expander::function_expander (const function_instance &instance,
> +                                     tree fndecl_in, tree exp_in,
> +                                     rtx target_in)
> +  : function_call_info (EXPR_LOCATION (exp_in), instance, fndecl_in),
> +    exp (exp_in), target (target_in), opno (0)
> +{
> +  if (!function_returns_void_p ())
> +    create_output_operand (&m_ops[opno++], target, TYPE_MODE (TREE_TYPE (exp)));
> +}
> +
> +/* Take argument ARGNO from EXP's argument list and convert it into
> +   an expand operand.  Store the operand in *M_OPS.  */
> +void
> +function_expander::add_input_operand (unsigned argno)
> +{
> +  tree arg = CALL_EXPR_ARG (exp, argno);
> +  rtx x = expand_normal (arg);
> +  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
> +}
> +
> +/* Generate instruction ICODE, given that its operands have already
> +   been added to M_OPS.  Return the value of the first operand.  */
> +rtx
> +function_expander::generate_insn (insn_code icode)
> +{
> +  gcc_assert (opno == insn_data[icode].n_generator_args);
> +  if (!maybe_expand_insn (icode, opno, m_ops))
> +    {
> +      error ("invalid argument to built-in function");
> +      return NULL_RTX;
> +    }
> +  return function_returns_void_p () ? const0_rtx : m_ops[0].value;
> +}
> +
> +inline hashval_t
> +registered_function_hasher::hash (value_type value)
> +{
> +  return value->instance.hash ();
> +}
> +
> +inline bool
> +registered_function_hasher::equal (value_type value, const compare_type &key)
> +{
> +  return value->instance == key;
> +}
> +
>  /* If TYPE is a built-in type defined by the RVV ABI, return the mangled name,
>     otherwise return NULL.  */
>  const char *
> @@ -356,4 +794,39 @@ handle_pragma_vector ()
>      register_vector_type ((enum vector_type_index) type_i);
>  }
>
> +/* Return the function decl with RVV function subcode CODE, or error_mark_node
> +   if no such function exists.  */
> +tree
> +builtin_decl (unsigned int code, bool)
> +{
> +  if (code >= vec_safe_length (registered_functions))
> +    return error_mark_node;
> +
> +  return (*registered_functions)[code]->decl;
> +}
> +
> +/* Expand a call to the RVV function with subcode CODE.  EXP is the call
> +   expression and TARGET is the preferred location for the result.
> +   Return the value of the lhs.  */
> +rtx
> +expand_builtin (unsigned int code, tree exp, rtx target)
> +{
> +  registered_function &rfn = *(*registered_functions)[code];
> +  return function_expander (rfn.instance, rfn.decl, exp, target).expand ();
> +}
> +
>  } // end namespace riscv_vector
> +
> +inline void
> +gt_ggc_mx (function_instance *)
> +{}
> +
> +inline void
> +gt_pch_nx (function_instance *)
> +{}
> +
> +inline void
> +gt_pch_nx (function_instance *, gt_pointer_operator, void *)
> +{}
> +
> +#include "gt-riscv-vector-builtins.h"
> diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def
> index 83603fedd57..b7a633ed376 100644
> --- a/gcc/config/riscv/riscv-vector-builtins.def
> +++ b/gcc/config/riscv/riscv-vector-builtins.def
> @@ -19,181 +19,290 @@ along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>
>  /* Use "DEF_RVV_TYPE" macro to define RVV datatype builtins.
> -   1.The 1 argument is the name exposed to users.
> +   1.The 'NAME' argument is the name exposed to users.
>       For example, "vint32m1_t".
> -   2.The 2 argument is the length of ABI-name.
> +   2.The 'NCHARS' argument is the length of ABI-name.
>       For example, length of "__rvv_int32m1_t" is 15.
> -   3.The 3 argument is the ABI-name. For example, "__rvv_int32m1_t".
> -   4.The 4 argument is associated scalar type which is used in
> +   3.The 'ABI_NAME' argument is the ABI-name. For example, "__rvv_int32m1_t".
> +   4.The 'SCALAR_TYPE' argument is associated scalar type which is used in
>       "build_vector_type_for_mode". For "vint32m1_t", we use "intSI_type_node" in
>       RV64. Otherwise, we use "long_integer_type_node".
> -   5.The 5 and 6 argument are the machine modes of corresponding RVV type used
> -     in "build_vector_type_for_mode". For "vint32m1_t", we use VNx2SImode when
> -     TARGET_MIN_VLEN > 32. Otherwise the machine mode is VNx1SImode.  */
> +   5.The 'VECTOR_MODE' is the machine modes of corresponding RVV type used
> +     in "build_vector_type_for_mode" when TARGET_MIN_VLEN > 32.
> +     For example: VECTOR_MODE = VNx2SI for "vint32m1_t".
> +   6.The 'VECTOR_MODE_MIN_VLEN_32' is the machine modes of corresponding RVV
> +     type used in "build_vector_type_for_mode" when TARGET_MIN_VLEN = 32. For
> +     example: VECTOR_MODE_MIN_VLEN_32 = VNx1SI for "vint32m1_t".
> +   7.The 'VECTOR_SUFFIX' define mode suffix for vector type.
> +     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vector = i32m1.
> +   8.The 'SCALAR_SUFFIX' define mode suffix for scalar type.
> +     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].scalar = i32.
> +   9.The 'VSETVL_SUFFIX' define mode suffix for vsetvli instruction.
> +     For example: type_suffixes[VECTOR_TYPE_vin32m1_t].vsetvl = e32m1.
> +*/
>
>  #ifndef DEF_RVV_TYPE
>  #define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE,         \
> -                    VECTOR_MODE_MIN_VLEN_32)
> +                    VECTOR_MODE_MIN_VLEN_32, VECTOR_SUFFIX, SCALAR_SUFFIX,    \
> +                    VSETVL_SUFFIX)
> +#endif
> +
> +/* Use "DEF_RVV_OP_TYPE" macro to define RVV operand types.
> +   The 'NAME' will be concatenated into intrinsic function name.  */
> +#ifndef DEF_RVV_OP_TYPE
> +#define DEF_RVV_OP_TYPE(NAME)
> +#endif
> +
> +/* Use "DEF_RVV_PRED_TYPE" macro to define RVV predication types.
> +   The 'NAME' will be concatenated into intrinsic function name.  */
> +#ifndef DEF_RVV_PRED_TYPE
> +#define DEF_RVV_PRED_TYPE(NAME)
>  #endif
>
>  /* SEW/LMUL = 64:
>     Only enable when TARGET_MIN_VLEN > 32 and machine mode = VNx1BImode.  */
> -DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID)
> +DEF_RVV_TYPE (vbool64_t, 14, __rvv_bool64_t, boolean, VNx1BI, VOID, _b64, , )
>  /* SEW/LMUL = 32:
>     Machine mode = VNx2BImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx1BImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI)
> +DEF_RVV_TYPE (vbool32_t, 14, __rvv_bool32_t, boolean, VNx2BI, VNx1BI, _b32, , )
>  /* SEW/LMUL = 16:
>     Machine mode = VNx2BImode when TARGET_MIN_VLEN = 32.
>     Machine mode = VNx4BImode when TARGET_MIN_VLEN > 32.  */
> -DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI)
> +DEF_RVV_TYPE (vbool16_t, 14, __rvv_bool16_t, boolean, VNx4BI, VNx2BI, _b16, , )
>  /* SEW/LMUL = 8:
>     Machine mode = VNx8BImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx4BImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI)
> +DEF_RVV_TYPE (vbool8_t, 13, __rvv_bool8_t, boolean, VNx8BI, VNx4BI, _b8, , )
>  /* SEW/LMUL = 4:
>     Machine mode = VNx16BImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx8BImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI)
> +DEF_RVV_TYPE (vbool4_t, 13, __rvv_bool4_t, boolean, VNx16BI, VNx8BI, _b4, , )
>  /* SEW/LMUL = 2:
>     Machine mode = VNx32BImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx16BImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI)
> +DEF_RVV_TYPE (vbool2_t, 13, __rvv_bool2_t, boolean, VNx32BI, VNx16BI, _b2, , )
>  /* SEW/LMUL = 1:
>     Machine mode = VNx64BImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx32BImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI)
> +DEF_RVV_TYPE (vbool1_t, 13, __rvv_bool1_t, boolean, VNx64BI, VNx32BI, _b1, , )
>
>  /* LMUL = 1/8:
>     Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1QImode.  */
> -DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID)
> -DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID)
> +DEF_RVV_TYPE (vint8mf8_t, 15, __rvv_int8mf8_t, intQI, VNx1QI, VOID, _i8mf8, _i8,
> +             _e8mf8)
> +DEF_RVV_TYPE (vuint8mf8_t, 16, __rvv_uint8mf8_t, unsigned_intQI, VNx1QI, VOID,
> +             _u8mf8, _u8, _e8mf8)
>  /* LMUL = 1/4:
>     Machine mode = VNx2QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx1QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI)
> -DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI)
> +DEF_RVV_TYPE (vint8mf4_t, 15, __rvv_int8mf4_t, intQI, VNx2QI, VNx1QI, _i8mf4,
> +             _i8, _e8mf4)
> +DEF_RVV_TYPE (vuint8mf4_t, 16, __rvv_uint8mf4_t, unsigned_intQI, VNx2QI, VNx1QI,
> +             _u8mf4, _u8, _e8mf4)
>  /* LMUL = 1/2:
>     Machine mode = VNx4QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx2QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI)
> -DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI)
> +DEF_RVV_TYPE (vint8mf2_t, 15, __rvv_int8mf2_t, intQI, VNx4QI, VNx2QI, _i8mf2,
> +             _i8, _e8mf2)
> +DEF_RVV_TYPE (vuint8mf2_t, 16, __rvv_uint8mf2_t, unsigned_intQI, VNx4QI, VNx2QI,
> +             _u8mf2, _u8, _e8mf2)
>  /* LMUL = 1:
>     Machine mode = VNx8QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx4QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI)
> -DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI)
> +DEF_RVV_TYPE (vint8m1_t, 14, __rvv_int8m1_t, intQI, VNx8QI, VNx4QI, _i8m1, _i8,
> +             _e8m1)
> +DEF_RVV_TYPE (vuint8m1_t, 15, __rvv_uint8m1_t, unsigned_intQI, VNx8QI, VNx4QI,
> +             _u8m1, _u8, _e8m1)
>  /* LMUL = 2:
>     Machine mode = VNx16QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx8QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI)
> -DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI)
> +DEF_RVV_TYPE (vint8m2_t, 14, __rvv_int8m2_t, intQI, VNx16QI, VNx8QI, _i8m2, _i8,
> +             _e8m2)
> +DEF_RVV_TYPE (vuint8m2_t, 15, __rvv_uint8m2_t, unsigned_intQI, VNx16QI, VNx8QI,
> +             _u8m2, _u8, _e8m2)
>  /* LMUL = 4:
>     Machine mode = VNx32QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx16QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI)
> -DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI)
> +DEF_RVV_TYPE (vint8m4_t, 14, __rvv_int8m4_t, intQI, VNx32QI, VNx16QI, _i8m4,
> +             _i8, _e8m4)
> +DEF_RVV_TYPE (vuint8m4_t, 15, __rvv_uint8m4_t, unsigned_intQI, VNx32QI, VNx16QI,
> +             _u8m4, _u8, _e8m4)
>  /* LMUL = 8:
>     Machine mode = VNx64QImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx32QImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI)
> -DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI)
> +DEF_RVV_TYPE (vint8m8_t, 14, __rvv_int8m8_t, intQI, VNx64QI, VNx32QI, _i8m8,
> +             _i8, _e8m8)
> +DEF_RVV_TYPE (vuint8m8_t, 15, __rvv_uint8m8_t, unsigned_intQI, VNx64QI, VNx32QI,
> +             _u8m8, _u8, _e8m8)
>
>  /* LMUL = 1/4:
>     Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1HImode.  */
> -DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID)
> -DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID)
> +DEF_RVV_TYPE (vint16mf4_t, 16, __rvv_int16mf4_t, intHI, VNx1HI, VOID, _i16mf4,
> +             _i16, _e16mf4)
> +DEF_RVV_TYPE (vuint16mf4_t, 17, __rvv_uint16mf4_t, unsigned_intHI, VNx1HI, VOID,
> +             _u16mf4, _u16, _e16mf4)
>  /* LMUL = 1/2:
>     Machine mode = VNx2HImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx1HImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI)
> +DEF_RVV_TYPE (vint16mf2_t, 16, __rvv_int16mf2_t, intHI, VNx2HI, VNx1HI, _i16mf2,
> +             _i16, _e16mf2)
>  DEF_RVV_TYPE (vuint16mf2_t, 17, __rvv_uint16mf2_t, unsigned_intHI, VNx2HI,
> -             VNx1HI)
> +             VNx1HI, _u16mf2, _u16, _e16mf2)
>  /* LMUL = 1:
>     Machine mode = VNx4HImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx2HImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI)
> -DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI)
> +DEF_RVV_TYPE (vint16m1_t, 15, __rvv_int16m1_t, intHI, VNx4HI, VNx2HI, _i16m1,
> +             _i16, _e16m1)
> +DEF_RVV_TYPE (vuint16m1_t, 16, __rvv_uint16m1_t, unsigned_intHI, VNx4HI, VNx2HI,
> +             _u16m1, _u16, _e16m1)
>  /* LMUL = 2:
>     Machine mode = VNx8HImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx4HImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI)
> -DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI)
> +DEF_RVV_TYPE (vint16m2_t, 15, __rvv_int16m2_t, intHI, VNx8HI, VNx4HI, _i16m2,
> +             _i16, _e16m2)
> +DEF_RVV_TYPE (vuint16m2_t, 16, __rvv_uint16m2_t, unsigned_intHI, VNx8HI, VNx4HI,
> +             _u16m2, _u16, _e16m2)
>  /* LMUL = 4:
>     Machine mode = VNx16HImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx8HImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI)
> +DEF_RVV_TYPE (vint16m4_t, 15, __rvv_int16m4_t, intHI, VNx16HI, VNx8HI, _i16m4,
> +             _i16, _e16m4)
>  DEF_RVV_TYPE (vuint16m4_t, 16, __rvv_uint16m4_t, unsigned_intHI, VNx16HI,
> -             VNx8HI)
> +             VNx8HI, _u16m4, _u16, _e16m4)
>  /* LMUL = 8:
>     Machine mode = VNx32HImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx16HImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI)
> +DEF_RVV_TYPE (vint16m8_t, 15, __rvv_int16m8_t, intHI, VNx32HI, VNx16HI, _i16m8,
> +             _i16, _e16m8)
>  DEF_RVV_TYPE (vuint16m8_t, 16, __rvv_uint16m8_t, unsigned_intHI, VNx32HI,
> -             VNx16HI)
> +             VNx16HI, _u16m8, _u16, _e16m8)
>
>  /* LMUL = 1/2:
>     Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SImode.  */
> -DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID)
> -DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID)
> +DEF_RVV_TYPE (vint32mf2_t, 16, __rvv_int32mf2_t, int32, VNx1SI, VOID, _i32mf2,
> +             _i32, _e32mf2)
> +DEF_RVV_TYPE (vuint32mf2_t, 17, __rvv_uint32mf2_t, unsigned_int32, VNx1SI, VOID,
> +             _u32mf2, _u32, _e32mf2)
>  /* LMUL = 1:
>     Machine mode = VNx2SImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx1SImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI)
> -DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI)
> +DEF_RVV_TYPE (vint32m1_t, 15, __rvv_int32m1_t, int32, VNx2SI, VNx1SI, _i32m1,
> +             _i32, _e32m1)
> +DEF_RVV_TYPE (vuint32m1_t, 16, __rvv_uint32m1_t, unsigned_int32, VNx2SI, VNx1SI,
> +             _u32m1, _u32, _e32m1)
>  /* LMUL = 2:
>     Machine mode = VNx4SImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx2SImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI)
> -DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI)
> +DEF_RVV_TYPE (vint32m2_t, 15, __rvv_int32m2_t, int32, VNx4SI, VNx2SI, _i32m2,
> +             _i32, _e32m2)
> +DEF_RVV_TYPE (vuint32m2_t, 16, __rvv_uint32m2_t, unsigned_int32, VNx4SI, VNx2SI,
> +             _u32m2, _u32, _e32m2)
>  /* LMUL = 4:
>     Machine mode = VNx8SImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx4SImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI)
> -DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI)
> +DEF_RVV_TYPE (vint32m4_t, 15, __rvv_int32m4_t, int32, VNx8SI, VNx4SI, _i32m4,
> +             _i32, _e32m4)
> +DEF_RVV_TYPE (vuint32m4_t, 16, __rvv_uint32m4_t, unsigned_int32, VNx8SI, VNx4SI,
> +             _u32m4, _u32, _e32m4)
>  /* LMUL = 8:
>     Machine mode = VNx16SImode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx8SImode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI)
> +DEF_RVV_TYPE (vint32m8_t, 15, __rvv_int32m8_t, int32, VNx16SI, VNx8SI, _i32m8,
> +             _i32, _e32m8)
>  DEF_RVV_TYPE (vuint32m8_t, 16, __rvv_uint32m8_t, unsigned_int32, VNx16SI,
> -             VNx8SI)
> +             VNx8SI, _u32m8, _u32, _e32m8)
>
>  /* SEW = 64:
>     Disable when TARGET_MIN_VLEN > 32.  */
> -DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID)
> -DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID)
> -DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID)
> -DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID)
> -DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID)
> -DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID)
> -DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID)
> -DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID)
> +DEF_RVV_TYPE (vint64m1_t, 15, __rvv_int64m1_t, intDI, VNx1DI, VOID, _i64m1,
> +             _i64, _e64m1)
> +DEF_RVV_TYPE (vuint64m1_t, 16, __rvv_uint64m1_t, unsigned_intDI, VNx1DI, VOID,
> +             _u64m1, _u64, _e64m1)
> +DEF_RVV_TYPE (vint64m2_t, 15, __rvv_int64m2_t, intDI, VNx2DI, VOID, _i64m2,
> +             _i64, _e64m2)
> +DEF_RVV_TYPE (vuint64m2_t, 16, __rvv_uint64m2_t, unsigned_intDI, VNx2DI, VOID,
> +             _u64m2, _u64, _e64m2)
> +DEF_RVV_TYPE (vint64m4_t, 15, __rvv_int64m4_t, intDI, VNx4DI, VOID, _i64m4,
> +             _i64, _e64m4)
> +DEF_RVV_TYPE (vuint64m4_t, 16, __rvv_uint64m4_t, unsigned_intDI, VNx4DI, VOID,
> +             _u64m4, _u64, _e64m4)
> +DEF_RVV_TYPE (vint64m8_t, 15, __rvv_int64m8_t, intDI, VNx8DI, VOID, _i64m8,
> +             _i64, _e64m8)
> +DEF_RVV_TYPE (vuint64m8_t, 16, __rvv_uint64m8_t, unsigned_intDI, VNx8DI, VOID,
> +             _u64m8, _u64, _e64m8)
>
>  /* LMUL = 1/2:
>     Only enble when TARGET_MIN_VLEN > 32 and machine mode = VNx1SFmode.  */
> -DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID)
> +DEF_RVV_TYPE (vfloat32mf2_t, 18, __rvv_float32mf2_t, float, VNx1SF, VOID,
> +             _f32mf2, _f32, _e32mf2)
>  /* LMUL = 1:
>     Machine mode = VNx2SFmode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx1SFmode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF)
> +DEF_RVV_TYPE (vfloat32m1_t, 17, __rvv_float32m1_t, float, VNx2SF, VNx1SF,
> +             _f32m1, _f32, _e32m1)
>  /* LMUL = 2:
>     Machine mode = VNx4SFmode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx2SFmode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF)
> +DEF_RVV_TYPE (vfloat32m2_t, 17, __rvv_float32m2_t, float, VNx4SF, VNx2SF,
> +             _f32m2, _f32, _e32m2)
>  /* LMUL = 4:
>     Machine mode = VNx8SFmode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx4SFmode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF)
> +DEF_RVV_TYPE (vfloat32m4_t, 17, __rvv_float32m4_t, float, VNx8SF, VNx4SF,
> +             _f32m4, _f32, _e32m4)
>  /* LMUL = 8:
>     Machine mode = VNx16SFmode when TARGET_MIN_VLEN > 32.
>     Machine mode = VNx8SFmode when TARGET_MIN_VLEN = 32.  */
> -DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF)
> +DEF_RVV_TYPE (vfloat32m8_t, 17, __rvv_float32m8_t, float, VNx16SF, VNx8SF,
> +             _f32m8, _f32, _e32m8)
>
>  /* SEW = 64:
>     Disable when TARGET_VECTOR_FP64.  */
> -DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID)
> -DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID)
> -DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID)
> -DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID)
> +DEF_RVV_TYPE (vfloat64m1_t, 17, __rvv_float64m1_t, double, VNx1DF, VOID, _f64m1,
> +             _f64, _e64m1)
> +DEF_RVV_TYPE (vfloat64m2_t, 17, __rvv_float64m2_t, double, VNx2DF, VOID, _f64m2,
> +             _f64, _e64m2)
> +DEF_RVV_TYPE (vfloat64m4_t, 17, __rvv_float64m4_t, double, VNx4DF, VOID, _f64m4,
> +             _f64, _e64m4)
> +DEF_RVV_TYPE (vfloat64m8_t, 17, __rvv_float64m8_t, double, VNx8DF, VOID, _f64m8,
> +             _f64, _e64m8)
> +
> +DEF_RVV_OP_TYPE (vv)
> +DEF_RVV_OP_TYPE (vx)
> +DEF_RVV_OP_TYPE (v)
> +DEF_RVV_OP_TYPE (wv)
> +DEF_RVV_OP_TYPE (wx)
> +DEF_RVV_OP_TYPE (x_x_v)
> +DEF_RVV_OP_TYPE (vf2)
> +DEF_RVV_OP_TYPE (vf4)
> +DEF_RVV_OP_TYPE (vf8)
> +DEF_RVV_OP_TYPE (vvm)
> +DEF_RVV_OP_TYPE (vxm)
> +DEF_RVV_OP_TYPE (x_x_w)
> +DEF_RVV_OP_TYPE (v_v)
> +DEF_RVV_OP_TYPE (v_x)
> +DEF_RVV_OP_TYPE (vs)
> +DEF_RVV_OP_TYPE (mm)
> +DEF_RVV_OP_TYPE (m)
> +DEF_RVV_OP_TYPE (vf)
> +DEF_RVV_OP_TYPE (vm)
> +DEF_RVV_OP_TYPE (wf)
> +DEF_RVV_OP_TYPE (vfm)
> +DEF_RVV_OP_TYPE (v_f)
> +
> +DEF_RVV_PRED_TYPE (ta)
> +DEF_RVV_PRED_TYPE (tu)
> +DEF_RVV_PRED_TYPE (ma)
> +DEF_RVV_PRED_TYPE (mu)
> +DEF_RVV_PRED_TYPE (tama)
> +DEF_RVV_PRED_TYPE (tamu)
> +DEF_RVV_PRED_TYPE (tuma)
> +DEF_RVV_PRED_TYPE (tumu)
> +DEF_RVV_PRED_TYPE (m)
> +DEF_RVV_PRED_TYPE (tam)
> +DEF_RVV_PRED_TYPE (tum)
>
> +#undef DEF_RVV_PRED_TYPE
> +#undef DEF_RVV_OP_TYPE
>  #undef DEF_RVV_TYPE
> diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
> index ea67da9905c..425da12326c 100644
> --- a/gcc/config/riscv/riscv-vector-builtins.h
> +++ b/gcc/config/riscv/riscv-vector-builtins.h
> @@ -21,8 +21,101 @@
>  #ifndef GCC_RISCV_VECTOR_BUILTINS_H
>  #define GCC_RISCV_VECTOR_BUILTINS_H
>
> +/* The full name of an RVV intrinsic function is the concatenation of:
> +
> +   - the base name ("vadd", etc.)
> +   - the operand suffix ("_vv", "_vx", etc.)
> +   - the type suffix ("_i32m1", "_i32mf2", etc.)
> +   - the predication suffix ("_tamu", "_tumu", etc.)
> +
> +   Each piece of information is individually useful, so we retain this
> +   classification throughout:
> +
> +   - function_base represents the base name.
> +
> +   - operand_type_index can be used as an index to get operand suffix.
> +
> +   - rvv_op_info can be used as an index to get argument suffix.
> +
> +   - predication_type_index can be used as an index to get predication suffix.
> +
> +   In addition to its unique full name, a function may have a shorter
> +   overloaded alias.  This alias removes pieces of the suffixes that
> +   can be inferred from the arguments, such as by shortening the mode
> +   suffix or dropping some of the type suffixes.  The base name and the
> +   predication suffix stay the same.
> +
> +   - The function_instance class describes contains all properties of each
> +     individual function. Such these information will be used by
> +     function_builder, function_base, function_shape, gimple_folder,
> +     function_expander, etc.
> +
> +   - The function_builder class provides several helper function to add an
> +     intrinsic function.
> +
> +   - The function_shape class describes how that instruction has been presented
> +     at the language level:
> +
> +      1. Determine the function name for C and C++ overload function which can
> +        be recognized by compiler at language level for each instruction
> +        according to members of function_instance (base name, operand suffix,
> +        type suffix, predication suffix, etc.).
> +
> +      2. Specify the arguments type and return type of each function to
> +        describe how that instruction has presented at language level.
> +
> +   - The function_base describes how the underlying instruction behaves.
> +
> +   The static list of functions uses function_group to describe a group
> +   of related functions.  The function_builder class is responsible for
> +   expanding this static description into a list of individual functions
> +   and registering the associated built-in functions.  function_instance
> +   describes one of these individual functions in terms of the properties
> +   described above.
> +
> +   The classes involved in compiling a function call are:
> +
> +   - function_resolver, which resolves an overloaded function call to a
> +     specific function_instance and its associated function decl.
> +
> +   - function_checker, which checks whether the values of the arguments
> +     conform to the RVV ISA specification.
> +
> +   - gimple_folder, which tries to fold a function call at the gimple level
> +
> +   - function_expander, which expands a function call into rtl instructions
> +
> +   function_resolver and function_checker operate at the language level
> +   and so are associated with the function_shape.  gimple_folder and
> +   function_expander are concerned with the behavior of the function
> +   and so are associated with the function_base.  */
> +
>  namespace riscv_vector {
>
> +/* Flags that describe what a function might do, in addition to reading
> +   its arguments and returning a result.  */
> +static const unsigned int CP_READ_FPCR = 1U << 0;
> +static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
> +static const unsigned int CP_READ_MEMORY = 1U << 2;
> +static const unsigned int CP_WRITE_MEMORY = 1U << 3;
> +static const unsigned int CP_READ_CSR = 1U << 4;
> +static const unsigned int CP_WRITE_CSR = 1U << 5;
> +
> +/* Bit values used to identify required extensions for RVV intrinsics.  */
> +#define RVV_REQUIRE_RV64BIT (1 << 0)   /* Require RV64.  */
> +#define RVV_REQUIRE_ZVE64 (1 << 1)     /* Require TARGET_MIN_VLEN > 32.  */
> +#define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32.  */
> +#define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64.  */
> +
> +/* Enumerates the RVV operand types.  */
> +enum operand_type_index
> +{
> +  OP_TYPE_none,
> +#define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
> +#include "riscv-vector-builtins.def"
> +  NUM_OP_TYPES
> +};
> +
>  /* Enumerates the RVV types, together called
>     "vector types" for brevity.  */
>  enum vector_type_index
> @@ -32,6 +125,31 @@ enum vector_type_index
>    NUM_VECTOR_TYPES
>  };
>
> +/* Enumerates the RVV governing predication types.  */
> +enum predication_type_index
> +{
> +  PRED_TYPE_none,
> +#define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
> +#include "riscv-vector-builtins.def"
> +  NUM_PRED_TYPES
> +};
> +
> +/* Enumerates the RVV base types.  */
> +enum rvv_base_type
> +{
> +  RVV_BASE_vector,
> +  RVV_BASE_scalar,
> +  RVV_BASE_vector_ptr,
> +  RVV_BASE_scalar_ptr,
> +  RVV_BASE_scalar_const_ptr,
> +  RVV_BASE_void,
> +  RVV_BASE_size,
> +  RVV_BASE_ptrdiff,
> +  RVV_BASE_unsigned_long,
> +  RVV_BASE_long,
> +  NUM_BASE_TYPES
> +};
> +
>  /* Builtin types that are used to register RVV intrinsics.  */
>  struct GTY (()) rvv_builtin_types_t
>  {
> @@ -42,6 +160,251 @@ struct GTY (()) rvv_builtin_types_t
>    tree scalar_const_ptr;
>  };
>
> +/* Builtin suffix that are used to register RVV intrinsics.  */
> +struct rvv_builtin_suffixes
> +{
> +  const char *vector;
> +  const char *scalar;
> +  const char *vsetvl;
> +};
> +
> +/* RVV Builtin argument information.  */
> +struct rvv_arg_type_info
> +{
> +  CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
> +    : base_type (base_type_in)
> +  {}
> +  enum rvv_base_type base_type;
> +
> +  tree get_tree_type (vector_type_index) const;
> +};
> +
> +/* Static information for each operand.  */
> +struct rvv_type_info
> +{
> +  enum vector_type_index index;
> +  uint64_t required_extensions;
> +};
> +
> +/* RVV Builtin operands information.  */
> +struct rvv_op_info
> +{
> +  const rvv_type_info *types;
> +  const operand_type_index op;
> +  rvv_arg_type_info ret;
> +  const rvv_arg_type_info *args;
> +};
> +
> +class registered_function;
> +class function_base;
> +class function_shape;
> +
> +/* Static information about a set of functions.  */
> +struct function_group_info
> +{
> +  /* The base name, as a string.  */
> +  const char *base_name;
> +
> +  /* Describes the behavior associated with the function base name.  */
> +  const function_base *const *base;
> +
> +  /* The shape of the functions, as described above the class definition.
> +     It's possible to have entries with the same base name but different
> +     shapes.  */
> +  const function_shape *const *shape;
> +
> +  /* A list of the available operand types, predication types,
> +     and of the available operand datatype.
> +     The function supports every combination of the two.
> +     The list of predication is terminated by two NUM_PRED_TYPES,
> +     while the list of operand info is terminated by NUM_BASE_TYPES.
> +     The list of these type suffix is lexicographically ordered based
> +     on the index value.  */
> +  const predication_type_index *preds;
> +  const rvv_op_info ops_infos;
> +};
> +
> +class GTY ((user)) function_instance
> +{
> +public:
> +  function_instance (const char *, const function_base *,
> +                    const function_shape *, rvv_type_info,
> +                    predication_type_index, const rvv_op_info *);
> +
> +  bool operator== (const function_instance &) const;
> +  bool operator!= (const function_instance &) const;
> +  hashval_t hash () const;
> +
> +  unsigned int call_properties () const;
> +  bool reads_global_state_p () const;
> +  bool modifies_global_state_p () const;
> +  bool could_trap_p () const;
> +
> +  /* Return true if return type or arguments are floating point type.  */
> +  bool any_type_float_p () const;
> +
> +  tree get_return_type () const;
> +  tree get_arg_type (unsigned opno) const;
> +
> +  /* The properties of the function.  (The explicit "enum"s are required
> +     for gengtype.)  */
> +  const char *base_name;
> +  const function_base *base;
> +  const function_shape *shape;
> +  rvv_type_info type;
> +  enum predication_type_index pred;
> +  const rvv_op_info *op_info;
> +};
> +
> +/* A class for building and registering function decls.  */
> +class function_builder
> +{
> +public:
> +  function_builder ();
> +  ~function_builder ();
> +
> +  void allocate_argument_types (const function_instance &, vec<tree> &) const;
> +  void add_unique_function (const function_instance &, const function_shape *,
> +                           tree, vec<tree> &);
> +  void register_function_group (const function_group_info &);
> +  void append_name (const char *);
> +  char *finish_name ();
> +
> +private:
> +  tree get_attributes (const function_instance &);
> +
> +  registered_function &add_function (const function_instance &, const char *,
> +                                    tree, tree, bool);
> +
> +  /* True if we should create a separate decl for each instance of an
> +     overloaded function, instead of using function_builder.  */
> +  bool m_direct_overloads;
> +
> +  /* Used for building up function names.  */
> +  obstack m_string_obstack;
> +};
> +
> +/* A base class for handling calls to built-in functions.  */
> +class function_call_info : public function_instance
> +{
> +public:
> +  function_call_info (location_t, const function_instance &, tree);
> +
> +  bool function_returns_void_p ();
> +
> +  /* The location of the call.  */
> +  location_t location;
> +
> +  /* The FUNCTION_DECL that is being called.  */
> +  tree fndecl;
> +};
> +
> +/* Return true if the function has no return value.  */
> +inline bool
> +function_call_info::function_returns_void_p ()
> +{
> +  return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
> +}
> +
> +/* A class for expanding a function call into RTL.  */
> +class function_expander : public function_call_info
> +{
> +public:
> +  function_expander (const function_instance &, tree, tree, rtx);
> +  rtx expand ();
> +
> +  void add_input_operand (machine_mode, rtx);
> +  void add_input_operand (unsigned argno);
> +  rtx generate_insn (insn_code);
> +
> +  /* The function call expression.  */
> +  tree exp;
> +
> +  /* For functions that return a value, this is the preferred location
> +     of that value.  It could be null or could have a different mode
> +     from the function return type.  */
> +  rtx target;
> +
> +  /* The number of the operands.  */
> +  int opno;
> +
> +private:
> +  /* Used to build up the operands to an instruction.  */
> +  struct expand_operand m_ops[MAX_RECOG_OPERANDS];
> +};
> +
> +/* Provides information about a particular function base name, and handles
> +   tasks related to the base name.  */
> +class function_base
> +{
> +public:
> +  /* Return a set of CP_* flags that describe what the function might do,
> +     in addition to reading its arguments and returning a result.  */
> +  virtual unsigned int call_properties (const function_instance &) const;
> +
> +  /* Expand the given call into rtl.  Return the result of the function,
> +     or an arbitrary value if the function doesn't return a result.  */
> +  virtual rtx expand (function_expander &) const = 0;
> +};
> +
> +/* Classifies functions into "shapes" base on:
> +
> +   - Base name of the intrinsic function.
> +
> +   - Operand types list.
> +
> +   - Argument type list.
> +
> +   - Predication type list.  */
> +class function_shape
> +{
> +public:
> +  /* Shape the function name according to function_instance.  */
> +  virtual char *get_name (function_builder &, const function_instance &,
> +                         bool) const
> +    = 0;
> +
> +  /* Define all functions associated with the given group.  */
> +  virtual void build (function_builder &, const function_group_info &) const
> +    = 0;
> +};
> +
> +extern const char *const operand_suffixes[NUM_OP_TYPES];
> +extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
> +extern const char *const predication_suffixes[NUM_PRED_TYPES];
> +extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
> +
> +inline bool
> +function_instance::operator!= (const function_instance &other) const
> +{
> +  return !operator== (other);
> +}
> +
> +/* Expand the call and return its lhs.  */
> +inline rtx
> +function_expander::expand ()
> +{
> +  return base->expand (*this);
> +}
> +
> +/* Create op and add it into M_OPS and increase OPNO.  */
> +inline void
> +function_expander::add_input_operand (machine_mode mode, rtx op)
> +{
> +  create_input_operand (&m_ops[opno++], op, mode);
> +}
> +
> +/* Default implementation of function_base::call_properties, with conservatively
> +   correct behavior for floating-point instructions.  */
> +inline unsigned int
> +function_base::call_properties (const function_instance &instance) const
> +{
> +  unsigned int flags = 0;
> +  if (instance.any_type_float_p ())
> +    return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
> +  return flags;
> +}
> +
>  } // end namespace riscv_vector
>
>  #endif
> --
> 2.36.1
>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-10-21  4:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-17  8:20 [PATCH] RISC-V: Add RVV intrinsic basic framework juzhe.zhong
2022-10-21  4:23 ` Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).