RISC-V: Add vmadc/vmsbc C/C++ API support
authorJu-Zhe Zhong <juzhe.zhong@rivai.ai>
Wed, 8 Feb 2023 20:52:36 +0000 (04:52 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Sun, 12 Feb 2023 07:14:35 +0000 (15:14 +0800)
gcc/ChangeLog:

* config/riscv/riscv-vector-builtins-bases.cc (class vmadc): New class.
(class vmsbc): Ditto.
(BASE): Define new class.
* config/riscv/riscv-vector-builtins-bases.h: Ditto.
* config/riscv/riscv-vector-builtins-functions.def (vmadc): New define.
(vmsbc): Ditto.
* config/riscv/riscv-vector-builtins-shapes.cc (struct return_mask_def):
New class.
(SHAPE): Ditto.
* config/riscv/riscv-vector-builtins-shapes.h: Ditto.
* config/riscv/riscv-vector-builtins.cc
(function_expander::use_exact_insn): Adjust for new support
* config/riscv/riscv-vector-builtins.h
(function_base::has_merge_operand_p): New function.
* config/riscv/vector-iterators.md: New iterator.
* config/riscv/vector.md (@pred_madc<mode>): New pattern.
(@pred_msbc<mode>): Ditto.
(@pred_madc<mode>_scalar): Ditto.
(@pred_msbc<mode>_scalar): Ditto.
(*pred_madc<mode>_scalar): Ditto.
(*pred_madc<mode>_extended_scalar): Ditto.
(*pred_msbc<mode>_scalar): Ditto.
(*pred_msbc<mode>_extended_scalar): Ditto.
(@pred_madc<mode>_overflow): Ditto.
(@pred_msbc<mode>_overflow): Ditto.
(@pred_madc<mode>_overflow_scalar): Ditto.
(@pred_msbc<mode>_overflow_scalar): Ditto.
(*pred_madc<mode>_overflow_scalar): Ditto.
(*pred_madc<mode>_overflow_extended_scalar): Ditto.
(*pred_msbc<mode>_overflow_scalar): Ditto.
(*pred_msbc<mode>_overflow_extended_scalar): Ditto.

gcc/config/riscv/riscv-vector-builtins-bases.cc
gcc/config/riscv/riscv-vector-builtins-bases.h
gcc/config/riscv/riscv-vector-builtins-functions.def
gcc/config/riscv/riscv-vector-builtins-shapes.cc
gcc/config/riscv/riscv-vector-builtins-shapes.h
gcc/config/riscv/riscv-vector-builtins.cc
gcc/config/riscv/riscv-vector-builtins.h
gcc/config/riscv/vector-iterators.md
gcc/config/riscv/vector.md

index 8bf5bb9..bcf2dfe 100644 (file)
@@ -338,6 +338,64 @@ public:
   }
 };
 
+/* Implements vmadc.  */
+class vmadc : public function_base
+{
+public:
+  bool apply_tail_policy_p () const override { return false; }
+  bool apply_mask_policy_p () const override { return false; }
+  bool use_mask_predication_p () const override { return false; }
+  bool has_merge_operand_p () const override { return false; }
+
+  rtx expand (function_expander &e) const override
+  {
+    switch (e.op_info->op)
+      {
+      case OP_TYPE_vvm:
+       return e.use_exact_insn (code_for_pred_madc (e.vector_mode ()));
+      case OP_TYPE_vxm:
+       return e.use_exact_insn (code_for_pred_madc_scalar (e.vector_mode ()));
+      case OP_TYPE_vv:
+       return e.use_exact_insn (
+         code_for_pred_madc_overflow (e.vector_mode ()));
+      case OP_TYPE_vx:
+       return e.use_exact_insn (
+         code_for_pred_madc_overflow_scalar (e.vector_mode ()));
+      default:
+       gcc_unreachable ();
+      }
+  }
+};
+
+/* Implements vmsbc.  */
+class vmsbc : public function_base
+{
+public:
+  bool apply_tail_policy_p () const override { return false; }
+  bool apply_mask_policy_p () const override { return false; }
+  bool use_mask_predication_p () const override { return false; }
+  bool has_merge_operand_p () const override { return false; }
+
+  rtx expand (function_expander &e) const override
+  {
+    switch (e.op_info->op)
+      {
+      case OP_TYPE_vvm:
+       return e.use_exact_insn (code_for_pred_msbc (e.vector_mode ()));
+      case OP_TYPE_vxm:
+       return e.use_exact_insn (code_for_pred_msbc_scalar (e.vector_mode ()));
+      case OP_TYPE_vv:
+       return e.use_exact_insn (
+         code_for_pred_msbc_overflow (e.vector_mode ()));
+      case OP_TYPE_vx:
+       return e.use_exact_insn (
+         code_for_pred_msbc_overflow_scalar (e.vector_mode ()));
+      default:
+       gcc_unreachable ();
+      }
+  }
+};
+
 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;
