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

Reply via email to