diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index 43f815156d8..e14a1854eee 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -239,6 +239,63 @@ public:
   }
 };
 
+/* Implements vwadd/vwsub/vwmul.  */
+template<rtx_code CODE1, rtx_code CODE2>
+class widen_binop : public function_base
+{
+public:
+  rtx expand (function_expander &e) const override
+  {
+    switch (e.op_info->op)
+      {
+      case OP_TYPE_vv:
+	return e.use_exact_insn (
+	  code_for_pred_dual_widen (CODE1, CODE2, e.vector_mode ()));
+      case OP_TYPE_vx:
+	return e.use_exact_insn (
+	  code_for_pred_dual_widen_scalar (CODE1, CODE2, e.vector_mode ()));
+      case OP_TYPE_wv:
+	return e.use_exact_insn (
+	  code_for_pred_single_widen (CODE1, CODE2, e.vector_mode ()));
+      case OP_TYPE_wx:
+	return e.use_exact_insn (
+	  code_for_pred_single_widen_scalar (CODE1, CODE2, e.vector_mode ()));
+      default:
+	gcc_unreachable ();
+      }
+  }
+};
+
+/* Implements vwmulsu.  */
+class vwmulsu : public function_base
+{
+public:
+  rtx expand (function_expander &e) const override
+  {
+    switch (e.op_info->op)
+      {
+      case OP_TYPE_vv:
+	return e.use_exact_insn (code_for_pred_widen_mulsu (e.vector_mode ()));
+      case OP_TYPE_vx:
+	return e.use_exact_insn (
+	  code_for_pred_widen_mulsu_scalar (e.vector_mode ()));
+      default:
+	gcc_unreachable ();
+      }
+  }
+};
+
+/* Implements vwcvt.  */
+template<rtx_code CODE>
+class vwcvt : public function_base
+{
+public:
+  rtx expand (function_expander &e) const override
+  {
+    return e.use_exact_insn (code_for_pred (CODE, e.vector_mode ()));
+  }
+};
+
 static CONSTEXPR const vsetvl<false> vsetvl_obj;
 static CONSTEXPR const vsetvl<true> vsetvlmax_obj;
 static CONSTEXPR const loadstore<false, LST_UNIT_STRIDE, false> vle_obj;
@@ -288,6 +345,15 @@ static CONSTEXPR const unop<NEG> vneg_obj;
 static CONSTEXPR const unop<NOT> vnot_obj;
 static CONSTEXPR const ext<SIGN_EXTEND> vsext_obj;
 static CONSTEXPR const ext<ZERO_EXTEND> vzext_obj;
+static CONSTEXPR const widen_binop<PLUS, SIGN_EXTEND>vwadd_obj;
+static CONSTEXPR const widen_binop<MINUS, SIGN_EXTEND>vwsub_obj;
+static CONSTEXPR const widen_binop<MULT, SIGN_EXTEND>vwmul_obj;
+static CONSTEXPR const widen_binop<PLUS, ZERO_EXTEND>vwaddu_obj;
+static CONSTEXPR const widen_binop<MINUS, ZERO_EXTEND>vwsubu_obj;
+static CONSTEXPR const widen_binop<MULT, ZERO_EXTEND>vwmulu_obj;
+static CONSTEXPR const vwmulsu vwmulsu_obj;
+static CONSTEXPR const vwcvt<SIGN_EXTEND> vwcvt_x_obj;
+static CONSTEXPR const vwcvt<ZERO_EXTEND> vwcvtu_x_obj;
 static CONSTEXPR const binop<SS_PLUS> vsadd_obj;
 static CONSTEXPR const binop<SS_MINUS> vssub_obj;
 static CONSTEXPR const binop<US_PLUS> vsaddu_obj;
@@ -347,6 +413,15 @@ BASE (vneg)
 BASE (vnot)
 BASE (vsext)
 BASE (vzext)
+BASE (vwadd)
+BASE (vwsub)
+BASE (vwmul)
+BASE (vwaddu)
+BASE (vwsubu)
+BASE (vwmulu)
+BASE (vwmulsu)
+BASE (vwcvt_x)
+BASE (vwcvtu_x)
 BASE (vsadd)
 BASE (vssub)
 BASE (vsaddu)
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h
index 96cfdd85659..51ec940a5aa 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.h
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.h
@@ -73,10 +73,20 @@ extern const function_base *const vneg;
 extern const function_base *const vnot;
 extern const function_base *const vsext;
 extern const function_base *const vzext;
