[02/21] Add RVV intrinsic framework

Message ID 20220531085012.269719-3-juzhe.zhong@rivai.ai
State Committed
Headers
Series *** Add RVV (RISC-V 'V' Extension) support *** |

Commit Message

juzhe.zhong@rivai.ai May 31, 2022, 8:49 a.m. UTC
  From: zhongjuzhe <juzhe.zhong@rivai.ai>

gcc/ChangeLog:

        * config.gcc: Add riscv-vector-builtins-functions.o and riscv-vector-builtins.o extra_objs for RVV support.
        * config/riscv/riscv-builtins.cc (riscv_init_builtins): Add RVV support.
        (riscv_builtin_decl): Add RVV support.
        (riscv_expand_builtin): Add RVV support.
        (riscv_gimple_fold_builtin): New function.
        * config/riscv/riscv-protos.h (riscv_gimple_fold_builtin): New function.
        (enum riscv_builtin_class): New macro define.
        * config/riscv/riscv-vector.cc (rvv_get_mask_mode): New function.
        * config/riscv/riscv-vector.h (rvv_get_mask_mode): New function.
        * config/riscv/riscv.cc (riscv_class_max_nregs): Add RVV register.
        (riscv_conditional_register_usage): Add RVV register.
        (TARGET_GIMPLE_FOLD_BUILTIN): New targethook.
        * config/riscv/t-riscv: New object.
        * config/riscv/md-parser: New file.
        * config/riscv/riscv-vector-builtins-functions.cc: New file.
        * config/riscv/riscv-vector-builtins-functions.def: New file.
        * config/riscv/riscv-vector-builtins-functions.h: New file.
        * config/riscv/riscv-vector-builtins-iterators.def: New file.
        * config/riscv/riscv-vector-builtins.cc: New file.
        * config/riscv/riscv-vector-builtins.def: New file.
        * config/riscv/riscv-vector-builtins.h: New file.
        * config/riscv/vector-iterators.md: New file.
        
---
 gcc/config.gcc                                |    5 +-
 gcc/config/riscv/md-parser                    |  205 ++++
 gcc/config/riscv/riscv-builtins.cc            |   88 +-
 gcc/config/riscv/riscv-protos.h               |   19 +
 .../riscv/riscv-vector-builtins-functions.cc  | 1012 +++++++++++++++++
 .../riscv/riscv-vector-builtins-functions.def |   34 +
 .../riscv/riscv-vector-builtins-functions.h   |  491 ++++++++
 .../riscv/riscv-vector-builtins-iterators.def |   12 +
 gcc/config/riscv/riscv-vector-builtins.cc     |  266 +++++
 gcc/config/riscv/riscv-vector-builtins.def    |   37 +
 gcc/config/riscv/riscv-vector-builtins.h      |   59 +
 gcc/config/riscv/riscv-vector.cc              |   17 +
 gcc/config/riscv/riscv-vector.h               |    1 +
 gcc/config/riscv/riscv.cc                     |   21 +
 gcc/config/riscv/t-riscv                      |   36 +
 gcc/config/riscv/vector-iterators.md          |   19 +
 16 files changed, 2307 insertions(+), 15 deletions(-)
 create mode 100644 gcc/config/riscv/md-parser
 create mode 100644 gcc/config/riscv/riscv-vector-builtins-functions.cc
 create mode 100644 gcc/config/riscv/riscv-vector-builtins-functions.def
 create mode 100644 gcc/config/riscv/riscv-vector-builtins-functions.h
 create mode 100644 gcc/config/riscv/riscv-vector-builtins-iterators.def
 create mode 100644 gcc/config/riscv/riscv-vector-builtins.cc
 create mode 100644 gcc/config/riscv/riscv-vector-builtins.def
 create mode 100644 gcc/config/riscv/riscv-vector-builtins.h
 create mode 100644 gcc/config/riscv/vector-iterators.md
  

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 50154c2eb3a..bdda82ae576 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -517,8 +517,11 @@  pru-*-*)
 	;;
 riscv*)
 	cpu_type=riscv
-	extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-vector.o"
+	extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-vector.o riscv-vector-builtins-functions.o riscv-vector-builtins.o"
 	d_target_objs="riscv-d.o"
+	target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-builtins.cc \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
+	target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins-functions.cc"
+	target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins-functions.h"
 	;;
 rs6000*-*-*)
 	extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
diff --git a/gcc/config/riscv/md-parser b/gcc/config/riscv/md-parser
new file mode 100644
index 00000000000..311b8709c0a
--- /dev/null
+++ b/gcc/config/riscv/md-parser
@@ -0,0 +1,205 @@ 
+# Mode iterators and attributes parser for RISC-V 'V' Extension for GNU compiler.
+# Copyright (C) 2022-2022 Free Software Foundation, Inc.
+# Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+# 
+# This file is part of GCC.
+# 
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+
+
+def print_err(msg):
+    print("\033[31m\033[1mRISCV md parser Error: %s\033[0m\033[0m" % msg)
+
+
+def write_to_file(file_path, one_line, opt='a+'):
+    dir_name = os.path.dirname(file_path)
+    if dir_name is not None and len(dir_name) > 0:
+        os.makedirs(dir_name, exist_ok=True)
+    with open(file_path, opt, encoding="utf-8") as f:
+        f.write(one_line)
+
+
+def get_prologue():
+    return """/* Do not modify this file, it auto gen by md-parser script */
+#ifndef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+#define DEF_RISCV_ARG_MODE_ATTR_VARIABLE(A, B)
+#endif
+
+#ifndef DEF_RISCV_ARG_MODE_ATTR
+#define DEF_RISCV_ARG_MODE_ATTR(A, B, C, D, E)
+#endif
+
+"""
+
+
+def get_epilogue():
+    return """
+#undef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+#undef DEF_RISCV_ARG_MODE_ATTR
+"""
+
+
+def gen_mode_attr(def_seg):
+    result_str = ""
+    element_cnt = 0
+    for value_seg in def_seg.value_segment_list:
+        splitted_value_seg_string = value_seg.string.split()
+        if len(splitted_value_seg_string) == 2:
+            # we only want the def_seg for intrinsics function code which has the "mode" as right hand side value
+            attr = splitted_value_seg_string[1]
+            if not attr.isdigit() and (attr.upper().replace('X', 'x') == attr) and not attr.startswith ("0x"):
+                result_str += "DEF_RISCV_ARG_MODE_ATTR(%s, %d, %s, %s, %s)\n" % (
+                    def_seg.name, element_cnt, splitted_value_seg_string[0], attr, "TARGET_FP16" if attr.count("HF") > 0 else "TARGET_HARD_FLOAT" if attr.count("SF") > 0 else "TARGET_DOUBLE_FLOAT" if attr.count("DF") > 0 else "TARGET_ANY")
+                element_cnt += 1
+            else:
+                # if the mode_attr is not a totally attribute with the "mode" value, ignore the whole pack
+                return ""
+        else:
+            print_err("Value Segment(%s) in \"%s\" maybe not right for \"%s\"" % (
+                value_seg.string, def_seg.name, def_seg.def_type))
+    if len(result_str) > 0:
+        result_str = "DEF_RISCV_ARG_MODE_ATTR_VARIABLE(%s, %d)\n%s" % (def_seg.name, element_cnt, result_str)
+    return result_str
+
+
+def gen_mode_iterator(def_seg):
+    result_str = ""
+    element_cnt = 0
+    for value_seg in def_seg.value_segment_list:
+        splitted_value_seg_string = value_seg.string.split()
+        if len(splitted_value_seg_string) == 1:
+            result_str += "DEF_RISCV_ARG_MODE_ATTR(%s, %d, %s, %s, TARGET_ANY)\n" % (
+                def_seg.name, element_cnt, value_seg.string, value_seg.string)
+            element_cnt += 1
+        elif len(splitted_value_seg_string) == 2:
+            result_str += "DEF_RISCV_ARG_MODE_ATTR(%s, %d, %s, %s, %s)\n" % (
+                def_seg.name, element_cnt, splitted_value_seg_string[0], splitted_value_seg_string[0],
+                splitted_value_seg_string[1])
+            element_cnt += 1
+        else:
+            print_err("Value Segment(%s) in \"%s\" maybe not right for \"%s\"" % (
+                value_seg.string, def_seg.name, def_seg.def_type))
+    if len(result_str) > 0:
+        result_str = "DEF_RISCV_ARG_MODE_ATTR_VARIABLE(%s, %d)\n%s" % (def_seg.name, element_cnt, result_str)
+    return result_str
+
+
+class Segment:
+    def __init__(self):
+        self.string = ""
+        self.parentheses = 0
+
+    def append(self, char_value):
+        self.string += char_value
+        self.parentheses += 1 if char_value == '(' else -1 if char_value == ')' else 0
+
+    def is_intact(self):
+        return self.parentheses == 0
+
+    def strip_self(self):
+        self.string = self.string.replace('(', '').replace(')', '').replace('"', ' ')
+        self.string = self.string.strip()
+        return self
+
+    def __str__(self):
+        return self.string
+
+
+class DefSegment(Segment):
+    def __init__(self):
+        super().__init__()
+        self.def_type = ""
+        self.name = ""
+        self.value_str = ""
+        self.value_segment_list = []
+
+    def make_value_segments(self):
+        # split value string into multiple value segments which will contain a single or a double value array
+        i = 0
+        current_value_segment = None
+        while i < len(self.value_str):
+            if self.value_str[i] != ' ' and current_value_segment is None:
+                # new segment start
+                current_value_segment = Segment()
+                current_value_segment.append(self.value_str[i])
+            elif current_value_segment is not None:
+                current_value_segment.append(self.value_str[i])
+                if current_value_segment.is_intact() and (
+                        current_value_segment.string.endswith(' ') or current_value_segment.string.endswith(')')):
+                    self.value_segment_list.append(current_value_segment.strip_self())
+                    current_value_segment = None
+            i += 1
+        # append the last segment which is missed by the while loop
+        if current_value_segment is not None:
+            self.value_segment_list.append(current_value_segment.strip_self())
+
+    def parse(self):
+        if len(self.string) == 0:
+            return False
+        if self.string.count('[') != 1 or self.string.count(']') != 1:
+            print_err("\"%s\" is not a valid [...] format string" % self.string)
+            return False
+        # ignore the '(' and ')'
+        self.string = self.string[1:len(self.string) - 1]
+        self.def_type = self.string.split()[0]
+        self.name = self.string.split()[1]
+        # get the value string inside '[' and ']'
+        self.value_str = self.string[self.string.index('[') + 1:self.string.index(']')].strip()
+        self.make_value_segments()
+        return True
+
+
+if __name__ == '__main__':
+    local_dir = os.path.dirname(os.path.realpath(__file__))
+    output_file = local_dir + '/' + sys.argv[1]
+    target_md_files = []
+    for arg in sys.argv[2:]:
+        target_md_files.append(local_dir + '/' + arg)
+    segment_list = []
+    for md_file in target_md_files:
+        with open(md_file) as file:
+            current_segment = None
+            for line in file.readlines():
+                stripped_line = line.strip()
+                if stripped_line.startswith(";;"):
+                    continue
+                if stripped_line.count("(") > 0 or current_segment is not None:
+                    char_index = 0
+                    # add a space at the end of the stripped_line for further split
+                    stripped_line += " "
+                    while char_index < len(stripped_line):
+                        if stripped_line[char_index] == '(' and current_segment is None:
+                            # new segment start
+                            current_segment = DefSegment()
+                            current_segment.append('(')
+                        elif current_segment is not None:
+                            current_segment.append(stripped_line[char_index])
+                            if current_segment.is_intact():
+                                segment_list.append(current_segment)
+                                current_segment = None
+                        char_index += 1
+    output_str = get_prologue()
+    for segment in segment_list:
+        if not segment.parse():
+            continue
+        if segment.def_type == "define_mode_iterator":
+            output_str += gen_mode_iterator(segment)
+        elif segment.def_type == "define_mode_attr":
+            output_str += gen_mode_attr(segment)
+    output_str += get_epilogue()
+    write_to_file(output_file, output_str, opt='w')
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 795132a0c16..9bd2f1227a8 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -36,6 +36,13 @@  along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "expr.h"
 #include "langhooks.h"