@@ -398,6 +456,8 @@ static CONSTEXPR const vwcvt<SIGN_EXTEND> vwcvt_x_obj;
 static CONSTEXPR const vwcvt<ZERO_EXTEND> vwcvtu_x_obj;
 static CONSTEXPR const vadc vadc_obj;
 static CONSTEXPR const vsbc vsbc_obj;
+static CONSTEXPR const vmadc vmadc_obj;
+static CONSTEXPR const vmsbc vmsbc_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;
@@ -468,6 +528,8 @@ BASE (vwcvt_x)
 BASE (vwcvtu_x)
 BASE (vadc)
 BASE (vsbc)
+BASE (vmadc)
+BASE (vmsbc)
 BASE (vsadd)
 BASE (vssub)
 BASE (vsaddu)
index 729c069..6a8747b 100644 (file)
@@ -84,6 +84,8 @@ extern const function_base *const vwcvt_x;
 extern const function_base *const vwcvtu_x;
 extern const function_base *const vadc;
 extern const function_base *const vsbc;
+extern const function_base *const vmadc;
+extern const function_base *const vmsbc;
 extern const function_base *const vsadd;
 extern const function_base *const vssub;
 extern const function_base *const vsaddu;
index 3d8db35..6d32853 100644 (file)
@@ -140,6 +140,14 @@ DEF_RVV_FUNCTION (vadc, no_mask_policy, tu_preds, iu_vvvm_ops)
 DEF_RVV_FUNCTION (vsbc, no_mask_policy, tu_preds, iu_vvvm_ops)
 DEF_RVV_FUNCTION (vadc, no_mask_policy, tu_preds, iu_vvxm_ops)
 DEF_RVV_FUNCTION (vsbc, no_mask_policy, tu_preds, iu_vvxm_ops)
+DEF_RVV_FUNCTION (vmadc, return_mask, none_preds, iu_mvvm_ops)
+DEF_RVV_FUNCTION (vmsbc, return_mask, none_preds, iu_mvvm_ops)
+DEF_RVV_FUNCTION (vmadc, return_mask, none_preds, iu_mvxm_ops)
+DEF_RVV_FUNCTION (vmsbc, return_mask, none_preds, iu_mvxm_ops)
+DEF_RVV_FUNCTION (vmadc, return_mask, none_preds, iu_mvv_ops)
+DEF_RVV_FUNCTION (vmsbc, return_mask, none_preds, iu_mvv_ops)
+DEF_RVV_FUNCTION (vmadc, return_mask, none_preds, iu_mvx_ops)
+DEF_RVV_FUNCTION (vmsbc, return_mask, none_preds, iu_mvx_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)
index 9187007..dae515c 100644 (file)
@@ -266,6 +266,33 @@ struct no_mask_policy_def : public build_base
   }
 };
 
+/* return_mask_def class. Such instructions belong to this class
+   is returning mask value.  */
+struct return_mask_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);
+
+    if (!overloaded_p)
+      b.append_name (operand_suffixes[instance.op_info->op]);
+
+    /* vop<sew>_<op> --> vop<sew>_<op>_<type1>_<type2>.  */
+    if (!overloaded_p)
+      {
+       b.append_name (type_suffixes[instance.type.index].vector);
+       vector_type_index ret_type_idx
+         = instance.op_info->ret.get_base_vector_type (
+           builtin_types[instance.type.index].vector);
+       b.append_name (type_suffixes[ret_type_idx].vector);
+      }
+
+    b.append_name (predication_suffixes[instance.pred]);
+    return b.finish_name ();
+  }
+};
+
 SHAPE(vsetvl, vsetvl)
 SHAPE(vsetvl, vsetvlmax)
 SHAPE(loadstore, loadstore)