+extern const function_base *const vwadd;
+extern const function_base *const vwsub;
+extern const function_base *const vwmul;
+extern const function_base *const vwaddu;
+extern const function_base *const vwsubu;
+extern const function_base *const vwmulu;
+extern const function_base *const vwmulsu;
+extern const function_base *const vwcvt_x;
+extern const function_base *const vwcvtu_x;
 extern const function_base *const vsadd;
 extern const function_base *const vssub;
 extern const function_base *const vsaddu;
 extern const function_base *const vssubu;
+
 }
 
 } // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def
index 418268f1279..e53fcb5546b 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -112,6 +112,30 @@ DEF_RVV_FUNCTION (vsext, alu, full_preds, i_vf8_ops)
 DEF_RVV_FUNCTION (vzext, alu, full_preds, u_vf2_ops)
 DEF_RVV_FUNCTION (vzext, alu, full_preds, u_vf4_ops)
 DEF_RVV_FUNCTION (vzext, alu, full_preds, u_vf8_ops)
+DEF_RVV_FUNCTION (vwadd, widen_alu, full_preds, i_wvv_ops)
+DEF_RVV_FUNCTION (vwsub, widen_alu, full_preds, i_wvv_ops)
+DEF_RVV_FUNCTION (vwmul, alu, full_preds, i_wvv_ops)
+DEF_RVV_FUNCTION (vwmulu, alu, full_preds, u_wvv_ops)
+DEF_RVV_FUNCTION (vwmulsu, alu, full_preds, i_su_wvv_ops)
+DEF_RVV_FUNCTION (vwaddu, widen_alu, full_preds, u_wvv_ops)
+DEF_RVV_FUNCTION (vwsubu, widen_alu, full_preds, u_wvv_ops)
+DEF_RVV_FUNCTION (vwadd, widen_alu, full_preds, i_wvx_ops)
+DEF_RVV_FUNCTION (vwsub, widen_alu, full_preds, i_wvx_ops)
+DEF_RVV_FUNCTION (vwmul, alu, full_preds, i_wvx_ops)
+DEF_RVV_FUNCTION (vwmulu, alu, full_preds, u_wvx_ops)
+DEF_RVV_FUNCTION (vwmulsu, alu, full_preds, i_su_wvx_ops)
+DEF_RVV_FUNCTION (vwaddu, widen_alu, full_preds, u_wvx_ops)
+DEF_RVV_FUNCTION (vwsubu, widen_alu, full_preds, u_wvx_ops)
+DEF_RVV_FUNCTION (vwadd, widen_alu, full_preds, i_wwv_ops)
+DEF_RVV_FUNCTION (vwsub, widen_alu, full_preds, i_wwv_ops)
+DEF_RVV_FUNCTION (vwaddu, widen_alu, full_preds, u_wwv_ops)
+DEF_RVV_FUNCTION (vwsubu, widen_alu, full_preds, u_wwv_ops)
+DEF_RVV_FUNCTION (vwadd, widen_alu, full_preds, i_wwx_ops)
+DEF_RVV_FUNCTION (vwsub, widen_alu, full_preds, i_wwx_ops)
+DEF_RVV_FUNCTION (vwaddu, widen_alu, full_preds, u_wwx_ops)
+DEF_RVV_FUNCTION (vwsubu, widen_alu, full_preds, u_wwx_ops)
+DEF_RVV_FUNCTION (vwcvt_x, alu, full_preds, i_x_x_v_ops)
+DEF_RVV_FUNCTION (vwcvtu_x, alu, full_preds, u_x_x_v_ops)
 /* 12. Vector Fixed-Point Arithmetic Instructions. */
 DEF_RVV_FUNCTION (vsadd, alu, full_preds, i_vvv_ops)
 DEF_RVV_FUNCTION (vssub, alu, full_preds, i_vvv_ops)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index e772a7ca475..62170f607ba 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -197,7 +197,8 @@ struct alu_def : public build_base
        API doesn't have OP suffix in overloaded function name, otherwise, we
        always append OP suffix in function name. For example, vsext_vf2.  */
     if (instance.op_info->op == OP_TYPE_vv || instance.op_info->op == OP_TYPE_vx
-	|| instance.op_info->op == OP_TYPE_v)
+	|| instance.op_info->op == OP_TYPE_v
+	|| instance.op_info->op == OP_TYPE_x_v)
       {
 	if (!overloaded_p)
 	  b.append_name (operand_suffixes[instance.op_info->op]);
@@ -218,10 +219,37 @@ struct alu_def : public build_base
   }
 };
 
