Hi Robin,
Would it hurt to allow any nonmemory operand here and just force the
"unsupported" constants into a register?
Are you talking about why operand 2 doesn't use nonmemory_operand
predicate? If so, I think this is because our vmerge.v[vxi]m insns
only supports that operand 1 is a scalar and operand 2 must be a
vector register.
My question was rather:
Why doesn't something like
(define_insn_and_split "vcond_mask_<mode><vm>"
[(set (match_operand:V_VLS 0 "register_operand")
(if_then_else:V_VLS
(match_operand:<VM> 3 "register_operand")
(match_operand:V_VLS 1 "nonmemory_operand")
(match_operand:V_VLS 2 "nonmemory_operand")))]
"TARGET_VECTOR && can_create_pseudo_p ()"
"#"
"&& 1"
[(const_int 0)]
{
/* The order of vcond_mask is opposite to pred_merge. */
if (REG_P (operands[2]))
operands[2] = force_reg (<MODE>mode, operands[2]);
std::swap (operands[1], operands[2]);
riscv_vector::emit_vlmax_insn (code_for_pred_merge (<MODE>mode),
riscv_vector::MERGE_OP, operands);
DONE;
}
[(set_attr "type" "vector")]
)
suffice? You could disallow operands[2] != 0 if needed.
I think I understand what you're saying. The reason for not doing this
is because simply allowing the operand 2 of vcond_mask to be vec_const_0
would cause the other combine patterns to fail because they require the
operand 2 of vcond_mask to be a register. Like the following existing
combine patterns (operand 2 as the instruction merge operand, is not
allowed to be non-register):
(define_insn_and_split "*cond_<optab><mode>"
[(set (match_operand:VF 0 "register_operand")
(if_then_else:VF
(match_operand:<VM> 1 "register_operand")
(any_float_unop:VF
(match_operand:VF 2 "register_operand"))
(match_operand:VF 3 "register_operand")))]
"TARGET_VECTOR && can_create_pseudo_p ()"
"#"
"&& 1"
[(const_int 0)]
{
insn_code icode = code_for_pred (<CODE>, <MODE>mode);
rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
riscv_vector::expand_cond_len_unop (icode, ops);
DONE;
}
[(set_attr "type" "vector")])
My current method is still to keep the operand 2 of vcond_mask as a
register, but the pattern of mov_vec_const_0 is simplified, so that the
corresponding combine pattern can be more simple. That's the only reason
I split the vcond_mask into three patterns.
--
Best,
Lehua