在 2025/2/7 下午8:09, Xi Ruoyao 写道:
/* snip */
-
-(define_insn "lasx_xvpickev_w"
- [(set (match_operand:V8SI 0 "register_operand" "=f")
- (vec_select:V8SI
- (vec_concat:V16SI
- (match_operand:V8SI 1 "register_operand" "f")
- (match_operand:V8SI 2 "register_operand" "f"))
- (parallel [(const_int 0) (const_int 2)
- (const_int 8) (const_int 10)
- (const_int 4) (const_int 6)
- (const_int 12) (const_int 14)])))]
- "ISA_HAS_LASX"
- "xvpickev.w\t%u0,%u2,%u1"
- [(set_attr "type" "simd_permute")
- (set_attr "mode" "V8SI")])
-
/* snip */
+;; Picking even/odd elements.
+(define_insn "simd_pick_evod_<mode>"
+ [(set (match_operand:ALLVEC 0 "register_operand" "=f")
+ (vec_select:ALLVEC
+ (vec_concat:<LVEC>
+ (match_operand:ALLVEC 1 "register_operand" "f")
+ (match_operand:ALLVEC 2 "register_operand" "f"))
+ (match_operand:<LVEC> 3 "vect_par_cnst_even_or_odd_half")))]
For LASX, the generated select array is problematic, taking xvpickev.w
as an example:
xvpickev.w vd,vj,vk
The behavior of the instruction is as follows:
vd.w[0] = vk.w[0]
vd.w[1] = vk.w[2]
vd.w[2] = vj.w[0]
vd.w[3] = vj.w[2]
vd.w[4] = vk.w[4]
vd.w[5] = vk.w[6]
vd.w[6] = vj.w[4]
vd.w[7] = vj.w[6]
At this point, the select array should be {0, 2, 8, 10, 4, 6, 12, 14}
instead of {0, 2, 4, 6, 8, 10, 12, 14}.
+ "GET_MODE_SIZE (<UNITMODE>mode) != 8" ;; Use vilvl.d instead
+ "<x>vpick%O3.<simdfmt_as_i>\t%<wu>0,%<wu>2,%<wu>1"
+ [(set_attr "type" "simd_permute")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "<simd_isa>_<x>vpick<ev_od>_<simdfmt_as_i><_f>"
+ [(match_operand:ALLVEC 0 "register_operand" "=f")
+ (match_operand:ALLVEC 1 "register_operand" " f")
+ (match_operand:ALLVEC 2 "register_operand" " f")
+ (const_int zero_one)]
+ "GET_MODE_SIZE (<UNITMODE>mode) != 8" ;; Use vilvl.d instead
+{
+ int nelts = GET_MODE_NUNITS (<MODE>mode);
+ rtx op3 = loongarch_gen_stepped_int_parallel (nelts, <zero_one>, 2);
+ rtx insn = gen_simd_pick_evod_<mode> (operands[0], operands[1],
+ operands[2], op3);
+ emit_insn (insn);
+ DONE;
+})
+
;; Integer widening add/sub/mult.
(define_insn "simd_<optab>w_evod_<mode>_<su>"
[(set (match_operand:<WVEC_HALF> 0 "register_operand" "=f")