+/* widen_alu_def class. Handle vwadd/vwsub. Unlike
+   vadd.vx/vadd.vv/vwmul.vv/vwmul.vx, vwadd.vv/vwadd.vx/vwadd.wv/vwadd.wx has
+   'OP' suffix in overloaded API.  */
+struct widen_alu_def : public build_base
+{
+  char *get_name (function_builder &b, const function_instance &instance,
+		  bool overloaded_p) const override
+  {
+    b.append_base_name (instance.base_name);
+
+    /* vop<sew> --> vop<sew>_<op>.  */
+    b.append_name (operand_suffixes[instance.op_info->op]);
+
+    /* vop<sew>_<op> --> vop<sew>_<op>_<type>.  */
+    if (!overloaded_p)
+      b.append_name (type_suffixes[instance.type.index].vector);
+
+    /* According to rvv-intrinsic-doc, it does not add "_m" suffix
+       for vop_m C++ overloaded API.  */
+    if (overloaded_p && instance.pred == PRED_TYPE_m)
+      return b.finish_name ();
+    b.append_name (predication_suffixes[instance.pred]);
+    return b.finish_name ();
+  }
+};
+
 SHAPE(vsetvl, vsetvl)
 SHAPE(vsetvl, vsetvlmax)
 SHAPE(loadstore, loadstore)
 SHAPE(indexed_loadstore, indexed_loadstore)
 SHAPE(alu, alu)
+SHAPE(widen_alu, widen_alu)
 
 } // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h b/gcc/config/riscv/riscv-vector-builtins-shapes.h
index b4f6eaa0bba..af5474ab36e 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
@@ -29,6 +29,7 @@ extern const function_shape *const vsetvlmax;
 extern const function_shape *const loadstore;
 extern const function_shape *const indexed_loadstore;
 extern const function_shape *const alu;
+extern const function_shape *const widen_alu;
 }
 
 } // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index 696864ce76d..8462c8cdc7d 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -341,6 +341,43 @@ static CONSTEXPR const rvv_arg_type_info vector_size_args[]
 static CONSTEXPR const rvv_arg_type_info vf2_args[]
   = {rvv_arg_type_info (RVV_BASE_double_trunc_vector), rvv_arg_type_info_end};
 
+/* A list of args for vector_type func (double demote type, double demote type)
+ * function.  */
+static CONSTEXPR const rvv_arg_type_info wvv_args[]
+  = {rvv_arg_type_info (RVV_BASE_double_trunc_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_vector), rvv_arg_type_info_end};
+
+/* A list of args for vector_type func (signed double demote type,
+ * unsigneddouble demote type) function.  */
+static CONSTEXPR const rvv_arg_type_info su_wvv_args[]
+  = {rvv_arg_type_info (RVV_BASE_double_trunc_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_unsigned_vector), rvv_arg_type_info_end};
+
+/* A list of args for vector_type func (double demote type, double demote type)
+ * function.  */
+static CONSTEXPR const rvv_arg_type_info wvx_args[]
+  = {rvv_arg_type_info (RVV_BASE_double_trunc_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_scalar), rvv_arg_type_info_end};
+
+/* A list of args for vector_type func (signed double demote type, unsigned
+ * double demote type) function.  */
+static CONSTEXPR const rvv_arg_type_info su_wvx_args[]
+  = {rvv_arg_type_info (RVV_BASE_double_trunc_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_unsigned_scalar),
+     rvv_arg_type_info_end};
+
+/* A list of args for vector_type func (double demote type, double demote type)
+ * function.  */
+static CONSTEXPR const rvv_arg_type_info wwv_args[]
+  = {rvv_arg_type_info (RVV_BASE_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_vector), rvv_arg_type_info_end};
+
+/* A list of args for vector_type func (double demote type, double demote type)
+ * function.  */
+static CONSTEXPR const rvv_arg_type_info wwx_args[]
+  = {rvv_arg_type_info (RVV_BASE_vector),
+     rvv_arg_type_info (RVV_BASE_double_trunc_scalar), rvv_arg_type_info_end};
+
 /* A list of args for vector_type func (quad demote type) function.  */
 static CONSTEXPR const rvv_arg_type_info vf4_args[]
   = {rvv_arg_type_info (RVV_BASE_quad_trunc_vector), rvv_arg_type_info_end};
