}
};
+/* 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;
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;
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)
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
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)
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]);
}
};
+/* 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
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
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};
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};
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) \
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:
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)
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 ();
}
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)
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
};
/* 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);
#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)
(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")
(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")
(define_constants [
(INVALID_ATTRIBUTE 255)
+ (X0_REGNUM 0)
])
;; True if the type is RVV instructions that include VTYPE
;; 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)")
;; 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)))
(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)))
(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)))
(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)))
(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])")]
;; (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
(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
(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.
"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])"))])