@@ -273,5 +300,6 @@ SHAPE(indexed_loadstore, indexed_loadstore)
 SHAPE(alu, alu)
 SHAPE(widen_alu, widen_alu)
 SHAPE(no_mask_policy, no_mask_policy)
+SHAPE(return_mask, return_mask)
 
 } // end namespace riscv_vector
index 6aadde3..783b471 100644 (file)
@@ -31,6 +31,7 @@ extern const function_shape *const indexed_loadstore;
 extern const function_shape *const alu;
 extern const function_shape *const widen_alu;
 extern const function_shape *const no_mask_policy;
+extern const function_shape *const return_mask;
 }
 
 } // end namespace riscv_vector
index 0036c81..ce62bae 100644 (file)
@@ -570,6 +570,38 @@ static CONSTEXPR const rvv_op_info iu_vvxm_ops
      rvv_arg_type_info (RVV_BASE_vector), /* Return type */
      vxm_args /* Args */};
 
+/* A static operand information for mask_type func (vector_type, vector_type,
+ * mask_type) function registration. */
+static CONSTEXPR const rvv_op_info iu_mvvm_ops
+  = {iu_ops,                             /* Types */
+     OP_TYPE_vvm,                        /* Suffix */
+     rvv_arg_type_info (RVV_BASE_mask), /* Return type */
+     vvm_args /* Args */};
+
+/* A static operand information for mask_type func (vector_type, scalar_type,
+ * mask_type) function registration. */
+static CONSTEXPR const rvv_op_info iu_mvxm_ops
+  = {iu_ops,                             /* Types */
+     OP_TYPE_vxm,                        /* Suffix */
+     rvv_arg_type_info (RVV_BASE_mask), /* Return type */
+     vxm_args /* Args */};
+
+/* A static operand information for mask_type func (vector_type, vector_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info iu_mvv_ops
+  = {iu_ops,                           /* Types */
+     OP_TYPE_vv,                       /* Suffix */
+     rvv_arg_type_info (RVV_BASE_mask), /* Return type */
+     vv_args /* Args */};
+
+/* A static operand information for mask_type func (vector_type, scalar_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info iu_mvx_ops
+  = {iu_ops,                           /* Types */
+     OP_TYPE_vx,                       /* Suffix */
+     rvv_arg_type_info (RVV_BASE_mask), /* Return type */
+     vx_args /* Args */};
+
 /* A static operand information for vector_type func (vector_type, vector_type)
  * function registration. */
 static CONSTEXPR const rvv_op_info i_vvv_ops
@@ -1670,7 +1702,7 @@ function_expander::use_exact_insn (insn_code icode)
     }
 
   /* Store operation doesn't have merge operand.  */
-  if (!function_returns_void_p ())
+  if (!function_returns_void_p () && base->has_merge_operand_p ())
     {
       if (use_real_merge_p (pred))
        add_input_operand (arg_offset++);
index 4f78c29..f00b2c5 100644 (file)
@@ -388,6 +388,9 @@ public:
   /* Return true if intrinsics use mask predication.  */
   virtual bool use_mask_predication_p () const;
 
+  /* Return true if intrinsics has merge operand.  */
+  virtual bool has_merge_operand_p () const;
+
   /* Expand the given call into rtl.  Return the result of the function,
      or an arbitrary value if the function doesn't return a result.  */
   virtual rtx expand (function_expander &) const = 0;
@@ -521,6 +524,14 @@ function_base::use_mask_predication_p () const
   return true;
 }
 
+/* We choose to return true by default since most of the intrinsics use
+   has merge operand.  */
+inline bool
+function_base::has_merge_operand_p () const
+{
+  return true;
+}
+
 /* Since most of intrinsics can be overloaded, we set it true by default.  */
 inline bool
 function_base::can_be_overloaded_p (enum predication_type_index) const
index c3f3f1b..6b255c4 100644 (file)
@@ -36,6 +36,9 @@
 
   UNSPEC_VADC
   UNSPEC_VSBC