@@ -349,6 +386,10 @@ static CONSTEXPR const rvv_arg_type_info vf4_args[]
 static CONSTEXPR const rvv_arg_type_info vf8_args[]
   = {rvv_arg_type_info (RVV_BASE_oct_trunc_vector), rvv_arg_type_info_end};
 
+/* A list of args for vector_type func (double demote type) function.  */
+static CONSTEXPR const rvv_arg_type_info x_x_v_args[]
+  = {rvv_arg_type_info (RVV_BASE_double_trunc_vector), rvv_arg_type_info_end};
+
 /* A list of none preds that will be registered for intrinsic functions.  */
 static CONSTEXPR const predication_type_index none_preds[]
   = {PRED_TYPE_none, NUM_PRED_TYPES};
@@ -658,6 +699,102 @@ static CONSTEXPR const rvv_op_info u_vf8_ops
      rvv_arg_type_info (RVV_BASE_vector), /* Return type */
      vf8_args /* Args */};
 
+/* A static operand information for vector_type func (double demote type, double
+ * demote type) function registration. */
+static CONSTEXPR const rvv_op_info i_wvv_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_vv,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wvv_args /* Args */};
+
+/* A static operand information for vector_type func (signed double demote type,
+ * unsigned double demote type) function registration. */
+static CONSTEXPR const rvv_op_info i_su_wvv_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_vv,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     su_wvv_args /* Args */};
+
+/* A static operand information for vector_type func (double demote type, double
+ * demote type) function registration. */
+static CONSTEXPR const rvv_op_info u_wvv_ops
+  = {wextu_ops,				  /* Types */
+     OP_TYPE_vv,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wvv_args /* Args */};
+
+/* A static operand information for vector_type func (double demote type, double
+ * demote scalar_type) function registration. */
+static CONSTEXPR const rvv_op_info i_wvx_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_vx,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wvx_args /* Args */};
+
+/* A static operand information for vector_type func (signed double demote type,
+ * unsigned double demote scalar_type) function registration. */
+static CONSTEXPR const rvv_op_info i_su_wvx_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_vx,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     su_wvx_args /* Args */};
+
+/* A static operand information for vector_type func (vector_type, double
+ * demote type) function registration. */
+static CONSTEXPR const rvv_op_info i_wwv_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_wv,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wwv_args /* Args */};
+
+/* A static operand information for vector_type func (vector_type, double
+ * demote scalar_type) function registration. */
+static CONSTEXPR const rvv_op_info i_wwx_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_wx,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wwx_args /* Args */};
+
+/* A static operand information for vector_type func (vector_type, double
+ * demote type) function registration. */
+static CONSTEXPR const rvv_op_info u_wwv_ops
+  = {wextu_ops,				  /* Types */
+     OP_TYPE_wv,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wwv_args /* Args */};
+
+/* A static operand information for vector_type func (vector_type, double
+ * demote scalar_type) function registration. */
+static CONSTEXPR const rvv_op_info u_wwx_ops
+  = {wextu_ops,				  /* Types */
+     OP_TYPE_wx,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wwx_args /* Args */};
+
+/* A static operand information for vector_type func (double demote type, double
+ * demote scalar_type) function registration. */
+static CONSTEXPR const rvv_op_info u_wvx_ops
+  = {wextu_ops,				  /* Types */
+     OP_TYPE_vx,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     wvx_args /* Args */};
+
+/* A static operand information for vector_type func (double demote type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info i_x_x_v_ops
+  = {wexti_ops,				  /* Types */
+     OP_TYPE_x_v,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     x_x_v_args /* Args */};
+
+/* A static operand information for vector_type func (unsigned double demote
+ * type) function registration. */
+static CONSTEXPR const rvv_op_info u_x_x_v_ops
+  = {wextu_ops,				  /* Types */
+     OP_TYPE_x_v,			  /* Suffix */
+     rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+     x_x_v_args /* Args */};
+
 /* A list of all RVV intrinsic functions.  */
 static function_group_info function_groups[] = {
 #define DEF_RVV_FUNCTION(NAME, SHAPE, PREDS, OPS_INFO)                         \
@@ -944,6 +1081,9 @@ rvv_arg_type_info::get_base_vector_type (tree type) const
   poly_int64 nunits = GET_MODE_NUNITS (TYPE_MODE (type));
   machine_mode inner_mode = GET_MODE_INNER (TYPE_MODE (type));
   bool unsigned_p = TYPE_UNSIGNED (type);
+  if (base_type == RVV_BASE_double_trunc_unsigned_vector
+      || base_type == RVV_BASE_double_trunc_unsigned_scalar)
+    unsigned_p = true;
   switch (base_type)
     {
     case RVV_BASE_uint8_index:
@@ -967,6 +1107,9 @@ rvv_arg_type_info::get_base_vector_type (tree type) const
       unsigned_p = true;
       break;
     case RVV_BASE_double_trunc_vector:
+    case RVV_BASE_double_trunc_scalar:
+    case RVV_BASE_double_trunc_unsigned_vector:
+    case RVV_BASE_double_trunc_unsigned_scalar:
       if (inner_mode == DImode)
         inner_mode = SImode;
       else if (inner_mode == SImode)
@@ -1073,11 +1216,19 @@ rvv_arg_type_info::get_tree_type (vector_type_index type_idx) const
     case RVV_BASE_double_trunc_vector:
     case RVV_BASE_quad_trunc_vector:
     case RVV_BASE_oct_trunc_vector:
+    case RVV_BASE_double_trunc_unsigned_vector:
       if (get_base_vector_type (builtin_types[type_idx].vector)
 	  != NUM_VECTOR_TYPES)
 	return builtin_types[get_base_vector_type (
 			       builtin_types[type_idx].vector)].vector;
       break;
+    case RVV_BASE_double_trunc_scalar:
+    case RVV_BASE_double_trunc_unsigned_scalar:
+      if (get_base_vector_type (builtin_types[type_idx].vector)
+	  != NUM_VECTOR_TYPES)
+	return builtin_types[get_base_vector_type (
+			       builtin_types[type_idx].vector)].scalar;
+      break;
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/config/riscv/riscv-vector-builtins.def b/gcc/config/riscv/riscv-vector-builtins.def
index 89bd5f13995..9f4cd011404 100644
--- a/gcc/config/riscv/riscv-vector-builtins.def
+++ b/gcc/config/riscv/riscv-vector-builtins.def
@@ -273,7 +273,7 @@ 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 (x_v)
 DEF_RVV_OP_TYPE (vf2)
 DEF_RVV_OP_TYPE (vf4)
 DEF_RVV_OP_TYPE (vf8)
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
index fc9d405784c..d033a2ea83f 100644
--- a/gcc/config/riscv/riscv-vector-builtins.h
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -158,6 +158,9 @@ enum rvv_base_type
   RVV_BASE_double_trunc_vector,
   RVV_BASE_quad_trunc_vector,
   RVV_BASE_oct_trunc_vector,
+  RVV_BASE_double_trunc_scalar,
+  RVV_BASE_double_trunc_unsigned_vector,
+  RVV_BASE_double_trunc_unsigned_scalar,
   NUM_BASE_TYPES
 };
 
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 8e6063ae83b..77c62e2d8f3 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -961,6 +961,46 @@ change_insn (function_info *ssa, insn_change change, insn_info *insn,
   /* These routines report failures themselves.  */
   if (!recog (attempt, change) || !change_is_worthwhile (change, false))
     return false;
+
+  /* Fix bug:
+      (insn 12 34 13 2 (set (reg:VNx8DI 120 v24 [orig:134 _1 ] [134])
+	(if_then_else:VNx8DI (unspec:VNx8BI [
+		    (const_vector:VNx8BI repeat [
+			    (const_int 1 [0x1])
+			])
+		    (const_int 0 [0])
+		    (const_int 2 [0x2]) repeated x2
+		    (const_int 0 [0])
+		    (reg:SI 66 vl)
+		    (reg:SI 67 vtype)
+		] UNSPEC_VPREDICATE)
+	    (plus:VNx8DI (reg/v:VNx8DI 104 v8 [orig:137 op1 ] [137])
+		(sign_extend:VNx8DI (vec_duplicate:VNx8SI (reg:SI 15 a5
+    [140])))) (unspec:VNx8DI [ (const_int 0 [0]) ] UNSPEC_VUNDEF))) "rvv.c":8:12
+    2784 {pred_single_widen_addsvnx8di_scalar} (expr_list:REG_EQUIV
+    (mem/c:VNx8DI (reg:DI 10 a0 [142]) [1 <retval>+0 S[64, 64] A128])
+	(expr_list:REG_EQUAL (if_then_else:VNx8DI (unspec:VNx8BI [
+			(const_vector:VNx8BI repeat [
+				(const_int 1 [0x1])
+			    ])
+			(reg/v:DI 13 a3 [orig:139 vl ] [139])
+			(const_int 2 [0x2]) repeated x2
+			(const_int 0 [0])
+			(reg:SI 66 vl)
+			(reg:SI 67 vtype)
+		    ] UNSPEC_VPREDICATE)
+		(plus:VNx8DI (reg/v:VNx8DI 104 v8 [orig:137 op1 ] [137])
+		    (const_vector:VNx8DI repeat [
+			    (const_int 2730 [0xaaa])
+			]))
+		(unspec:VNx8DI [
+			(const_int 0 [0])
+		    ] UNSPEC_VUNDEF))
+	    (nil))))
+    Here we want to remove use "a3". However, the REG_EQUAL/REG_EQUIV note use
+    "a3" which made us fail in change_insn.  We reference to the
+    'aarch64-cc-fusion.cc' and add this method.  */
+  remove_reg_equal_equiv_notes (rinsn);
   confirm_change_group ();
   ssa->change_insn (change);
 
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index daf30f5502d..ce401528511 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -651,9 +651,6 @@ enum reg_class
 #define FP_ARG_FIRST (FP_REG_FIRST + 10)
 #define FP_ARG_LAST  (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
 
-/* Helper macro for RVV vsetvl instruction generation.  */
-#define X0_REGNUM GP_REG_FIRST
-
 #define CALLEE_SAVED_REG_NUMBER(REGNO)			\
   ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 :		\
    (REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1)
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 7f5de072215..cef9832d583 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -280,6 +280,9 @@
 (define_code_iterator sat_int_plus_binop [ss_plus us_plus])
 (define_code_iterator sat_int_minus_binop [ss_minus us_minus])
 
+(define_code_iterator any_widen_binop [plus minus mult])
+(define_code_iterator plus_minus [plus minus])
+
 (define_code_attr binop_rhs1_predicate [
 			(plus "register_operand")
 			(minus "vector_arith_operand")
@@ -391,6 +394,11 @@
 			(ss_minus "vsalu")
 			(us_minus "vsalu")])
 
+(define_code_attr widen_binop_insn_type [
+			(plus "walu")
+			(minus "walu")
+			(mult "wmul")])
+
 ;; <binop_vi_variant_insn> expands to the insn name of binop matching constraint rhs1 is immediate.
 ;; minus is negated as vadd and ss_minus is negated as vsadd, others remain <insn>.
 (define_code_attr binop_vi_variant_insn [(ashift "sll.vi")
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 40a0bbea71a..ec177fa7efb 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -30,6 +30,7 @@
 
 (define_constants [
    (INVALID_ATTRIBUTE            255)
+   (X0_REGNUM                      0)
 ])
 
 ;; True if the type is RVV instructions that include VTYPE
@@ -142,7 +143,7 @@
 ;; It is valid for instruction that require sew/lmul ratio.
 (define_attr "ratio" ""
   (cond [(eq_attr "type" "vimov,vfmov,vldux,vldox,vstux,vstox,\
-			  vialu,vshift,vicmp,vimul,vidiv,vsalu,vext")
+			  vialu,vshift,vicmp,vimul,vidiv,vsalu,vext,viwalu,viwmul")
 	   (const_int INVALID_ATTRIBUTE)
 	 (eq_attr "mode" "VNx1QI,VNx1BI")
 	   (symbol_ref "riscv_vector::get_ratio(E_VNx1QImode)")
@@ -193,7 +194,7 @@
 ;; The index of operand[] to get the merge op.
 (define_attr "merge_op_idx" ""
 	(cond [(eq_attr "type" "vlde,vimov,vfmov,vldm,vlds,vmalu,vldux,vldox,\
-				vialu,vshift,vicmp,vimul,vidiv,vsalu,vext")
+				vialu,vshift,vicmp,vimul,vidiv,vsalu,vext,viwalu,viwmul")
 	 (const_int 2)]
 	(const_int INVALID_ATTRIBUTE)))
 
@@ -210,7 +211,8 @@
              (const_int 5)
              (const_int 4))
 
-	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu")
+	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\
+			  viwalu,viwmul")
 	   (const_int 5)]
   (const_int INVALID_ATTRIBUTE)))
 
@@ -226,7 +228,8 @@
 	     (symbol_ref "riscv_vector::get_ta(operands[6])")
 	     (symbol_ref "riscv_vector::get_ta(operands[5])"))
 
-	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu")
+	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\
+			  viwalu,viwmul")
 	   (symbol_ref "riscv_vector::get_ta(operands[6])")]
 	(const_int INVALID_ATTRIBUTE)))
 