+#include "backend.h"
+#include "gimple.h"
+#include "stringpool.h"
+#include "explow.h"
+#include "gimple-iterator.h"
+#include "riscv-protos.h"
+#include "riscv-vector-builtins.h"
 
 /* Macros to create an enumeration identifier for a function prototype.  */
 #define RISCV_FTYPE_NAME0(A) RISCV_##A##_FTYPE
@@ -189,6 +196,7 @@  riscv_build_function_type (enum riscv_function_type type)
 void
 riscv_init_builtins (void)
 {
+  riscv_vector::init_builtins ();
   for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++)
     {
       const struct riscv_builtin_description *d = &riscv_builtins[i];
@@ -196,7 +204,8 @@  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;
 	}
     }
@@ -205,11 +214,20 @@  riscv_init_builtins (void)
 /* Implement TARGET_BUILTIN_DECL.  */
 
 tree
-riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
+riscv_builtin_decl (unsigned int code, bool initialize_p)
 {
-  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
@@ -271,20 +289,29 @@  riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
 
 rtx
 riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
-		      machine_mode mode ATTRIBUTE_UNUSED,
-		      int ignore ATTRIBUTE_UNUSED)
+                      machine_mode mode ATTRIBUTE_UNUSED,
+                      int ignore 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_VECTOR:
+      return riscv_vector::expand_builtin (subcode, exp, target);
+    case RISCV_BUILTIN_GENERAL:
+      {
+        const struct riscv_builtin_description *d = &riscv_builtins[subcode];
 
-    case RISCV_BUILTIN_DIRECT_NO_TARGET:
-      return riscv_expand_builtin_direct (d->icode, target, exp, false);
+        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 ();
@@ -307,3 +334,36 @@  riscv_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
   *clear = build_call_expr (fsflags, 1, old_flags);
   *update = NULL_TREE;
 }
+
+/* Implement TARGET_GIMPLE_FOLD_BUILTIN.  */
+
+bool
+riscv_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+
+  gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+  tree fndecl = gimple_call_fndecl (stmt);
+  unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
+  unsigned int subcode = code >> RISCV_BUILTIN_SHIFT;
+  gimple *new_stmt = NULL;
+  switch (code & RISCV_BUILTIN_CLASS)
+    {
+    /* Gernal builtin can fold gimple if necessary,
+       may wrapp it into a function in the future.  */
+    case RISCV_BUILTIN_GENERAL:
+      return false;
+
+    case RISCV_BUILTIN_VECTOR:
+      new_stmt = riscv_vector::gimple_fold_builtin (subcode, gsi, stmt);
+      break;
+    }
+
+  if (!new_stmt)
+    return false;
+
+  gsi_replace (gsi, new_stmt, true);
+
+  return true;
+}
+
+#include "gt-riscv-builtins.h"
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 19c50f0e702..1cb3586d1f1 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -87,6 +87,7 @@  extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *);
 extern rtx riscv_expand_builtin (tree, rtx, rtx, machine_mode, int);
 extern tree riscv_builtin_decl (unsigned int, bool);
 extern void riscv_init_builtins (void);
+extern bool riscv_gimple_fold_builtin (gimple_stmt_iterator *);
 
 /* Routines implemented in riscv-common.cc.  */
 extern std::string riscv_arch_str (bool version_p = true);
@@ -116,4 +117,22 @@  extern unsigned int rvv_offset_temporaries (bool, poly_int64);
 extern enum vlmul_field_enum riscv_classify_vlmul_field (machine_mode);
 extern int rvv_regsize (machine_mode);
 
