https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110751
--- Comment #22 from JuzheZhong <juzhe.zhong at rivai dot ai> --- (In reply to rsand...@gcc.gnu.org from comment #20) > (In reply to Richard Biener from comment #19) > > Sure, I can kind of see the usefulness elsewhere. Just for this particular > > issue it doesn't seem necessary to sit down and design this when we can > > represent it like we do for MASK_LOAD (omit the 'else' value). > Yeah, that's fair. > > For the ifn->optab interface, I think it'd be natural to use an actual rtx > rather than a null pointer, since e.g. predicates are not set up to handle > nulls. So perhaps we should start the process there. We could add an UNDEF > rtl code that is initially only used for the ifn->optab interface, and > expand it as we find new use cases. We can grow the semantics based on > those use cases and based on LLVM's experience. > > > In other context we discussed specifying zero for MASK_LOAD masked elements > > so we can for example CSE better. CSE with UNDEF might be possible as well, > > but I'm not sure what LLVM's undef would allow and whether it's defined > > rigidly enough. > One of the main optimisations I wanted from that was: > a = IFN_MASK_LOAD (…, mask) > b = VEC_COND_EXPR <mask, a, {0,0,…}> > → > a = IFN_MASK_LOAD (…, mask) > b = a > which wouldn't be valid for undef. In RVV, we define a "undef" rtx which is: (unspec:V256HF [ (reg:SI 0 zero) ] UNSPEC_VUNDEF) So, RVV pattern as defined as follows: (define_insn "@pred_<optab><mode>" [(set (match_operand:VI 0 "register_operand" "=vd,vd, vr, vr") (if_then_else:VI (unspec:<VM> [(match_operand:<VM> 1 "vector_mask_operand" "vm,vm,Wc1,Wc1") (match_operand 4 "vector_length_operand" "rK,rK, rK, rK") (match_operand 5 "const_int_operand" " i, i, i, i") (match_operand 6 "const_int_operand" " i, i, i, i") (match_operand 7 "const_int_operand" " i, i, i, i") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (any_int_unop:VI (match_operand:VI 3 "register_operand" "vr,vr, vr, vr")) (match_operand:VI 2 "vector_merge_operand" "vu, 0, vu, 0")))] "TARGET_VECTOR" "v<insn>.v\t%0,%3%p1" [(set_attr "type" "vialu") (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_ma(operands[6])")) (set (attr "avl_type") (symbol_ref "INTVAL (operands[7])"))]) You can see operand: (match_operand:VI 2 "vector_merge_operand" "vu, 0, vu, 0") There is a constraint "vu": (define_constraint "vu" "A undefined vector value." (and (match_code "unspec") (match_test "XINT (op, 1) == UNSPEC_VUNDEF"))) RA will match constraint "vu" for "undef" else value. (insn 10 9 0 2 (set (mem:V256HF (reg/v/f:DI 136 [ out ]) [1 MEM[(v256hf *)out_4(D)]+0 S512 A128]) (if_then_else:V256HF (unspec:V256BI [ (const_vector:V256BI [ (const_int 1 [0x1]) repeated x256 ]) (reg:DI 138) (const_int 2 [0x2]) repeated x2 (const_int 0 [0]) (reg:SI 66 vl) (reg:SI 67 vtype) ] UNSPEC_VPREDICATE) (reg/v:V256HF 134 [ v ]) (unspec:V256HF [ (reg:SI 0 zero) ] UNSPEC_VUNDEF))) "rvv.c":18:17 1156 {pred_movv256hf} (nil)) You can see: (unspec:V256HF [ (reg:SI 0 zero) ] UNSPEC_VUNDEF) Then such operand will not consume a register. This is currently how RVV model "undef" in RTL backend.