@@ -242,7 +245,8 @@
 	     (symbol_ref "riscv_vector::get_ma(operands[7])")
 	     (symbol_ref "riscv_vector::get_ma(operands[6])"))
 
-	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu")
+	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\
+			  viwalu,viwmul")
 	   (symbol_ref "riscv_vector::get_ma(operands[7])")]
 	(const_int INVALID_ATTRIBUTE)))
 
@@ -260,7 +264,8 @@
 	     (const_int INVALID_ATTRIBUTE)
 	     (symbol_ref "INTVAL (operands[7])"))
 
-	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu")
+	 (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\
+			  viwalu,viwmul")
 	   (symbol_ref "INTVAL (operands[8])")
 	 (eq_attr "type" "vstux,vstox")
 	   (symbol_ref "INTVAL (operands[5])")]
@@ -670,6 +675,26 @@
 ;;                (const_int:QI N)]), -15 <= N < 16.
 ;;    2. (const_vector:VNx1SF repeat [
 ;;                (const_double:SF 0.0 [0x0.0p+0])]).
+
+;; We add "MEM_P (operands[0]) || MEM_P (operands[3]) || CONST_VECTOR_P (operands[1])" here to
+;; make sure we don't want CSE to generate the following pattern:
+;; (insn 17 8 19 2 (set (reg:VNx1HI 134 [ _1 ])
+;;       (if_then_else:VNx1HI (unspec:VNx1BI [
+;;                   (reg/v:VNx1BI 137 [ mask ])
+;;                   (reg:DI 151)
+;;                   (const_int 0 [0]) repeated x3
+;;                   (reg:SI 66 vl)
+;;                   (reg:SI 67 vtype)
+;;               ] UNSPEC_VPREDICATE)
+;;           (const_vector:VNx1HI repeat [
+;;                   (const_int 0 [0])
+;;               ])
+;;           (reg/v:VNx1HI 140 [ merge ]))) "rvv.c":8:12 608 {pred_movvnx1hi}
+;;    (expr_list:REG_DEAD (reg:DI 151)
+;;       (expr_list:REG_DEAD (reg/v:VNx1HI 140 [ merge ])
+;;           (expr_list:REG_DEAD (reg/v:VNx1BI 137 [ mask ])
+;;               (nil)))))
+;; Since both vmv.v.v and vmv.v.i doesn't have mask operand.
 (define_insn_and_split "@pred_mov<mode>"
   [(set (match_operand:V 0 "nonimmediate_operand"      "=vr,    vr,    vd,     m,    vr,    vr")
     (if_then_else:V
@@ -683,7 +708,8 @@
          (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
       (match_operand:V 3 "vector_move_operand"       "    m,     m,     m,    vr,    vr, viWc0")
       (match_operand:V 2 "vector_merge_operand"      "    0,    vu,    vu,    vu,   vu0,   vu0")))]
-  "TARGET_VECTOR"
+  "TARGET_VECTOR && (MEM_P (operands[0]) || MEM_P (operands[3]) 
+   || CONST_VECTOR_P (operands[1]))"
   "@
    vle<sew>.v\t%0,%3%p1
    vle<sew>.v\t%0,%3
@@ -1930,14 +1956,16 @@
    (set_attr "mode" "<MODE>")
    (set_attr "vl_op_idx" "4")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[5])"))
