At 2026/6/16 3:06, Robin Dapp wrote:
Hi Jiawei,
+;; Source modes for Zvzip instructions whose destination/source operand has
+;; 2x LMUL, without exposing forms that would require LMUL > 8.
+(define_mode_iterator VLMULX2 [
+ (RVVMF8QI "TARGET_VECTOR_ELEN_64")
+ RVVMF4QI RVVMF2QI RVVM1QI RVVM2QI RVVM4QI
+
+ (RVVMF4HI "TARGET_VECTOR_ELEN_64")
+ RVVMF2HI RVVM1HI RVVM2HI RVVM4HI
+
+ (RVVMF4BF "TARGET_VECTOR_ELEN_BF_16 && TARGET_VECTOR_ELEN_64")
+ (RVVMF2BF "TARGET_VECTOR_ELEN_BF_16")
+ (RVVM1BF "TARGET_VECTOR_ELEN_BF_16")
+ (RVVM2BF "TARGET_VECTOR_ELEN_BF_16")
+ (RVVM4BF "TARGET_VECTOR_ELEN_BF_16")
+
+ (RVVMF4HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_VECTOR_ELEN_64")
+ (RVVMF2HF "TARGET_VECTOR_ELEN_FP_16")
+ (RVVM1HF "TARGET_VECTOR_ELEN_FP_16")
+ (RVVM2HF "TARGET_VECTOR_ELEN_FP_16")
+ (RVVM4HF "TARGET_VECTOR_ELEN_FP_16")
+
+ (RVVMF2SI "TARGET_VECTOR_ELEN_64")
+ RVVM1SI RVVM2SI RVVM4SI
+
+ (RVVMF2SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_VECTOR_ELEN_64")
+ (RVVM1SF "TARGET_VECTOR_ELEN_FP_32")
+ (RVVM2SF "TARGET_VECTOR_ELEN_FP_32")
+ (RVVM4SF "TARGET_VECTOR_ELEN_FP_32")
+
+ (RVVM1DI "TARGET_VECTOR_ELEN_64")
+ (RVVM2DI "TARGET_VECTOR_ELEN_64")
+ (RVVM4DI "TARGET_VECTOR_ELEN_64")
+
+ (RVVM1DF "TARGET_VECTOR_ELEN_FP_64")
+ (RVVM2DF "TARGET_VECTOR_ELEN_FP_64")
+ (RVVM4DF "TARGET_VECTOR_ELEN_FP_64")
+])
I'm afraid we need VLS modes as well here :) And once we have those, we might
need to think about the naming, as LMUL might not make a lot of sense for e.g.
V4QI -> V8QI. Maybe just V_DOUBLE?
Also, we already have VI_QHS_NO_M8. You could re-use that and just add the
missing modes in a new combined iterator.
Then, HF modes, are these in scope?
+;; Zvzip v0.1 draft.
+(define_insn "@pred_vzip<mode>"
+ [(set (match_operand:<VLMUL_EXT2> 0 "register_operand" "=&vr, &vr")
+ (if_then_else:<VLMUL_EXT2>
+ (unspec:<VM>
+ [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
+ (match_operand 5 "vector_length_operand" " rvl, rvl")
+ (match_operand 6 "const_int_operand" " i, i")
+ (match_operand 7 "const_int_operand" " i, i")
+ (match_operand 8 "const_int_operand" " i, i")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ (unspec:<VLMUL_EXT2>
+ [(match_operand:VLMULX2 3 "register_operand" " vr, vr")
+ (match_operand:VLMULX2 4 "register_operand" " vr, vr")]
UNSPEC_VZIP)
+ (match_operand:<VLMUL_EXT2> 2 "vector_merge_operand" " vu, 0")))]
+ "TARGET_ZVZIP"
+ "vzip.vv\t%0,%3,%4%p1"
+ [(set_attr "type" "vgather")
+ (set_attr "mode" "<MODE>")])
Does the vgather type work with a "widening" instruction type? Like mode_idx
for example would come from operand[0] but operand[3] and operand[4] have
a smaller mode. Such kinds of issues will likely only occur in more
complicated scenarios and might not be caught in simpler tests.
I guess the earlyclobber is alright for now, until we have more fine-grained
options.
+(define_insn "@pred_vunzipe<mode>"
+ [(set (match_operand:VLMULX2 0 "register_operand" "=&vr, &vr")
+ (if_then_else:VLMULX2
+ (unspec:<VM>
+ [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
+ (match_operand 4 "vector_length_operand" " rvl, rvl")
+ (match_operand 5 "const_int_operand" " i, i")
+ (match_operand 6 "const_int_operand" " i, i")
+ (match_operand 7 "const_int_operand" " i, i")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ (unspec:VLMULX2
+ [(match_operand:<VLMUL_EXT2> 3 "register_operand" " vr, vr")]
UNSPEC_VUNZIPE)
+ (match_operand:VLMULX2 2 "vector_merge_operand" " vu, 0")))]
+ "TARGET_ZVZIP"
+ "vunzipe.v\t%0,%3%p1"
+ [(set_attr "type" "vgather")
+ (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_idx" "7")])
Same question here about the attributes. I haven't checked in detail, just
wanted to make sure.
Hi Robin,
Thanks for the suggestions, that makes sense.
I will rename the iterator/attribute so that the name no longer refers to
LMUL. Something like V_DOUBLE_EXTENDABLE / V_DOUBLE_EXT should be
clearer for
both scalable RVV modes and fixed-length VLS modes.
I will also add the VLS modes. For the integer Q/H/S modes I will reuse the
existing VI_QHS_NO_M8 iterator and build a combined iterator for the
remaining
modes that have a valid double-sized mode.
For the HF modes: I included them because Zvzip is a data
movement/reordering
extension rather than an FP arithmetic extension, and the current intrinsic
document / LLVM draft API exposes f16 forms. The modes will still be
gated by
the existing FP16 vector type availability. If you prefer, I can add a
comment
or split that out for easier review.
Regarding the attributes: yes, vzip is the special case. The vtype/VL
should
be based on the source mode, not the 2xLMUL destination mode. I will
make this
explicit instead of relying on the vgather defaults, e.g. by setting
mode_idx to
the source operand for vzip. For vunzipe/vunzipo the destination mode
is the
mode used for vsetvl, so operand 0 is still the right mode, but I can
set the
mode_idx explicitly there too for clarity.
I will also add tests that check the emitted vsetvli mode, for example
making
sure vzip_i8m2 uses e8,m1 rather than e8,m2.
Best regards,
Jiawei