在 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")

Reply via email to