+/* We classify builtin types into two classes:
+   1. General builtin class which is using the
+      original builtin architecture built in
+      RISCV.
+   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 vector_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-functions.cc b/gcc/config/riscv/riscv-vector-builtins-functions.cc
new file mode 100644
index 00000000000..19bcb66a83f
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.cc
@@ -0,0 +1,1012 @@ 
+/* Intrinsic implementation for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#define IN_TARGET_CODE 1
+
+#include "riscv-vector-builtins-functions.h"
+namespace riscv_vector
+{
+
+extern hash_table<registered_function_hasher> *function_table;
+extern GTY (()) tree
+    vector_types[MAX_TUPLE_NUM][NUM_VECTOR_TYPES + 1][MAX_VLMUL_FIELD];
+extern GTY (()) tree
+    vector_pointer_types[NUM_VECTOR_TYPES + 1][MAX_VLMUL_FIELD];
+extern GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+extern GTY(()) tree scalar_pointer_types[NUM_VECTOR_TYPES];
+extern GTY(()) tree const_scalar_pointer_types[NUM_VECTOR_TYPES];
+
+extern GTY (()) vec<registered_function *, va_gc> *registered_functions;
+
+/* 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_RAISE_LD_EXCEPTIONS = 1U << 2;
+static const unsigned int CP_READ_MEMORY = 1U << 3;
+static const unsigned int CP_WRITE_MEMORY = 1U << 4;
+static const unsigned int CP_READ_CSR = 1U << 5;
+static const unsigned int CP_WRITE_CSR = 1U << 6;
+
+/* True if we've already complained about attempts to use functions
+   when the required extension is disabled.  */
+static bool reported_missing_extension_p;
+
+static tree
+mode2mask_t (machine_mode mode)
+{
+  int factor = exact_div (GET_MODE_NUNITS (mode), GET_MODE_NUNITS (VNx2BImode))
+                   .to_constant ();
+  factor = exact_log2 (factor);
+  return vector_types[0][VECTOR_TYPE_bool][factor];
+}
+
+static enum vector_type_index
+get_type_idx (machine_mode mode, bool u)
+{
+  #define RVV_INT_TYPE(MODE, TYPE, SEW) \
+    case MODE: \
+      return u ? VECTOR_TYPE_u##TYPE##SEW : VECTOR_TYPE_##TYPE##SEW; \
+      break;
+  #define RVV_FLOAT_TYPE(MODE, TYPE, SEW) \
+    case MODE: \
+      return VECTOR_TYPE_##TYPE##SEW; \
+      break;
+  
+  switch (mode)
+    {
+    case BImode:
+      return VECTOR_TYPE_bool;
+    RVV_INT_TYPE (QImode, int, 8)
+    RVV_INT_TYPE (HImode, int, 16)
+    RVV_INT_TYPE (SImode, int, 32)
+    RVV_INT_TYPE (DImode, int, 64)
+    RVV_FLOAT_TYPE (SFmode, float, 32)
+    RVV_FLOAT_TYPE (DFmode, float, 64)
+    default:
+      gcc_unreachable ();
+    }
+  
+  return (enum vector_type_index) 0;
+}
+
+static int
+get_lmul_idx (machine_mode mode)
+{
+  machine_mode innermode = GET_MODE_INNER (mode);
+  bool is_bool_p = GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL ? true : false;
+  machine_mode base_mode = is_bool_p ? VNx2QImode : VNx2BImode;
+  int offset = exact_div (GET_MODE_NUNITS (mode), GET_MODE_NUNITS (base_mode))
+                   .to_constant ();
+  if (is_bool_p)
+    return exact_log2 (offset);
+  else
+    {
+      int nf = 1;
+      offset = exact_log2 (offset / nf);
+      int factor = exact_log2 (GET_MODE_BITSIZE (innermode).to_constant () /
+                               GET_MODE_BITSIZE (QImode));
+      return offset + factor;
+    }
+}
+
+static tree
+get_dt_t (machine_mode mode, bool u, bool ptr = false, bool c = false)
+{
+  if (mode == VOIDmode)
+    return void_type_node;
+    
+  machine_mode innermode = GET_MODE_INNER (mode);
+  enum vector_type_index base = get_type_idx (innermode, u);
+  tree type = NULL_TREE;
+  if (VECTOR_MODE_P (mode))
+    {
+      int offset = get_lmul_idx (mode);      
+      if (ptr)
+        type = vector_pointer_types[base][offset];
+      else
+        type = vector_types[0][base][offset];
+      
+      gcc_assert (type);
+      return type;
+    }
+  
+  if (ptr)
+    {
+      if (c)
+        type = const_scalar_pointer_types[base];
+      else
+        type = scalar_pointer_types[base];
+    }
+  else
+    type = scalar_types[base];
+  
+  gcc_assert (type);
+  return type;
+}
+
+/* Return true if the function has no return value.  */
+static bool
+function_returns_void_p (tree fndecl)
+{
+  return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+}
+
+/* Take argument ARGNO from EXP's argument list and convert it into
+   an expand operand.  Store the operand in *OP.  */
+
+static void
+add_input_operand (struct expand_operand *op, tree exp, unsigned argno)
+{
+  tree arg = CALL_EXPR_ARG (exp, argno);
+  rtx x = expand_normal (arg);
+  create_input_operand (op, x, TYPE_MODE (TREE_TYPE (arg)));
+}
+
+/* Expand instruction ICODE as part of a built-in function sequence.
+   Use the first NOPS elements of OPS as the instruction's operands.
+   HAS_TARGET_P is true if operand 0 is a target; it is false if the
+   instruction has no target.
+
+   Return the target rtx if HAS_TARGET_P, otherwise return const0_rtx.  */
+
+static rtx
+generate_builtin_insn (enum insn_code icode, unsigned int n_ops,
+                       struct expand_operand *ops, bool has_target_p)
+{
+  if (!maybe_expand_insn (icode, n_ops, ops))
+    {
+      error ("invalid argument to built-in function");
+      return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
+    }
+
+  return has_target_p ? ops[0].value : const0_rtx;
+}
+
+/* Return a hash code for a function_instance.  */
+static hashval_t
+get_string_hash (const char * input_string)
+{
+  if (!input_string || strlen (input_string) == 0)
+    return 0;
+
+  inchash::hash h;
+
+  for (unsigned int i = 0; i < strlen (input_string); i += 4)
+    {
+      unsigned int four_chars = 0;
+
+      for (unsigned int j = i; j < strlen (input_string) && j < i + 4; j++)
+        {
+          four_chars |= input_string[j] << (8 * (j - i));
+        }
+
+      h.add_int (four_chars);
+    }
+
+  return h.end ();
+}
+
+/* Report an error against LOCATION that the user has tried to use
+   function FNDECL when extension EXTENSION is disabled.  */
+static void
+report_missing_extension (location_t location, tree fndecl,
+                          const char *extension)
+{
+  /* Avoid reporting a slew of messages for a single oversight.  */
+  if (reported_missing_extension_p)
+    return;
+
+  error_at (location, "rvv function %qD requires ISA extension %qs", fndecl,
+            extension);
+  inform (location,
+          "you can enable %qs using the command-line"
+          " option %<-march%>",
+          extension);
+  reported_missing_extension_p = true;
+}
+
+/* Add attribute NAME to ATTRS.  */
+static tree
+add_attribute (const char *name, tree attrs)
+{
+  return tree_cons (get_identifier (name), NULL_TREE, attrs);
+}
+
+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;
+}
+
+/* function_instance class implemention */
+
+function_instance::function_instance (function_builder *__builder,
+                                      const char *__base_name,
+                                      vector_arg_modes &__arg_pattern,
+                                      enum predication_index __pred,
+                                      enum operation_index __operation)
+    : m_builder (__builder), m_base_name (__base_name),
+      m_target_arg_pattern (__arg_pattern), m_target_pred (__pred),
+      m_target_operation (__operation)
+{
+  function_name[0] = '\0';
+}
+
+function_instance::function_instance (const char *__name)
+{
+  memcpy (function_name, __name, NAME_MAXLEN);
+}
+
+function_instance::~function_instance ()
+{
+}
+
+inline bool
+function_instance::operator== (const function_instance &other) const
+{
+  return (strcmp (function_name, other.function_name) == 0);
+}
+
+inline bool
+function_instance::operator!= (const function_instance &other) const
+{
+  return !operator== (other);
+}
+
+/* Return a hash code for a function_instance.  */
+hashval_t
+function_instance::hash () const
+{
+  return get_string_hash (function_name);
+}
+
+bool
+function_instance::check (location_t, tree, tree, unsigned int, tree *) const
+{
+  return true;
+}
+
+/* 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 = m_builder->call_properties ();
+
+  /* -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 | CP_RAISE_LD_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 | CP_RAISE_LD_EXCEPTIONS))
+    return true;
+
+  /* Handle functions that could raise SIGBUS or SIGSEGV.  */
+  if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
+    return true;
+
+  return false;
+}
+
+const char *
+function_instance::get_base_name () const
+{
+  return m_base_name;
+}
+
+vector_arg_modes
+function_instance::get_arg_pattern () const
+{
+  return m_target_arg_pattern;
+}
+
+enum predication_index
+function_instance::get_pred () const
+{
+  return m_target_pred;
+}
+
+unsigned int
+function_instance::get_vma_vta () const
+{
+  return any_policy;
+}
+
+enum operation_index
+function_instance::get_operation () const
+{
+  return m_target_operation;
+}
+
+enum data_type_index *
+function_instance::get_data_type_list () const
+{
+  return m_builder->get_data_type_list ();
+}
+
+function_builder *
+function_instance::builder () const
+{
+  return m_builder;
+}
+
+/* function_builder class implemention */
+
+function_builder::function_builder (const char *__base_name,
+                                    vector_arg_all_modes &__arg_patterns,
+                                    uint64_t __pattern,
+                                    uint64_t __preds,
+                                    uint64_t __op_types,
+                                    const unsigned int __extensions)
+    : m_base_name (__base_name), m_target_arg_patterns (__arg_patterns),
+      m_target_pattern (__pattern), m_target_preds (__preds),
+      m_target_op_types (__op_types), m_required_extensions (__extensions)
+{
+  m_iter_idx_cnt = 0;
+  m_iter_arg_cnt = 0;
+  m_iter_arg_idx_list = (unsigned int *)xmalloc (m_target_arg_patterns.arg_len *
+                                                 sizeof (unsigned int));
+
+  for (unsigned int i = 0; i < m_target_arg_patterns.arg_len; i++)
+    {
+      // use mode iterator as mode iter
+      if (m_target_arg_patterns.target_op_list[i] < 0)
+        {
+          m_iter_idx_cnt =
+              (m_iter_idx_cnt == 0)
+                  ? m_target_arg_patterns.arg_list[i]->attr_len
+                  : m_iter_idx_cnt *
+                        m_target_arg_patterns.arg_list[i]->attr_len;
+          m_iter_arg_idx_list[m_iter_arg_cnt++] = i;
+        }
+    }
+
+  m_direct_overloads = lang_GNU_CXX ();
+
+  gcc_assert (m_iter_arg_cnt > 0);
+  gcc_assert (m_iter_idx_cnt > 0);
+  
+  gcc_obstack_init (&m_string_obstack);
+}
+
+function_builder::~function_builder ()
+{
+  free (m_iter_arg_idx_list);
+  obstack_free (&m_string_obstack, NULL);
+}
+
+/* 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);
+}
+
+rtx
+function_builder::expand_builtin_insn (enum insn_code icode, tree exp,
+                                       rtx target,
+                                       const function_instance &instance) const
+{
+  gcc_assert (call_expr_nargs (exp) > 0);
+  struct expand_operand ops[MAX_RECOG_OPERANDS];
+  machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  enum predication_index pred = instance.get_pred ();
+
+  /* Map any target to operand 0.  */
+  int opno = 0;
+  int offset = 0;
+
+  if (!function_returns_void_p (fndecl))
+    create_output_operand (&ops[opno++], target, mode);
+
+  if (need_mask_operand_p ())
+    {
+      if (has_mask_arg_p (pred))
+        add_input_operand (&ops[opno++], exp, offset++);
+      else
+        create_input_operand (&ops[opno++], const0_rtx, Pmode);
+    }
+
+  if (need_dest_operand_p ())
+    {
+      if (has_dest_arg_p (pred))
+        add_input_operand (&ops[opno++], exp, offset++);
+      else
+        create_input_operand (&ops[opno++], const0_rtx, Pmode);
+    }
+
+  for (int argno = offset; argno < call_expr_nargs (exp); argno++)
+    add_input_operand (&ops[opno++], exp, argno);
+
+  if (pred != PRED_none)
+    create_input_operand (&ops[opno++], GEN_INT (get_policy (pred)), Pmode);
+
+  /* Map the arguments to the other operands.  */
+  gcc_assert (opno == insn_data[icode].n_generator_args);
+  return generate_builtin_insn (icode, opno, ops,
+                                !function_returns_void_p (fndecl));
+}
+
+gimple *
+function_builder::fold (const function_instance &, gimple_stmt_iterator *,
+                        gcall *) const
+{
+  return NULL;
+}
+
+tree
+function_builder::get_return_type (const function_instance &) const
+{
+  return void_type_node;
+}
+
+size_t
+function_builder::get_dest_arguments_length () const
+{
+  return 1;
+}
+
+tree
+function_builder::get_mask_type (tree return_type,
+                                 const function_instance &instance,
+                                 const vec<tree> &) const
+{
+  tree type = return_type;
+  if (!VECTOR_MODE_P (TYPE_MODE (type)))
+    {
+      /* Fetch the vector mode start from arg[0]. */
+      for (unsigned int i = 0; i < instance.get_arg_pattern ().arg_len; i++)
+        {
+          if (VECTOR_MODE_P (instance.get_arg_pattern ().arg_list[i]))
+            {
+              type =
+                  get_dt_t (instance.get_arg_pattern ().arg_list[i],
+                            instance.get_data_type_list ()[i] == DT_unsigned);
+              break;
+            }
+        }
+    }
+  gcc_assert (VECTOR_MODE_P (TYPE_MODE (type)));
+  if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL)
+    return type;
+  else
+    {
+      machine_mode mask_mode;
+      gcc_assert (
+          rvv_get_mask_mode (TYPE_MODE (type)).exists (&mask_mode));
+      return mode2mask_t (mask_mode);
+    }
+}
+
+void
+function_builder::get_argument_types (const function_instance &,
+                                      vec<tree> &) const
+{
+}
+
+char *
+function_builder::assemble_name (function_instance &)
+{
+  return nullptr;
+}
+
+uint64_t
+function_builder::get_pattern () const
+{
+  return m_target_pattern;
+}
+
+bool
+function_builder::need_mask_operand_p () const
+{
+  uint64_t pat = get_pattern ();
+
+  return (pat & PAT_mask) || (pat & PAT_merge);
+}
+
+bool
+function_builder::need_dest_operand_p () const
+{
+  uint64_t pat = get_pattern ();
+
+  return (pat & PAT_tail) || ((pat & PAT_mask) && !(pat & PAT_ignore_policy));
+}
+
+bool
+function_builder::has_mask_arg_p (enum predication_index pred) const
+{
+  uint64_t pat = get_pattern ();
+
+  return pred == PRED_m || pred == PRED_tam || pred == PRED_tum ||
+         pred == PRED_tama || pred == PRED_tamu || pred == PRED_tuma ||
+         pred == PRED_tumu || pred == PRED_ma || pred == PRED_mu ||
+         (pat & PAT_merge);
+}
+
+bool
+function_builder::has_dest_arg_p (enum predication_index pred) const
+{
+  uint64_t pat = get_pattern ();
+
+  switch (pred)
+    {
+    case PRED_void:
+      return (pat & PAT_void_dest) || (pat & PAT_dest);
+    case PRED_ta:
+    case PRED_tama:
+      return (pat & PAT_dest);
+    case PRED_m:
+      return !(pat & PAT_ignore_policy);
+    case PRED_tu:
+    case PRED_tum:
+    case PRED_mu:
+    case PRED_tamu:
+    case PRED_tuma:
+    case PRED_tumu:
+      return true;
+    default:
+      return false;
+    }
+}
+
+bool
+function_builder::can_be_overloaded_p (const function_instance &) const
+{
+  return false;
+}
+
+unsigned int
+function_builder::get_policy (enum predication_index pred) const
+{
+  uint64_t pat = get_pattern ();
+
+  switch (pred)
+    {
+    case PRED_void:
+      return (pat & PAT_void_dest || pat & PAT_dest) ? tu_policy : ta_policy;
+    case PRED_m:
+      if (pat & PAT_ignore_policy)
+        return any_policy;
+      else if (pat & PAT_ignore_mask_policy)
+        return tu_policy;
+      else if (pat & PAT_ignore_tail_policy)
+        return mu_policy;
+      else
+        return tumu_policy;
+    case PRED_ta:
+    case PRED_tam:
+      return ta_policy;
+    case PRED_tu:
+    case PRED_tum:
+      return tu_policy;
+    case PRED_ma:
+      return ma_policy;
+    case PRED_mu:
+      return mu_policy;
+    case PRED_tama:
+      return tama_policy;
+    case PRED_tamu:
+      return tamu_policy;
+    case PRED_tuma:
+      return tuma_policy;
+    case PRED_tumu:
+      return tumu_policy;
+    default:
+      return any_policy;
+    }
+}
+
+size_t
+function_builder::get_position_of_mask_arg (enum predication_index) const
+{
+  return 0;
+}
+
+size_t
+function_builder::get_position_of_dest_arg (enum predication_index pred) const
+{
+  uint64_t pat = get_pattern ();
+  if (pred == PRED_tu ||
+      (pred == PRED_void && (pat & PAT_void_dest || pat & PAT_dest)) ||
+      (pred == PRED_ta && pat & PAT_dest))
+    return 0;
+  else
+    return 1;
+}
+
+unsigned int
+function_builder::call_properties () const
+{
+  return 0;
+}
+
+enum data_type_index *
+function_builder::get_data_type_list () const
+{
+  return m_target_arg_patterns.dt_list;
+}
+
+/* Return the appropriate function attributes for INSTANCE.  */
+tree
+function_builder::get_attributes (const function_instance &instance) const
+{
+  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 and OVERLOADED_P indicates
+   whether it is overloaded.  REQUIRED_EXTENSIONS are the set of
+   architecture extensions that the function requires.  */
+registered_function &
+function_builder::add_function (const function_instance &instance,
+                                const char *name, tree fntype, tree attrs,
+                                bool overloaded_p,
+                                bool placeholder_p) const
+{
+  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;
+  rfn.overloaded_p = overloaded_p;
+  rfn.required_extensions = m_required_extensions;
+  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.
+   REQUIRED_EXTENSIONS are the set of architecture extensions that the
+   function requires.  FORCE_DIRECT_OVERLOADS is true if there is a
+   one-to-one mapping between "short" and "full" names, and if standard
+   overload resolution therefore isn't necessary.  */
+void
+function_builder::add_unique_function (function_instance &instance,
+                                       tree return_type,
+                                       vec<tree> &argument_types)
+{
+  /* Add the function under its full (unique) name.  */
+  char *overloaded_name = this->assemble_name (instance);
+  if (instance.function_name[0] == '\0')
+    return;
+    
+  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, instance.function_name, fntype, attrs, false, false);
+
+  /* Enter the function into the hash table.  */
+  hashval_t hashval = instance.hash ();
+  registered_function **rfn_slot =
+      function_table->find_slot_with_hash (instance, hashval, INSERT);
+  
+  if (*rfn_slot)
+    {
+      error ("duplicate function name: %s", instance.function_name);
+      gcc_unreachable ();
+    }
+
+  *rfn_slot = &rfn;
+
+  if (overloaded_name)
+    {
+      /* Attribute lists shouldn't be shared.  */
+      tree attrs = get_attributes (instance);
+      bool placeholder_p = !m_direct_overloads;
+        add_function (instance, overloaded_name, fntype, attrs,
+                      false, placeholder_p);
+      obstack_free (&m_string_obstack, overloaded_name);
+    }
+}
+
+/* Check whether all the RISCV_* values in REQUIRED_EXTENSIONS are
+   enabled, given that those extensions are required for function FNDECL.
+   Report an error against LOCATION if not.  */
+bool
+function_builder::check_required_extensions (location_t location, tree fndecl,
+                                             uint64_t required_extensions) const
+{
+  /* For the instructions doesn't need any extension, we return true.  */
+  if (required_extensions == 0)
+    return true;
+
+  /* check vector extension enable or not.  */
+  if ((required_extensions & 0x1) && !TARGET_VECTOR)
+    report_missing_extension (location, fndecl, "V");
+
+  /* check f extension enable or not.  */
+  if (((required_extensions >> 4) & 0x1) && !TARGET_HARD_FLOAT)
+    report_missing_extension (location, fndecl, "F");
+
+  /* check d extension enable or not.  */
+  if (((required_extensions >> 5) & 0x1) && !TARGET_DOUBLE_FLOAT)
+    report_missing_extension (location, fndecl, "D");
+
+  return true;
+}
+
+/* If INSTANCE has a governing predicate, add it to the list of argument
+   types in ARGUMENT_TYPES.  RETURN_TYPE is the type returned by the
+   function.  */
+void
+function_builder::apply_predication (const function_instance &instance,
+                                     tree return_type,
+                                     vec<tree> &argument_types) const
+{
+  /* check if mask parameter need. */
+  if (has_mask_arg_p (instance.get_pred ()))
+    {
+      argument_types.quick_insert (
+          get_position_of_mask_arg (instance.get_pred ()),
+          get_mask_type (return_type, instance, argument_types));
+    }
+
+  /* check if dest parameter need. */
+  if (has_dest_arg_p (instance.get_pred ()))
+    {
+      size_t size = get_dest_arguments_length ();
+      if (argument_types.is_empty ())
+        for (size_t i = 0; i < size; i += 1)
+          argument_types.quick_push (return_type);
+      else
+        for (size_t i = 0; i < size; i += 1)
+          argument_types.quick_insert (get_position_of_dest_arg (instance.get_pred ()) + i,
+                                       return_type);
+    }
+
+  /* check if vl parameter need  */
+  if (instance.get_pred () != PRED_none)
+    argument_types.quick_push (size_type_node);
+}
+
+void
+function_builder::build_one (function_instance &instance)
+{
+  /* Byte forms of vlxusegei take 21 arguments.  */
+  auto_vec<tree, 21> argument_types;
+  tree return_type = get_return_type (instance);
+  get_argument_types (instance, argument_types);
+  apply_predication (instance, return_type, argument_types);
+  add_unique_function (instance, return_type, argument_types);
+}
+
+vector_arg_modes &
+function_builder::get_arg_modes_by_iter_idx (unsigned int iter_idx) const
+{
+  if (iter_idx >= m_iter_idx_cnt)
+    {
+      gcc_unreachable ();
+    }
+
+  unsigned int coefficient = 1;
+  machine_mode *arg_modes = (machine_mode *)xmalloc (
+      sizeof (machine_mode) * m_target_arg_patterns.arg_len);
+  vector_arg_modes &arg_modes_info =
+      *(vector_arg_modes *)xmalloc (sizeof (vector_arg_modes));
+  arg_modes_info.arg_len = m_target_arg_patterns.arg_len;
+  arg_modes_info.arg_list = arg_modes;
+  arg_modes_info.arg_extensions = m_required_extensions;
+
+  // set mode for iter args first
+  for (unsigned int i = 0; i < m_iter_arg_cnt; i++)
+    {
+      // get the iter arg's attribute length
+      unsigned int arg_attr_len =
+          m_target_arg_patterns.arg_list[m_iter_arg_idx_list[i]]->attr_len;
+      vector_mode_attr target_mode_attr =
+          m_target_arg_patterns.arg_list[m_iter_arg_idx_list[i]]
+              ->attr_list[(iter_idx / coefficient) % arg_attr_len];
+      arg_modes[m_iter_arg_idx_list[i]] = target_mode_attr.mode;
+      arg_modes_info.arg_extensions |= target_mode_attr.extension;
+      coefficient *= arg_attr_len;
+    }
+
+  // set mode for attr args
+  for (unsigned int i = 0; i < m_target_arg_patterns.arg_len; i++)
+    {
+      // skip iter args
+      if (m_target_arg_patterns.target_op_list[i] < 0)
+        continue;
+
+      machine_mode iter_mode =
+          arg_modes[m_target_arg_patterns.target_op_list[i]];
+      vector_mode_attr_list *arg_attr_list = m_target_arg_patterns.arg_list[i];
+      bool attr_mode_hit = false;
+
+      for (unsigned int j = 0; j < arg_attr_list->attr_len; j++)
+        {
+          if (iter_mode == arg_attr_list->attr_list[j].mode)
+            {
+              attr_mode_hit = true;
+              arg_modes[i] = arg_attr_list->attr_list[j].attr;
+              arg_modes_info.arg_extensions |=
+                  arg_attr_list->attr_list[j].extension;
+            }
+        }
+
+      // one argment mode NOT hit, that means maybe NO mode is valid for
+      // iter_idx
+      if (!attr_mode_hit)
+        {
+          // set arg_len to 0 to skip this arg pattern
+          arg_modes_info.arg_len = 0;
+          break;
+        }
+    }
+
+  return arg_modes_info;
+}
+
+void
+function_builder::register_function ()
+{
+  for (unsigned iter_idx = 0; iter_idx < m_iter_idx_cnt; iter_idx++)
+    {
+      vector_arg_modes &arg_modes = get_arg_modes_by_iter_idx (iter_idx);
+      
+      bool skip_p = false;
+      if (arg_modes.arg_len == 0)
+        skip_p = true;
+        
+      if (FLOAT_MODE_P (arg_modes.arg_list[0]) && 
+        get_data_type_list ()[0] == DT_unsigned)
+        skip_p = true;
+
+      if (skip_p)
+        {
+          free (arg_modes.arg_list);
+          free (&arg_modes);
+          continue;
+        }
+      for (unsigned pred = 1; pred < NUM_PREDS; pred <<= 1)
+        {
+          if ((m_target_preds & pred) == 0)
+            continue;
+
+          for (unsigned op_type = 1; op_type < NUM_OP; op_type <<= 1)
+            {
+              if ((m_target_op_types & op_type) == 0)
+                continue;
+
+              function_instance instance (
+                  this, m_base_name, arg_modes,
+                  (enum predication_index) (m_target_preds & pred),
+                  (enum operation_index) (m_target_op_types & op_type));
+              build_one (instance);
+            }
+        }
+    }
+}
+
+} // end namespace riscv_vector
+
+using 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-functions.h"
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
new file mode 100644
index 00000000000..f6161012813
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -0,0 +1,34 @@ 
+/* Intrinsic macros for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+   Based on MIPS target for GNU compiler.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef DEF_RVV_FUNCTION
+#define DEF_RVV_FUNCTION(A, B, C, D, E, F, G)
+#endif
+#ifndef VITER
+#define VITER(A)
+#endif
+#ifndef VATTR
+#define VATTR(A, B)
+#endif
+
+#undef DEF_RVV_FUNCTION
+#undef VITER
+#undef VATTR
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.h b/gcc/config/riscv/riscv-vector-builtins-functions.h
new file mode 100644
index 00000000000..1b769743857
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.h
@@ -0,0 +1,491 @@ 
+/* Intrinsic definitions for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_RISCV_VECTOR_BUILTINS_FUNCTIONS_H
+#define GCC_RISCV_VECTOR_BUILTINS_FUNCTIONS_H
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "stor-layout.h"
+#include "regs.h"
+#include "alias.h"
+#include "gimple-fold.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-pass.h"
+#include "tree-vrp.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-operands.h"
+#include "tree-phinodes.h"
+#include "targhooks.h"
+#include "langhooks-def.h"
+#include "riscv-vector.h"
+#include <string>
+
+namespace riscv_vector
+{
+  
+/* The macro defines the maximum length of name string. */
+static const unsigned int NAME_MAXLEN = 32;
+/* The macro defines the maxmum number of tuple. For 
+   RISC-V 'V' Extension, the maxmum tuple number is 8. 
+   TODO: We will support tuple type for segment instructions later. */
+static const unsigned int MAX_TUPLE_NUM = 1;
+
+/* Describes the various of data_type. 
+   Used by riscv-vector-builtins-iterators.def. */
+enum data_type_index
+{
+  /* signed data. */
+  DT_signed,
+  /* unsigned data. */
+  DT_unsigned,
+  /* signed data pointer. */
+  DT_ptr,
+  /* unsigned data pointer. */
+  DT_uptr,
+  /* const signed data pointer. */
+  DT_c_ptr,
+  /* const unsigned data pointer. */
+  DT_c_uptr,
+};
+
+/* Describes the various uses of a governing predicate.
+   Used by riscv-vector-builtins-iterators.def.  */
+enum predication_index
+{
+  /* No governing predicate is present.  */
+  PRED_none = 1 << 0,
+  /* tail agnostic, ignore mask policy */
+  PRED_ta = 1 << 3,
+  /* tail undisturbed, ignore mask policy */
+  PRED_tu = 1 << 4,
+  /* mask agnostic, ignore tail policy */
+  PRED_ma = 1 << 5,
+  /* mask undisturbed, ignore tail policy */
+  PRED_mu = 1 << 6,
+  /* mask and tail both agnostic */
+  PRED_tama = 1 << 7,
+  /* mask undisturbed and tail agnostic */
+  PRED_tamu = 1 << 8,
+  /* mask agnostic and tail undisturbed */
+  PRED_tuma = 1 << 9,
+  /* mask and tail both undisturbed */
+  PRED_tumu = 1 << 10,
+  /* No governing predicate is present.  */
+  PRED_void = 1 << 11,
+  /* mask and tail both undisturbed */
+  PRED_m = 1 << 12,
+  /* tail agnostic, ignore mask policy */
+  PRED_tam = 1 << 13,
+  /* tail undisturbed, ignore mask policy */
+  PRED_tum = 1 << 14,
+
+  NUM_PREDS
+};
+
+/* Describes the various intrinsic types.  */
+enum intrinsic_pattern
+{
+  /* other intrinsic */
+  PAT_none = 1 << 0,
+  PAT_mask = 1 << 1,
+  PAT_tail = 1 << 2,
+  PAT_dest = 1 << 3,
+  PAT_void_dest = 1 << 4,
+  PAT_ignore_mask_policy = 1 << 5,
+  PAT_ignore_tail_policy = 1 << 6,
+  PAT_ignore_policy = 1 << 7,
+  PAT_merge = 1 << 8,
+};
+
+/* Describes the various operation types.  */
+enum operation_index
+{
+  OP_none = 1 << 0,
+  OP_vv = 1 << 1,
+  OP_vx = 1 << 2,
+  OP_v = 1 << 3,
+  OP_wv = 1 << 4,
+  OP_wx = 1 << 5,
+  OP_x_x_v = 1 << 6,
+  OP_vf2 = 1 << 7,
+  OP_vf4 = 1 << 8,
+  OP_vf8 = 1 << 9,
+  OP_vvm = 1 << 10,
+  OP_vxm = 1 << 11,
+  OP_x_x_w = 1 << 12,
+  OP_v_v = 1 << 13,
+  OP_v_x = 1 << 14,
+  OP_vs = 1 << 15,
+  OP_mm = 1 << 16,
+  OP_m = 1 << 17,
+  OP_vf = 1 << 18,
+  OP_vm = 1 << 19,
+  OP_wf = 1 << 20,
+  OP_vfm = 1 << 21,
+  OP_v_f = 1 << 22,
+  NUM_OP
+};
+
+/* Describe indexed-ordered or indexed-unordered load store.  */
+enum indexed_mode
+{
+  INDEXED_u,
+  INDEXED_o,
+};
+
+/* Describe vector policy.  */
+enum vector_policy
+{
+  undisturbed = 0,
+  agnostic = 1,
+  any = 2,
+};
+
+/* Enumerates the VECTOR (data) vector types, together called
+   "vector types" for brevity.  */
+enum vector_type_index
+{
+#define DEF_RVV_TYPE(ELEM_TYPE, NODE) VECTOR_TYPE_##ELEM_TYPE,
+#include "riscv-vector-builtins.def"
+  NUM_VECTOR_TYPES
+#undef DEF_RVV_TYPE
+};
+
+struct vector_vlmul_info
+{
+  enum vlmul_field_enum vlmul;
+  const char *suffix;
+  const char *boolnum;
+};
+
+struct vector_type_info
+{
+  enum vector_type_index type;
+  const char *elem_name;
+};
+
+// for function arg mode infomation, include return type
+struct vector_mode_attr
+{
+  machine_mode mode;
+  machine_mode attr;
+  // the extension like TARGET_VECTOR
+  uint64_t extension;
+};
+
+// the total variable pack for function arg mode infomation, include return
+// type
+struct vector_mode_attr_list
+{
+  unsigned int attr_len;
+  vector_mode_attr *attr_list;
+};
+
+// for VATTR(OP, MODE_ATTR)
+struct vector_arg_attr_info
+{
+  int target_op;
+  enum data_type_index dt;
+  vector_mode_attr_list *mode_attr_list;
+};
+
+struct vector_arg_all_modes
+{
+  unsigned int arg_len;
+  data_type_index *dt_list;
+  int *target_op_list;
+  // arg_list[0] is always return type
+  vector_mode_attr_list **arg_list;
+};
+
+struct vector_arg_modes
+{
+  uint64_t arg_extensions;
+  unsigned int arg_len;
+  // arg_list[0] is always return type
+  machine_mode *arg_list;
+};
+
+constexpr unsigned int
+get_vma_vta (vector_policy vma, vector_policy vta)
+{
+  return (vma << 2) | vta;
+}
+
+constexpr vector_policy
+get_vma (unsigned int vma_vta)
+{
+  return (vector_policy)((vma_vta >> 2) & 0b11);
+}
+
+constexpr vector_policy
+get_vta (unsigned int vma_vta)
+{
+  return (vector_policy)(vma_vta & 0b11);
+}
+
+const unsigned int tama_policy = get_vma_vta(vector_policy::agnostic, vector_policy::agnostic);
+const unsigned int tamu_policy = get_vma_vta(vector_policy::undisturbed, vector_policy::agnostic);
+const unsigned int tuma_policy = get_vma_vta(vector_policy::agnostic, vector_policy::undisturbed);
+const unsigned int tumu_policy = get_vma_vta(vector_policy::undisturbed, vector_policy::undisturbed);
+const unsigned int ta_policy = get_vma_vta(vector_policy::any, vector_policy::agnostic);
+const unsigned int tu_policy = get_vma_vta(vector_policy::any, vector_policy::undisturbed);
+const unsigned int ma_policy = get_vma_vta(vector_policy::agnostic, vector_policy::any);
+const unsigned int mu_policy = get_vma_vta(vector_policy::undisturbed, vector_policy::any);
+const unsigned int any_policy = get_vma_vta(vector_policy::any, vector_policy::any);
+
+inline rtx
+gen_tama_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, tama_policy);
+}
+
+inline rtx
+gen_tamu_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, tamu_policy);
+}
+
+inline rtx
+gen_tuma_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, tuma_policy);
+}
+
+inline rtx
+gen_tumu_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, tumu_policy);
+}
+
+inline rtx
+gen_ta_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, ta_policy);
+}
+
+inline rtx
+gen_tu_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, tu_policy);
+}
+
+inline rtx
+gen_ma_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, ma_policy);
+}
+
+inline rtx
+gen_mu_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, mu_policy);
+}
+
+inline rtx
+gen_any_policy ()
+{
+  return gen_rtx_CONST_INT (Pmode, any_policy);
+}
+
+class function_builder;
+
+class GTY ((user)) function_instance
+{
+public:
+  function_instance (function_builder *, const char *, vector_arg_modes &,
+                     enum predication_index, enum operation_index);
+  function_instance (const char *__name);
+  ~function_instance ();
+
+  bool operator== (const function_instance &) const;
+  bool operator!= (const function_instance &) const;
+
+  hashval_t hash () const;
+  bool check (location_t, tree, tree, unsigned int, tree *) const;
+  unsigned int call_properties () const;
+  bool reads_global_state_p () const;
+  bool modifies_global_state_p () const;
+  bool could_trap_p () const;
+
+  const char *get_base_name () const;
+  vector_arg_modes get_arg_pattern () const;
+  enum predication_index get_pred () const;
+  unsigned int get_vma_vta () const;
+  enum operation_index get_operation () const;
+  enum data_type_index *get_data_type_list () const;
+  function_builder *builder () const;
+  
+  char function_name[NAME_MAXLEN];
+
+private:
+  function_builder *m_builder;
+  const char *m_base_name;
+  vector_arg_modes m_target_arg_pattern;
+  enum predication_index m_target_pred;
+  enum operation_index m_target_operation;
+};
+
+/* Describes a function decl.  */
+class GTY (()) registered_function
+{
+public:
+  function_instance GTY ((skip)) instance;
+
+  /* The decl itself.  */
+  tree GTY ((skip)) decl;
+
+  /* The architecture extensions that the function requires, as a set of
+     RISCV_TARGET_* flags.  */
+  uint64_t required_extensions;
+  
+  /* True if the decl represents an overloaded function that needs to be
+     resolved.  */
+  bool overloaded_p;
+};
+
+/* A class for building and registering function decls.  */
+class function_builder
+{
+public:
+  function_builder (const char *, vector_arg_all_modes &, uint64_t,
+                    uint64_t, uint64_t, const unsigned int);
+
+  virtual ~function_builder ();
+
+  void register_function ();
+
+  /* Try to fold the given gimple call.  Return the new gimple statement
+     on success, otherwise return null.  */
+  virtual gimple * fold (const function_instance &, gimple_stmt_iterator *, gcall *) 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 (const function_instance &, tree, rtx) const = 0;
+
+  rtx
+  expand_builtin_insn (enum insn_code, tree, rtx,
+                       const function_instance &) const;
+
+  virtual tree get_return_type (const function_instance &) const;
+
+  virtual tree get_mask_type (tree, const function_instance &, const vec<tree> &) const;
+
+  virtual void get_argument_types (const function_instance &,
+                                   vec<tree> &) const;
+
+  virtual size_t get_dest_arguments_length () const;
+  
+  uint64_t get_pattern () const;
+  /* check if need add mask operand for corresponding rtl */
+  bool need_mask_operand_p () const;
+  /* check if need add dest operand for corresponding rtl */
+  bool need_dest_operand_p () const;
+  /* check if has mask arg for corresponding function decl */
+  bool has_mask_arg_p (enum predication_index) const;
+  /* check if has dest arg for corresponding function decl */
+  virtual bool has_dest_arg_p (enum predication_index) const;
+  unsigned int get_policy (enum predication_index) const;
+  /* get parameter position of mask arg */
+  virtual size_t get_position_of_mask_arg (enum predication_index) const;
+  /* get parameter position of dest arg */
+  virtual size_t get_position_of_dest_arg (enum predication_index) const;
+
+  void apply_predication (const function_instance &, tree, vec<tree> &) const;
+
+  virtual unsigned int call_properties () const;
+
+  vector_arg_modes &get_arg_modes_by_iter_idx (unsigned int) const;
+
+  enum data_type_index *get_data_type_list () const;
+
+  bool check_required_extensions (location_t, tree, uint64_t) const;
+  virtual char * assemble_name (function_instance &);
+  void append_name (const char *);
+  char *finish_name ();
+  
+  /* Return true if the function can be overloaded. */ 
+  virtual bool can_be_overloaded_p (const function_instance &) const;
+  
+private:
+  void add_unique_function (function_instance &, tree, vec<tree> &);
+  void build_one (function_instance &);
+  tree get_attributes (const function_instance &) const;
+
+  registered_function &add_function (const function_instance &, const char *,
+                                     tree, tree, bool, bool) const;
+
+  /* The base name, as a string.  */
+  const char *m_base_name;
+  vector_arg_all_modes m_target_arg_patterns;
+  uint64_t m_target_pattern;
+  uint64_t m_target_preds;
+  uint64_t m_target_op_types;
+  uint64_t m_required_extensions;
+
+  unsigned int m_iter_idx_cnt;
+  unsigned int m_iter_arg_cnt;
+  unsigned int *m_iter_arg_idx_list;
+
+  /* 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;
+};
+
+/* 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 &);
+};
+
+} // namespace riscv_vector
+
+#endif // end GCC_RISCV_VECTOR_BUILTINS_FUNCTIONS_H
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector-builtins-iterators.def b/gcc/config/riscv/riscv-vector-builtins-iterators.def
new file mode 100644
index 00000000000..ac0c37e12d4
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins-iterators.def
@@ -0,0 +1,12 @@ 
+/* Do not modify this file, it auto gen by md-parser script */
+#ifndef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+#define DEF_RISCV_ARG_MODE_ATTR_VARIABLE(A, B)
+#endif
+
+#ifndef DEF_RISCV_ARG_MODE_ATTR
+#define DEF_RISCV_ARG_MODE_ATTR(A, B, C, D, E)
+#endif
+
+
+#undef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+#undef DEF_RISCV_ARG_MODE_ATTR
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
new file mode 100644
index 00000000000..7ea07a24b5b
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -0,0 +1,266 @@ 
+/* Builtins implementation for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "stor-layout.h"
+#include "regs.h"
+#include "alias.h"
+#include "gimple-fold.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-pass.h"
+#include "tree-vrp.h"
+#include "tree-ssanames.h"
+#include "tree-ssa-operands.h"
+#include "tree-phinodes.h"
+#include "targhooks.h"
+#include "langhooks-def.h"
+#include "riscv-vector-builtins.h"
+#include "riscv-vector-builtins-functions.h"
+#include "riscv-vector.h"
+namespace riscv_vector
+{
+
+/* The same vlmul doesn't mean use the same mask,
+   this is used as save codes.
+   for example: i32m8 use vbool4_t i8m8 use vbool1_t. */
+static CONSTEXPR const vector_vlmul_info vector_vlmuls[] =
+{
+  { VLMUL_FIELD_101, "mf8", "64" }, { VLMUL_FIELD_110, "mf4", "32" },
+  { VLMUL_FIELD_111, "mf2", "16" }, { VLMUL_FIELD_000, "m1", "8" },
+  { VLMUL_FIELD_001, "m2", "4" }, { VLMUL_FIELD_010, "m4", "2" },
+  { VLMUL_FIELD_011, "m8", "1" },
+};
+
+static CONSTEXPR const vector_type_info vector_type_infos[] =
+{
+#define DEF_RVV_TYPE(ELEM_TYPE, NODE) { VECTOR_TYPE_##ELEM_TYPE, #ELEM_TYPE },
+#include "riscv-vector-builtins.def"
+#undef DEF_RVV_TYPE
+};
+
+static GTY(()) tree internal_vector_types[NUM_VECTOR_TYPES + 1][MAX_VLMUL_FIELD];
+
+/* Same, but with the riscv_vector.h "v..._t" name.  */
+GTY(()) tree vector_types[MAX_TUPLE_NUM][NUM_VECTOR_TYPES + 1][MAX_VLMUL_FIELD];
+/* Same, but with the riscv_vector.h "v..._t *" name.  */
+GTY(()) tree vector_pointer_types[NUM_VECTOR_TYPES + 1][MAX_VLMUL_FIELD];
+/* The scalar type associated with each vector type.  */
+GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+/* The scalar pointer type associated with each vector type.  */
+GTY(()) tree scalar_pointer_types[NUM_VECTOR_TYPES];
+/* The const scalar pointer type associated with each vector type.  */
+GTY(()) tree const_scalar_pointer_types[NUM_VECTOR_TYPES];
+
+/* All registered function decls, hashed on the function_instance
+   that they implement.  This is used for looking up implementations of
+   overloaded functions.  */
+hash_table<registered_function_hasher> *function_table;
+
+static riscv_vector::function_builder** all_vector_functions;
+
+/* The list of all registered function decls, indexed by code.  */
+vec<registered_function *, va_gc> *registered_functions;
+
+static unsigned int NUM_INSN_FUNC;
+
+static void init_def_variables ();
+
+/* Initialize all compiler built-ins related to RVV that should be
+   defined at start-up.  */
+void
+init_builtins ()
+{
+  if (!TARGET_VECTOR)
+    return;
+}
+
+/* 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;
+}
+
+/* Perform any semantic checks needed for a call to the RVV function
+   with subcode CODE, such as testing for integer constant expressions.
+   The call occurs at location LOCATION and has NARGS arguments,
+   given by ARGS.  FNDECL is the original function decl, before
+   overload resolution.
+
+   Return true if the call is valid, otherwise report a suitable error.  */
+bool
+check_builtin_call (location_t location, vec<location_t>, unsigned int code,
+                    tree fndecl, unsigned int nargs, tree *args)
+{
+  const registered_function &rfn = *(*registered_functions)[code];
+  function_builder *builder = rfn.instance.builder ();
+
+  if (!builder->check_required_extensions (
+          location, rfn.decl, rfn.instance.get_arg_pattern ().arg_extensions))
+    return false;
+
+  return rfn.instance.check (location, fndecl, TREE_TYPE (rfn.decl), nargs,
+                             args);
+}
+
+/* Attempt to fold STMT, given that it's a call to the RVV function
+   with subcode CODE.  Return the new statement on success and null
+   on failure.  Insert any other new statements at GSI.  */
+gimple *
+gimple_fold_builtin (unsigned int code, gimple_stmt_iterator *gsi, gcall *stmt)
+{
+  registered_function &rfn = *(*registered_functions)[code];
+  function_builder *builder = rfn.instance.builder ();
+  return builder->fold (rfn.instance, gsi, stmt);
+}
+
+/* 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];
+  function_builder *builder = rfn.instance.builder ();
+
+  if (!builder->check_required_extensions (
+          EXPR_LOCATION (exp), rfn.decl,
+          rfn.instance.get_arg_pattern ().arg_extensions))
+    return target;
+
+  return builder->expand (rfn.instance, exp, target);
+}
+
+riscv_vector::vector_arg_all_modes &
+get_vector_arg_all_patterns (unsigned int len,
+                             riscv_vector::vector_arg_attr_info attr, ...)
+{
+  riscv_vector::vector_arg_all_modes &patterns =
+      *ggc_alloc<riscv_vector::vector_arg_all_modes> ();
+  patterns.arg_len = len;
+  patterns.arg_list = (riscv_vector::vector_mode_attr_list **)xmalloc (
+      len * sizeof (riscv_vector::vector_mode_attr_list *));
+  patterns.target_op_list = (int *)xmalloc (len * sizeof (int));
+  patterns.dt_list =
+      (enum data_type_index *)xmalloc (len * sizeof (enum data_type_index));
+
+  unsigned int arg_idx = 0;
+  va_list arg_ptr;
+  riscv_vector::vector_arg_attr_info next_attr = attr;
+
+  va_start (arg_ptr, attr);
+
+  while (arg_idx < len)
+    {
+      patterns.dt_list[arg_idx] = next_attr.dt;
+      patterns.arg_list[arg_idx] = next_attr.mode_attr_list;
+      patterns.target_op_list[arg_idx] = next_attr.target_op;
+      next_attr = va_arg (arg_ptr, riscv_vector::vector_arg_attr_info);
+      arg_idx++;
+    }
+
+  va_end (arg_ptr);
+
+  return patterns;
+}
+
+static vector_mode_attr_list vector_mode_attr_list_list[vector_arg_mode_category_num];
+
+static void
+init_def_variables ()
+{
+
+/* define vector arg mode category */
+#define VVAR(NAME) vector_mode_attr_list_list[vector_mode_attr_##NAME]
+#define VITER(NAME, SIGN) riscv_vector::vector_arg_attr_info{-1, DT_##SIGN, &VVAR(NAME)}
+#define VATTR(OP, NAME, SIGN) riscv_vector::vector_arg_attr_info{OP, DT_##SIGN, &VVAR(NAME)}
+#define DEF_RISCV_ARG_MODE_ATTR_VARIABLE(VARIABLE_NAME, ELEM_CNT) \
+  VVAR(VARIABLE_NAME) = {ELEM_CNT, \
+    (riscv_vector::vector_mode_attr*)xmalloc(ELEM_CNT * sizeof(vector_mode_attr))};
+#include "riscv-vector-builtins-iterators.def"
+#undef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+
+/* define every vector arg mode in category  */
+#define DEF_RISCV_ARG_MODE_ATTR(VARIABLE_NAME, INDEX, MODE, ATTR_MODE,        \
+				CONDITION)                                    \
+  VVAR (VARIABLE_NAME).attr_list[INDEX]                                       \
+      = { MODE##mode, ATTR_MODE##mode, RISCV_##CONDITION };
+#include "riscv-vector-builtins-iterators.def"
+#undef DEF_RISCV_ARG_MODE_ATTR
+
+  /* count the number of intrinsic functions */
+  NUM_INSN_FUNC = 0;
+#define DEF_RVV_FUNCTION(BASE_NAME, CLASS_NAME, ARG_PATTERN, INTRNSIC_PATTER, PREDS, OP_TYPES) \
+  NUM_INSN_FUNC++;
+#include "riscv-vector-builtins-functions.def"
+#undef DEF_RVV_FUNCTION
+
+  all_vector_functions = (riscv_vector::function_builder **)xmalloc (
+			   sizeof (riscv_vector::function_builder *) * NUM_INSN_FUNC);
+
+  unsigned int func_idx = 0;
+#define VITER(NAME, SIGN)                                                     \
+  riscv_vector::vector_arg_attr_info { -1, DT_##SIGN, &VVAR (NAME) }
+#define VATTR(OP, NAME, SIGN)                                                 \
+  riscv_vector::vector_arg_attr_info { OP, DT_##SIGN, &VVAR (NAME) }
+#define DEF_RVV_FUNCTION(BASE_NAME, CLASS_NAME, ARG_PATTERN, INTRNSIC_PATTER, PREDS, OP_TYPES) \
+  all_vector_functions[func_idx++] = new riscv_vector::CLASS_NAME (           \
+      #BASE_NAME, get_vector_arg_all_patterns ARG_PATTERN, INTRNSIC_PATTER, PREDS, OP_TYPES,   \
+      (REQUIRED_EXTENSIONS));
+#include "riscv-vector-builtins-functions.def"
+#undef DEF_RVV_FUNCTION
+}
+
+} //end namespace riscv_vector
+
+using namespace riscv_vector;
+
+#include "gt-riscv-vector-builtins.h"
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def
new file mode 100644
index 00000000000..805f9d725dc
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.def
@@ -0,0 +1,37 @@ 
+/* Builtins macros for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef DEF_RVV_TYPE
+#define DEF_RVV_TYPE(A, B)
+#endif
+
+DEF_RVV_TYPE (bool, boolean)
+DEF_RVV_TYPE (float32, float)
+DEF_RVV_TYPE (float64, double)
+DEF_RVV_TYPE (int8, int8)
+DEF_RVV_TYPE (int16, int16)
+DEF_RVV_TYPE (int32, int32)
+DEF_RVV_TYPE (int64, int64)
+DEF_RVV_TYPE (uint8, unsigned_int8)
+DEF_RVV_TYPE (uint16, unsigned_int16)
+DEF_RVV_TYPE (uint32, unsigned_int32)
+DEF_RVV_TYPE (uint64, unsigned_int64)
+
+#undef DEF_RVV_TYPE
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
new file mode 100644
index 00000000000..6bba4c90c3a
--- /dev/null
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -0,0 +1,59 @@ 
+/* Builtins definitions for RISC-V 'V' Extension for GNU compiler.
+   Copyright (C) 2022-2022 Free Software Foundation, Inc.
+   Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_RISCV_VECTOR_BUILTINS_H
+#define GCC_RISCV_VECTOR_BUILTINS_H
+
+#include <vector>
+#include "riscv-vector-builtins-functions.h"
+
+namespace riscv_vector
+{
+  
+/* global share variables */
+
+static const unsigned int RISCV_TARGET_ANY = 0;
+static const unsigned int RISCV_TARGET_VECTOR = 1;
+static const unsigned int RISCV_TARGET_HARD_FLOAT = 1 << 2;
+static const unsigned int RISCV_TARGET_DOUBLE_FLOAT = 1 << 3;
+
+enum vector_arg_mode_category {
+#define VVAR(NAME) vector_mode_attr_##NAME
+#define DEF_RISCV_ARG_MODE_ATTR_VARIABLE(VARIABLE_NAME, ELEM_CNT) \
+  VVAR(VARIABLE_NAME),
+#include "riscv-vector-builtins-iterators.def"
+#undef DEF_RISCV_ARG_MODE_ATTR_VARIABLE
+#undef VVAR
+  /* the number of arg mode category */
+  vector_arg_mode_category_num
+};
+
+void init_builtins ();
+void handle_pragma_vector ();
+tree builtin_decl (unsigned, bool);
+gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *);
+rtx expand_builtin (unsigned int, tree, rtx);
+bool check_builtin_call (location_t, vec<location_t>, unsigned int,
+			 tree, unsigned int, tree *);
+machine_mode vector_builtin_mode (scalar_mode, enum vlmul_field_enum);
+
+} // end namespace riscv_vector
+
+#endif
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector.cc b/gcc/config/riscv/riscv-vector.cc
index e315b5d2cac..87dc6739f4f 100644
--- a/gcc/config/riscv/riscv-vector.cc
+++ b/gcc/config/riscv/riscv-vector.cc
@@ -226,4 +226,21 @@  rvv_regsize (machine_mode mode)
     }
 	
 	return 1;