-   (set (attr "ma") (symbol_ref "riscv_vector::get_ta(operands[6])"))
+   (set (attr "ma") (symbol_ref "riscv_vector::get_ma(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
 
 ;; -------------------------------------------------------------------------------
 ;; ---- Predicated integer widening operations
 ;; -------------------------------------------------------------------------------
 ;; Includes:
+;; - 11.2 Vector Widening Integer Add/Subtract
 ;; - 11.3 Vector Integer Extension
+;; - 11.12 Vector Widening Integer Multiply Instructions
 ;; -------------------------------------------------------------------------------
 
 ;; Vector Double-Widening Sign-extend and Zero-extend.
@@ -1999,3 +2027,164 @@
   "v<sz>ext.vf8\t%0,%3%p1"
   [(set_attr "type" "vext")
    (set_attr "mode" "<MODE>")])
+
+;; Vector Widening Add/Subtract/Multiply.
+(define_insn "@pred_dual_widen_<any_widen_binop:optab><any_extend:su><mode>"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (any_widen_binop:VWEXTI
+	    (any_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr"))
+	    (any_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" "   vr")))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vw<any_widen_binop:insn><any_extend:u>.vv\t%0,%3,%4%p1"
+  [(set_attr "type" "vi<widen_binop_insn_type>")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_dual_widen_<any_widen_binop:optab><any_extend:su><mode>_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (any_widen_binop:VWEXTI
+	    (any_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr"))
+	    (any_extend:VWEXTI
+	      (vec_duplicate:<V_DOUBLE_TRUNC>
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ"))))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vw<any_widen_binop:insn><any_extend:u>.vx\t%0,%3,%z4%p1"
+  [(set_attr "type" "vi<widen_binop_insn_type>")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (plus_minus:VWEXTI
+	    (match_operand:VWEXTI 3 "register_operand"             "   vr")
+	    (any_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" "   vr")))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vw<plus_minus:insn><any_extend:u>.wv\t%0,%3,%4%p1"
+  [(set_attr "type" "vi<widen_binop_insn_type>")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_single_widen_<plus_minus:optab><any_extend:su><mode>_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (plus_minus:VWEXTI
+	    (match_operand:VWEXTI 3 "register_operand"             "   vr")
+	    (any_extend:VWEXTI
+	      (vec_duplicate:<V_DOUBLE_TRUNC>
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ"))))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vw<plus_minus:insn><any_extend:u>.wx\t%0,%3,%z4%p1"
+  [(set_attr "type" "vi<widen_binop_insn_type>")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_widen_mulsu<mode>"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (mult:VWEXTI
+	    (sign_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr"))
+	    (zero_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand" "   vr")))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vwmulsu.vv\t%0,%3,%4%p1"
+  [(set_attr "type" "viwmul")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+(define_insn "@pred_widen_mulsu<mode>_scalar"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 5 "vector_length_operand"              "   rK")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (match_operand 8 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (mult:VWEXTI
+	    (sign_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr"))
+	    (zero_extend:VWEXTI
+	      (vec_duplicate:<V_DOUBLE_TRUNC>
+		(match_operand:<VSUBEL> 4 "reg_or_0_operand"       "   rJ"))))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vwmulsu.vx\t%0,%3,%z4%p1"
+  [(set_attr "type" "viwmul")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")])
+
+;; vwcvt<u>.x.x.v
+(define_insn "@pred_<optab><mode>"
+  [(set (match_operand:VWEXTI 0 "register_operand"                  "=&vr")
+	(if_then_else:VWEXTI
+	  (unspec:<VM>
+	    [(match_operand:<VM> 1 "vector_mask_operand"           "vmWc1")
+	     (match_operand 4 "vector_length_operand"              "   rK")
+	     (match_operand 5 "const_int_operand"                  "    i")
+	     (match_operand 6 "const_int_operand"                  "    i")
+	     (match_operand 7 "const_int_operand"                  "    i")
+	     (reg:SI VL_REGNUM)
+	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+	  (plus:VWEXTI
+	    (any_extend:VWEXTI
+	      (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand" "   vr"))
+	    (vec_duplicate:VWEXTI
+	      (reg:<VEL> X0_REGNUM)))
+	  (match_operand:VWEXTI 2 "vector_merge_operand"           "  0vu")))]
+  "TARGET_VECTOR"
+  "vwcvt<u>.x.x.v\t%0,%3%p1"
+  [(set_attr "type" "viwalu")
+   (set_attr "mode" "<V_DOUBLE_TRUNC>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[5])"))
+   (set (attr "ma") (symbol_ref "riscv_vector::get_ma(operands[6])"))
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