+  UNSPEC_VMADC
+  UNSPEC_VMSBC
+  UNSPEC_OVERFLOW
 ])
 
 (define_mode_iterator V [
index 3cd87f8..b3f8c05 100644 (file)
    vadc.vim\t%0,%2,%v3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vsbc.vvm\t%0,%2,%3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vadc.vxm\t%0,%2,%3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vsbc.vxm\t%0,%2,%z3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vadc.vxm\t%0,%2,%3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vadc.vxm\t%0,%2,%3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vsbc.vxm\t%0,%2,%z3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
   "vsbc.vxm\t%0,%2,%z3,%4"
   [(set_attr "type" "vicalu")
    (set_attr "mode" "<MODE>")
+   (set_attr "merge_op_idx" "1")
    (set_attr "vl_op_idx" "5")
    (set (attr "ta") (symbol_ref "riscv_vector::get_ta(operands[6])"))
    (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))])
 
+(define_insn "@pred_madc<mode>"
+  [(set (match_operand:<VM> 0 "register_operand"        "=&vr, &vr")
+       (unspec:<VM>
+          [(plus:VI
+            (match_operand:VI 1 "register_operand"     "  vr,  vr")
+            (match_operand:VI 2 "vector_arith_operand" "  vr,  vi"))
+           (match_operand:<VM> 3 "register_operand"    "  vm,  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand" "  rK,  rK")
+              (match_operand 5 "const_int_operand"     "   i,   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
+  "TARGET_VECTOR"
+  "@
+   vmadc.vvm\t%0,%1,%2,%3
+   vmadc.vim\t%0,%1,%v2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "@pred_msbc<mode>"
+  [(set (match_operand:<VM> 0 "register_operand"        "=&vr")
+       (unspec:<VM>
+          [(minus:VI
+            (match_operand:VI 1 "register_operand"     "  vr")
+            (match_operand:VI 2 "register_operand"     "  vr"))
+           (match_operand:<VM> 3 "register_operand"    "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand" "  rK")
+              (match_operand 5 "const_int_operand"     "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
+  "TARGET_VECTOR"
+  "vmsbc.vvm\t%0,%1,%2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "@pred_madc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(plus:VI_QHS
+            (vec_duplicate:VI_QHS
+              (match_operand:<VEL> 2 "register_operand" "   r"))
+            (match_operand:VI_QHS 1 "register_operand"  "  vr"))
+           (match_operand:<VM> 3 "register_operand"     "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"  "  rK")
+              (match_operand 5 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
+  "TARGET_VECTOR"
+  "vmadc.vxm\t%0,%1,%2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "@pred_msbc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(minus:VI_QHS
+            (vec_duplicate:VI_QHS
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
+            (match_operand:VI_QHS 1 "register_operand"  "  vr"))
+           (match_operand:<VM> 3 "register_operand"     "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"  "  rK")
+              (match_operand 5 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
+  "TARGET_VECTOR"
+  "vmsbc.vxm\t%0,%1,%z2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_expand "@pred_madc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_int_operand"))
+            (match_operand:VI_D 1 "register_operand"))
+           (match_operand:<VM> 3 "register_operand")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand")
+              (match_operand 5 "const_int_operand")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
+  "TARGET_VECTOR"
+  {
+    if (riscv_vector::simm5_p (operands[2]))
+      operands[2] = force_reg (<VEL>mode, operands[2]);
+    else if (!TARGET_64BIT)
+      {
+       rtx v = gen_reg_rtx (<MODE>mode);
+
+       if (riscv_vector::simm32_p (operands[2]))
+         operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode,
+               force_reg (Pmode, operands[2]));
+       else
+         {
+           if (CONST_INT_P (operands[2]))
+             operands[2] = force_reg (<VEL>mode, operands[2]);
+
+           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+                                           v, operands[2], operands[5],
+                                           <VM>mode);
+           emit_insn (gen_pred_madc<mode> (operands[0], operands[1], v, operands[3],
+                                           operands[4], operands[5]));
+           DONE;
+         }
+      }
+    else
+      operands[2] = force_reg (<VEL>mode, operands[2]);
+  })
+
+(define_insn "*pred_madc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "register_operand" "   r"))
+            (match_operand:VI_D 1 "register_operand"    "  vr"))
+           (match_operand:<VM> 3 "register_operand"     "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"  "  rK")
+              (match_operand 5 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
+  "TARGET_VECTOR"
+  "vmadc.vxm\t%0,%1,%2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "*pred_madc<mode>_extended_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"             "=&vr")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (sign_extend:<VEL>
+                (match_operand:<VSUBEL> 2 "register_operand" "   r")))
+            (match_operand:VI_D 1 "register_operand"         "  vr"))
+           (match_operand:<VM> 3 "register_operand"          "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"       "  rK")
+              (match_operand 5 "const_int_operand"           "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMADC))]
+  "TARGET_VECTOR"
+  "vmadc.vxm\t%0,%1,%2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_expand "@pred_msbc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_int_operand"))
+            (match_operand:VI_D 1 "register_operand"))
+           (match_operand:<VM> 3 "register_operand")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand")
+              (match_operand 5 "const_int_operand")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
+  "TARGET_VECTOR"
+  {
+    if (!TARGET_64BIT)
+      {
+        rtx v = gen_reg_rtx (<MODE>mode);
+
+       if (riscv_vector::simm32_p (operands[2]))
+         {
+           if (!rtx_equal_p (operands[2], const0_rtx))
+             operands[2] = force_reg (Pmode, operands[2]);
+           operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[2]);
+         }
+       else
+         {
+           if (CONST_INT_P (operands[2]))
+             operands[2] = force_reg (<VEL>mode, operands[2]);
+
+           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+                                           v, operands[2], operands[5],
+                                           <VM>mode);
+           emit_insn (gen_pred_msbc<mode> (operands[0], operands[1], v, operands[3],
+                                           operands[4], operands[5]));
+           DONE;
+         }
+      }
+    else
+      {
+       if (!rtx_equal_p (operands[2], const0_rtx))
+         operands[2] = force_reg (<VEL>mode, operands[2]);
+      }
+  })
+
+(define_insn "*pred_msbc<mode>_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
+            (match_operand:VI_D 1 "register_operand"    "  vr"))
+           (match_operand:<VM> 3 "register_operand"     "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"  "  rK")
+              (match_operand 5 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
+  "TARGET_VECTOR"
+  "vmsbc.vxm\t%0,%1,%z2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "*pred_msbc<mode>_extended_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"             "=&vr")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (sign_extend:<VEL>
+                (match_operand:<VSUBEL> 2 "reg_or_0_operand" "  rJ")))
+            (match_operand:VI_D 1 "register_operand"         "  vr"))
+           (match_operand:<VM> 3 "register_operand"          "  vm")
+           (unspec:<VM>
+             [(match_operand 4 "vector_length_operand"       "  rK")
+              (match_operand 5 "const_int_operand"           "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_VMSBC))]
+  "TARGET_VECTOR"
+  "vmsbc.vxm\t%0,%1,%z2,%3"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "4")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))])
+
+(define_insn "@pred_madc<mode>_overflow"
+  [(set (match_operand:<VM> 0 "register_operand"        "=&vr, &vr")
+       (unspec:<VM>
+          [(plus:VI
+            (match_operand:VI 1 "register_operand"     "  vr,  vr")
+            (match_operand:VI 2 "vector_arith_operand" "  vr,  vi"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand" "  rK,  rK")
+              (match_operand 4 "const_int_operand"     "   i,   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "@
+   vmadc.vv\t%0,%1,%2
+   vmadc.vi\t%0,%1,%v2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_insn "@pred_msbc<mode>_overflow"
+  [(set (match_operand:<VM> 0 "register_operand"        "=&vr")
+       (unspec:<VM>
+          [(minus:VI
+            (match_operand:VI 1 "register_operand"     "  vr")
+            (match_operand:VI 2 "register_operand"     "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand" "  rK")
+              (match_operand 4 "const_int_operand"     "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmsbc.vv\t%0,%1,%2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_insn "@pred_madc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(plus:VI_QHS
+            (vec_duplicate:VI_QHS
+              (match_operand:<VEL> 2 "register_operand" "   r"))
+            (match_operand:VI_QHS 1 "register_operand"  "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"  "  rK")
+              (match_operand 4 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmadc.vx\t%0,%1,%2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_insn "@pred_msbc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(minus:VI_QHS
+            (vec_duplicate:VI_QHS
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
+            (match_operand:VI_QHS 1 "register_operand"  "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"  "  rK")
+              (match_operand 4 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmsbc.vx\t%0,%1,%z2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_expand "@pred_madc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_int_operand"))
+            (match_operand:VI_D 1 "register_operand"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand")
+              (match_operand 4 "const_int_operand")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  {
+    if (riscv_vector::simm5_p (operands[2]))
+      operands[2] = force_reg (<VEL>mode, operands[2]);
+    else if (!TARGET_64BIT)
+      {
+        rtx v = gen_reg_rtx (<MODE>mode);
+
+       if (riscv_vector::simm32_p (operands[2]))
+         operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode,
+               force_reg (Pmode, operands[2]));
+       else
+         {
+           if (CONST_INT_P (operands[2]))
+             operands[2] = force_reg (<VEL>mode, operands[2]);
+
+           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+                                           v, operands[2], operands[3],
+                                           <VM>mode);
+           emit_insn (gen_pred_madc<mode>_overflow (operands[0], operands[1],
+                                                    v, operands[3], operands[4]));
+           DONE;
+         }
+      }
+    else
+      operands[2] = force_reg (<VEL>mode, operands[2]);
+  })
+
+(define_insn "*pred_madc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "register_operand" "   r"))
+            (match_operand:VI_D 1 "register_operand"    "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"  "  rK")
+              (match_operand 4 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmadc.vx\t%0,%1,%2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_insn "*pred_madc<mode>_overflow_extended_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"             "=&vr")
+       (unspec:<VM>
+          [(plus:VI_D
+            (vec_duplicate:VI_D
+              (sign_extend:<VEL>
+                (match_operand:<VSUBEL> 2 "register_operand" "   r")))
+            (match_operand:VI_D 1 "register_operand"         "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"       "  rK")
+              (match_operand 4 "const_int_operand"           "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmadc.vx\t%0,%1,%2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_expand "@pred_msbc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_int_operand"))
+            (match_operand:VI_D 1 "register_operand"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand")
+              (match_operand 4 "const_int_operand")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  {
+    if (!TARGET_64BIT)
+      {
+        rtx v = gen_reg_rtx (<MODE>mode);
+
+       if (riscv_vector::simm32_p (operands[2]))
+         {
+           if (!rtx_equal_p (operands[2], const0_rtx))
+             operands[2] = force_reg (Pmode, operands[2]);
+           operands[2] = gen_rtx_SIGN_EXTEND (<VEL>mode, operands[2]);
+         }
+       else
+         {
+           if (CONST_INT_P (operands[2]))
+             operands[2] = force_reg (<VEL>mode, operands[2]);
+
+           riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (<MODE>mode),
+                                           v, operands[2], operands[3],
+                                           <VM>mode);
+           emit_insn (gen_pred_msbc<mode>_overflow (operands[0], operands[1],
+                                                    v, operands[3], operands[4]));
+           DONE;
+         }
+      }
+    else
+      {
+       if (!rtx_equal_p (operands[2], const0_rtx))
+         operands[2] = force_reg (<VEL>mode, operands[2]);
+      }
+  })
+
+(define_insn "*pred_msbc<mode>_overflow_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"         "=&vr")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (match_operand:<VEL> 2 "reg_or_0_operand" "  rJ"))
+            (match_operand:VI_D 1 "register_operand"    "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"  "  rK")
+              (match_operand 4 "const_int_operand"      "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmsbc.vx\t%0,%1,%z2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
+(define_insn "*pred_msbc<mode>_overflow_extended_scalar"
+  [(set (match_operand:<VM> 0 "register_operand"             "=&vr")
+       (unspec:<VM>
+          [(minus:VI_D
+            (vec_duplicate:VI_D
+              (sign_extend:<VEL>
+                (match_operand:<VSUBEL> 2 "reg_or_0_operand" "  rJ")))
+            (match_operand:VI_D 1 "register_operand"         "  vr"))
+           (unspec:<VM>
+             [(match_operand 3 "vector_length_operand"       "  rK")
+              (match_operand 4 "const_int_operand"           "   i")
+              (reg:SI VL_REGNUM)
+              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)] UNSPEC_OVERFLOW))]
+  "TARGET_VECTOR"
+  "vmsbc.vx\t%0,%1,%z2"
+  [(set_attr "type" "vicalu")
+   (set_attr "mode" "<MODE>")
+   (set_attr "vl_op_idx" "3")
+   (set (attr "avl_type") (symbol_ref "INTVAL (operands[4])"))])
+
 ;; -------------------------------------------------------------------------------
 ;; ---- Predicated integer unary operations
 ;; -------------------------------------------------------------------------------