+}
+
+/* Get related mask mode for a RVV vector mode.  */
+
+opt_machine_mode
+rvv_get_mask_mode (machine_mode mode)
+{
+  machine_mode mask_mode;
+  int nf = 1;
+
+  FOR_EACH_MODE_IN_CLASS (mask_mode, MODE_VECTOR_BOOL)
+    if (GET_MODE_INNER (mask_mode) == BImode
+      && known_eq (GET_MODE_NUNITS (mask_mode) * nf,
+        GET_MODE_NUNITS (mode))
+      && rvv_mask_mode_p (mask_mode))
+      return mask_mode;
+  return default_get_mask_mode (mode);
 }
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv-vector.h b/gcc/config/riscv/riscv-vector.h
index b8d77ddb195..62df507e7df 100644
--- a/gcc/config/riscv/riscv-vector.h
+++ b/gcc/config/riscv/riscv-vector.h
@@ -25,4 +25,5 @@  bool rvv_legitimate_poly_int_p (rtx);
 unsigned int rvv_offset_temporaries (bool, poly_int64);
 vlmul_field_enum rvv_classify_vlmul_field (machine_mode);
 int rvv_regsize (machine_mode);
+opt_machine_mode rvv_get_mask_mode (machine_mode);
 #endif // GCC_RISCV_VECTOR_H
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 37d8f1271d4..b82a38da7c9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4967,7 +4967,16 @@  riscv_class_max_nregs (reg_class_t rclass, machine_mode mode)
 
   if (reg_class_subset_p (rclass, GR_REGS))
     return riscv_hard_regno_nregs (GP_REG_FIRST, mode);
