template <int MAX_OPERANDS> class insn_expander
{
public:
- insn_expander () : m_opno (0) {}
+ insn_expander () : m_opno (0), has_dest(false) {}
void add_output_operand (rtx x, machine_mode mode)
{
create_output_operand (&m_ops[m_opno++], x, mode);
add_input_operand (gen_int_mode (type, Pmode), Pmode);
}
+ void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode)
+ {
+ dest_mode = GET_MODE (dest);
+ has_dest = true;
+
+ add_output_operand (dest, dest_mode);
+
+ if (mask)
+ add_input_operand (mask, GET_MODE (mask));
+ else
+ add_all_one_mask_operand (mask_mode);
+
+ add_vundef_operand (dest_mode);
+ }
+
+ void set_len_and_policy (rtx len, bool vlmax_p)
+ {
+ gcc_assert (has_dest);
+ gcc_assert (len || vlmax_p);
+
+ if (len)
+ add_input_operand (len, Pmode);
+ else
+ {
+ rtx vlmax = gen_reg_rtx (Pmode);
+ emit_vlmax_vsetvl (dest_mode, vlmax);
+ add_input_operand (vlmax, Pmode);
+ }
+
+ if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
+ add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
+
+ if (vlmax_p)
+ add_avl_type_operand (avl_type::VLMAX);
+ else
+ add_avl_type_operand (avl_type::NONVLMAX);
+ }
+
void expand (enum insn_code icode, bool temporary_volatile_p = false)
{
if (temporary_volatile_p)
private:
int m_opno;
+ bool has_dest;
+ machine_mode dest_mode;
expand_operand m_ops[MAX_OPERANDS];
};
machine_mode mask_mode, bool vlmax_p)
{
insn_expander<8> e;
- machine_mode mode = GET_MODE (dest);
+ e.set_dest_and_mask (mask, dest, mask_mode);
- e.add_output_operand (dest, mode);
+ e.add_input_operand (src, GET_MODE (src));
- if (mask)
- e.add_input_operand (mask, GET_MODE (mask));
- else
- e.add_all_one_mask_operand (mask_mode);
+ e.set_len_and_policy (len, vlmax_p);
- e.add_vundef_operand (mode);
+ e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+}
- e.add_input_operand (src, GET_MODE (src));
+/* Emit an RVV binop. If one of SRC1 and SRC2 is a scalar operand, its mode is
+ specified using SCALAR_MODE. */
+static void
+emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
+ rtx len, machine_mode mask_mode, machine_mode scalar_mode,
+ bool vlmax_p)
+{
+ insn_expander<9> e;
+ e.set_dest_and_mask (mask, dest, mask_mode);
- if (len)
- e.add_input_operand (len, Pmode);
- else
- {
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (mode, vlmax);
- e.add_input_operand (vlmax, Pmode);
- }
+ gcc_assert (VECTOR_MODE_P (GET_MODE (src1))
+ || VECTOR_MODE_P (GET_MODE (src2)));
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
- e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
+ if (VECTOR_MODE_P (GET_MODE (src1)))
+ e.add_input_operand (src1, GET_MODE (src1));
+ else
+ e.add_input_operand (src1, scalar_mode);
- if (vlmax_p)
- e.add_avl_type_operand (avl_type::VLMAX);
+ if (VECTOR_MODE_P (GET_MODE (src2)))
+ e.add_input_operand (src2, GET_MODE (src2));
else
- e.add_avl_type_operand (avl_type::NONVLMAX);
+ e.add_input_operand (src2, scalar_mode);
- e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+ e.set_len_and_policy (len, vlmax_p);
+
+ e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
}
void
emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
}
-/* Emit binary operations. */
-
-static void
-emit_binop (unsigned icode, rtx *ops, machine_mode mask_mode,
- machine_mode scalar_mode)
+void
+emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+ machine_mode mask_mode, machine_mode scalar_mode)
{
- insn_expander<9> e;
- machine_mode mode = GET_MODE (ops[0]);
- e.add_output_operand (ops[0], mode);
- e.add_all_one_mask_operand (mask_mode);
- e.add_vundef_operand (mode);
- if (VECTOR_MODE_P (GET_MODE (ops[1])))
- e.add_input_operand (ops[1], GET_MODE (ops[1]));
- else
- e.add_input_operand (ops[1], scalar_mode);
- if (VECTOR_MODE_P (GET_MODE (ops[2])))
- e.add_input_operand (ops[2], GET_MODE (ops[2]));
- else
- e.add_input_operand (ops[2], scalar_mode);
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (mode, vlmax);
- e.add_input_operand (vlmax, Pmode);
- e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- e.add_avl_type_operand (avl_type::VLMAX);
- e.expand ((enum insn_code) icode, false);
+ emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode,
+ scalar_mode, len ? false : true);
}
/* Emit vid.v instruction. */
static void
-emit_index_op (rtx target, machine_mode mask_mode)
+emit_index_op (rtx dest, machine_mode mask_mode)
{
insn_expander<7> e;
- machine_mode mode = GET_MODE (target);
- e.add_output_operand (target, mode);
- e.add_all_one_mask_operand (mask_mode);
- e.add_vundef_operand (mode);
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (mode, vlmax);
- e.add_input_operand (vlmax, Pmode);
- e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- e.add_avl_type_operand (avl_type::VLMAX);
- e.expand (code_for_pred_series (mode), false);
+ e.set_dest_and_mask (NULL, dest, mask_mode);
+
+ e.set_len_and_policy (NULL, true);
+
+ e.expand (code_for_pred_series (GET_MODE (dest)), false);
}
/* Expand series const vector. */
/* Emit logical left shift operation. */
int shift = exact_log2 (INTVAL (step));
rtx shift_amount = gen_int_mode (shift, Pmode);
- rtx ops[3] = {step_adj, vid, shift_amount};
insn_code icode = code_for_pred_scalar (ASHIFT, mode);
- emit_binop (icode, ops, mask_mode, Pmode);
+ emit_nonvlmax_binop (icode, step_adj, vid, shift_amount,
+ NULL, mask_mode, Pmode);
}
else
{
- rtx ops[3] = {step_adj, vid, step};
insn_code icode = code_for_pred_scalar (MULT, mode);
- emit_binop (icode, ops, mask_mode, inner_mode);
+ emit_nonvlmax_binop (icode, step_adj, vid, step,
+ NULL, mask_mode, inner_mode);
}
}
else
{
rtx result = gen_reg_rtx (mode);
- rtx ops[3] = {result, step_adj, base};
insn_code icode = code_for_pred_scalar (PLUS, mode);
- emit_binop (icode, ops, mask_mode, inner_mode);
+ emit_nonvlmax_binop (icode, result, step_adj, base,
+ NULL, mask_mode, inner_mode);
emit_move_insn (dest, result);
}
}