@@ -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)
@@ -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;
@@ -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)
@@ -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
@@ -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
@@ -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++);
@@ -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
@@ -36,6 +36,9 @@
UNSPEC_VADC
UNSPEC_VSBC
+ UNSPEC_VMADC
+ UNSPEC_VMSBC
+ UNSPEC_OVERFLOW
])
(define_mode_iterator V [
@@ -1962,6 +1962,7 @@
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])"))])
@@ -1985,6 +1986,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])"))])
@@ -2009,6 +2011,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])"))])
@@ -2033,6 +2036,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])"))])
@@ -2102,6 +2106,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])"))])
@@ -2127,6 +2132,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])"))])
@@ -2200,6 +2206,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])"))])
@@ -2225,10 +2232,497 @@
"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
;; -------------------------------------------------------------------------------