+		
+  if (reg_class_subset_p (V_REGS, rclass))
+    return riscv_hard_regno_nregs (V_REG_FIRST, mode);
+
+  if (reg_class_subset_p (VL_REGS, rclass))
+    return 1;
 
+  if (reg_class_subset_p (VTYPE_REGS, rclass))
+    return 1;
+		
   return 0;
 }
 
@@ -5308,6 +5317,15 @@  riscv_conditional_register_usage (void)
       for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
 	call_used_regs[regno] = 1;
     }
+
+  if (!TARGET_VECTOR)
+    {
+      for (int regno = V_REG_FIRST; regno <= V_REG_LAST; regno++)
+	call_used_regs[regno] = 1;
+	
+      fixed_regs[VTYPE_REGNUM] = call_used_regs[VTYPE_REGNUM] = 1;
+      fixed_regs[VL_REGNUM] = call_used_regs[VL_REGNUM] = 1;
+    }
 }
 
 /* Return a register priority for hard reg REGNO.  */
@@ -5903,6 +5921,9 @@  riscv_asan_shadow_offset (void)
 #undef TARGET_BUILTIN_DECL
 #define TARGET_BUILTIN_DECL riscv_builtin_decl
 
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN riscv_gimple_fold_builtin
+
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN riscv_expand_builtin
 
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index b5abf9c45d0..9b0da73f3b5 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -27,6 +27,42 @@  riscv-vector.o: $(srcdir)/config/riscv/riscv-vector.cc
 	$(COMPILE) $<
 	$(POSTCOMPILE)
 
+riscv-vector-builtins-functions.o: \
+  $(srcdir)/config/riscv/riscv-vector-builtins-functions.cc \
+  $(srcdir)/config/riscv/riscv-vector-builtins.def \
+  $(srcdir)/config/riscv/riscv-vector-builtins-functions.def \
+  $(srcdir)/config/riscv/vector-iterators.md \
+  $(srcdir)/config/riscv/md-parser  \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \
+  $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+  gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+  stor-layout.h $(REG_H) alias.h gimple-fold.h langhooks.h \
+  stringpool.h \
+  $(srcdir)/config/riscv/riscv-vector-builtins-functions.h
+	python3 $(srcdir)/config/riscv/md-parser \
+		riscv-vector-builtins-iterators.def vector-iterators.md && \
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/riscv/riscv-vector-builtins-functions.cc
+
+riscv-vector-builtins.o: \
+  $(srcdir)/config/riscv/riscv-vector-builtins.cc \
+  $(srcdir)/config/riscv/riscv-vector-builtins.def \
+  $(srcdir)/config/riscv/riscv-vector-builtins-functions.def \
+  $(srcdir)/config/riscv/vector-iterators.md \
+  $(srcdir)/config/riscv/md-parser  \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \
+  $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+  gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+  stor-layout.h $(REG_H) alias.h gimple-fold.h langhooks.h \
+  stringpool.h \
+  $(srcdir)/config/riscv/riscv-vector-builtins.h \
+  $(srcdir)/config/riscv/riscv-vector-builtins-functions.h \
+	riscv-vector-builtins-functions.o
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/riscv/riscv-vector-builtins.cc
+
 PASSES_EXTRA += $(srcdir)/config/riscv/riscv-passes.def
 
 $(common_out_file): $(srcdir)/config/riscv/riscv-cores.def \
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
new file mode 100644
index 00000000000..450e20c44ce
--- /dev/null
+++ b/gcc/config/riscv/vector-iterators.md
@@ -0,0 +1,19 @@ 
+;; Machine description for RISCV architecture.
+;; Copyright (C) 2022-2022 Free Software Foundation, Inc.
+;; Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
\ No newline at end of file