Like what we've done for {lsx_,lasx_x}v{add,sub,mul}l{ev,od}, use
special predicates and TImode RTL instead of hard-coded const vectors
and UNSPECs.

gcc/ChangeLog:

        * config/loongarch/lasx.md (UNSPEC_LASX_XVHADDW_Q_D): Remove.
        (UNSPEC_LASX_XVHSUBW_Q_D): Remove.
        (UNSPEC_LASX_XVHADDW_QU_DU): Remove.
        (UNSPEC_LASX_XVHSUBW_QU_DU): Remove.
        (lasx_xvh<addsub:optab>w_h<u>_b<u>): Remove.
        (lasx_xvh<addsub:optab>w_w<u>_h<u>): Remove.
        (lasx_xvh<addsub:optab>w_d<u>_w<u>): Remove.
        (lasx_xvhaddw_q_d): Remove.
        (lasx_xvhsubw_q_d): Remove.
        (lasx_xvhaddw_qu_du): Remove.
        (lasx_xvhsubw_qu_du): Remove.
        (reduc_plus_scal_v4di): Call gen_lasx_haddw_q_d_punned instead
        of gen_lasx_xvhaddw_q_d.
        (reduc_plus_scal_v8si): Likewise.
        * config/loongarch/lsx.md (UNSPEC_LSX_VHADDW_Q_D): Remove.
        (UNSPEC_ASX_VHSUBW_Q_D): Remove.
        (UNSPEC_ASX_VHADDW_QU_DU): Remove.
        (UNSPEC_ASX_VHSUBW_QU_DU): Remove.
        (lsx_vh<addsub:optab>w_h<u>_b<u>): Remove.
        (lsx_vh<addsub:optab>w_w<u>_h<u>): Remove.
        (lsx_vh<addsub:optab>w_d<u>_w<u>): Remove.
        (lsx_vhaddw_q_d): Remove.
        (lsx_vhsubw_q_d): Remove.
        (lsx_vhaddw_qu_du): Remove.
        (lsx_vhsubw_qu_du): Remove.
        (reduc_plus_scal_v2di): Change the temporary register mode to
        V1TI, and pun the mode calling gen_vec_extractv2didi.
        (reduc_plus_scal_v4si): Change the temporary register mode to
        V1TI.
        * config/loongarch/predicates.md (vect_par_cnst_even_half): New
        define_special_predicate.
        (vect_par_cnst_even_or_odd_half): Likewise.
        * config/loongarch/simd.md (simd_h<optab>w_<mode>_<su>): New
        define_insn.
        (<simd_isa>_<x>vh<optab>w_<simdfmt_w><u>_<simdfmt><u>): New
        define_expand.
        (<simd_isa>_h<optab>w_q<u>_d<u>_punned): New define_expand.
        * config/loongarch/loongarch-builtins.cc
        (CODE_FOR_lsx_vhaddw_q_d): Define as a macro to override with
        punned expand.
        (CODE_FOR_lsx_vhaddw_qu_du): Likewise.
        (CODE_FOR_lsx_vhsubw_q_d): Likewise.
        (CODE_FOR_lsx_vhsubw_qu_du): Likewise.
        (CODE_FOR_lasx_xvhaddw_q_d): Likewise.
        (CODE_FOR_lasx_xvhaddw_qu_du): Likewise.
        (CODE_FOR_lasx_xvhsubw_q_d): Likewise.
        (CODE_FOR_lasx_xvhsubw_qu_du): Likewise.
---
 gcc/config/loongarch/lasx.md               | 126 +--------------------
 gcc/config/loongarch/loongarch-builtins.cc |  10 ++
 gcc/config/loongarch/lsx.md                | 108 +-----------------
 gcc/config/loongarch/predicates.md         |  16 +++
 gcc/config/loongarch/simd.md               |  48 ++++++++
 5 files changed, 81 insertions(+), 227 deletions(-)

diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
index 640fa028f1e..1dc11840187 100644
--- a/gcc/config/loongarch/lasx.md
+++ b/gcc/config/loongarch/lasx.md
@@ -100,10 +100,6 @@ (define_c_enum "unspec" [
   UNSPEC_LASX_XVMADDWOD
   UNSPEC_LASX_XVMADDWOD2
   UNSPEC_LASX_XVMADDWOD3
-  UNSPEC_LASX_XVHADDW_Q_D
-  UNSPEC_LASX_XVHSUBW_Q_D
-  UNSPEC_LASX_XVHADDW_QU_DU
-  UNSPEC_LASX_XVHSUBW_QU_DU
   UNSPEC_LASX_XVADD_Q
   UNSPEC_LASX_XVSUB_Q
   UNSPEC_LASX_XVREPLVE
@@ -1407,76 +1403,6 @@ (define_insn "fixuns_trunc<FLASX:mode><mode256_i>2"
    (set_attr "cnv_mode" "<FINTCNV256_2>")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "lasx_xvh<optab>w_h<u>_b<u>"
-  [(set (match_operand:V16HI 0 "register_operand" "=f")
-       (addsub:V16HI
-         (any_extend:V16HI
-           (vec_select:V16QI
-             (match_operand:V32QI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)
-                        (const_int 5) (const_int 7)
-                        (const_int 9) (const_int 11)
-                        (const_int 13) (const_int 15)
-                        (const_int 17) (const_int 19)
-                        (const_int 21) (const_int 23)
-                        (const_int 25) (const_int 27)
-                        (const_int 29) (const_int 31)])))
-         (any_extend:V16HI
-           (vec_select:V16QI
-             (match_operand:V32QI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)
-                        (const_int 4) (const_int 6)
-                        (const_int 8) (const_int 10)
-                        (const_int 12) (const_int 14)
-                        (const_int 16) (const_int 18)
-                        (const_int 20) (const_int 22)
-                        (const_int 24) (const_int 26)
-                        (const_int 28) (const_int 30)])))))]
-  "ISA_HAS_LASX"
-  "xvh<optab>w.h<u>.b<u>\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V16HI")])
-
-(define_insn "lasx_xvh<optab>w_w<u>_h<u>"
-  [(set (match_operand:V8SI 0 "register_operand" "=f")
-       (addsub:V8SI
-         (any_extend:V8SI
-           (vec_select:V8HI
-             (match_operand:V16HI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)
-                        (const_int 5) (const_int 7)
-                        (const_int 9) (const_int 11)
-                        (const_int 13) (const_int 15)])))
-         (any_extend:V8SI
-           (vec_select:V8HI
-             (match_operand:V16HI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)
-                        (const_int 4) (const_int 6)
-                        (const_int 8) (const_int 10)
-                        (const_int 12) (const_int 14)])))))]
-  "ISA_HAS_LASX"
-  "xvh<optab>w.w<u>.h<u>\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V8SI")])
-
-(define_insn "lasx_xvh<optab>w_d<u>_w<u>"
-  [(set (match_operand:V4DI 0 "register_operand" "=f")
-       (addsub:V4DI
-         (any_extend:V4DI
-           (vec_select:V4SI
-             (match_operand:V8SI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)
-                        (const_int 5) (const_int 7)])))
-         (any_extend:V4DI
-           (vec_select:V4SI
-             (match_operand:V8SI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)
-                        (const_int 4) (const_int 6)])))))]
-  "ISA_HAS_LASX"
-  "xvh<optab>w.d<u>.w<u>\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4DI")])
-
 (define_insn "lasx_xvpackev_b"
   [(set (match_operand:V32QI 0 "register_operand" "=f")
        (vec_select:V32QI
@@ -3590,54 +3516,6 @@ (define_insn "lasx_xvmaddwod_q_du_d"
   [(set_attr "type" "simd_int_arith")
    (set_attr "mode" "V4DI")])
 
-;;XVHADDW.Q.D
-;;TODO2
-(define_insn "lasx_xvhaddw_q_d"
-  [(set (match_operand:V4DI 0 "register_operand" "=f")
-       (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
-                     (match_operand:V4DI 2 "register_operand" "f")]
-                    UNSPEC_LASX_XVHADDW_Q_D))]
-  "ISA_HAS_LASX"
-  "xvhaddw.q.d\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4DI")])
-
-;;XVHSUBW.Q.D
-;;TODO2
-(define_insn "lasx_xvhsubw_q_d"
-  [(set (match_operand:V4DI 0 "register_operand" "=f")
-       (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
-                     (match_operand:V4DI 2 "register_operand" "f")]
-                    UNSPEC_LASX_XVHSUBW_Q_D))]
-  "ISA_HAS_LASX"
-  "xvhsubw.q.d\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4DI")])
-
-;;XVHADDW.QU.DU
-;;TODO2
-(define_insn "lasx_xvhaddw_qu_du"
-  [(set (match_operand:V4DI 0 "register_operand" "=f")
-       (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
-                     (match_operand:V4DI 2 "register_operand" "f")]
-                    UNSPEC_LASX_XVHADDW_QU_DU))]
-  "ISA_HAS_LASX"
-  "xvhaddw.qu.du\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4DI")])
-
-;;XVHSUBW.QU.DU
-;;TODO2
-(define_insn "lasx_xvhsubw_qu_du"
-  [(set (match_operand:V4DI 0 "register_operand" "=f")
-       (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
-                     (match_operand:V4DI 2 "register_operand" "f")]
-                    UNSPEC_LASX_XVHSUBW_QU_DU))]
-  "ISA_HAS_LASX"
-  "xvhsubw.qu.du\t%u0,%u1,%u2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4DI")])
-
 ;;XVADD.Q
 ;;TODO2
 (define_insn "lasx_xvadd_q"
@@ -4223,7 +4101,7 @@ (define_expand "reduc_plus_scal_v4di"
   rtx tmp = gen_reg_rtx (V4DImode);
   rtx tmp1 = gen_reg_rtx (V4DImode);
   rtx vec_res = gen_reg_rtx (V4DImode);
-  emit_insn (gen_lasx_xvhaddw_q_d (tmp, operands[1], operands[1]));
+  emit_insn (gen_lasx_haddw_q_d_punned (tmp, operands[1], operands[1]));
   emit_insn (gen_lasx_xvpermi_d_v4di (tmp1, tmp, GEN_INT (2)));
   emit_insn (gen_addv4di3 (vec_res, tmp, tmp1));
   emit_insn (gen_vec_extractv4didi (operands[0], vec_res, const0_rtx));
@@ -4239,7 +4117,7 @@ (define_expand "reduc_plus_scal_v8si"
   rtx tmp1 = gen_reg_rtx (V4DImode);
   rtx vec_res = gen_reg_rtx (V4DImode);
   emit_insn (gen_lasx_xvhaddw_d_w (tmp, operands[1], operands[1]));
-  emit_insn (gen_lasx_xvhaddw_q_d (tmp1, tmp, tmp));
+  emit_insn (gen_lasx_haddw_q_d_punned (tmp1, tmp, tmp));
   emit_insn (gen_lasx_xvpermi_d_v4di (tmp, tmp1, GEN_INT (2)));
   emit_insn (gen_addv4di3 (vec_res, tmp, tmp1));
   emit_insn (gen_vec_extractv8sisi (operands[0], gen_lowpart 
(V8SImode,vec_res),
diff --git a/gcc/config/loongarch/loongarch-builtins.cc 
b/gcc/config/loongarch/loongarch-builtins.cc
index abe6e1f3ddc..a87e6273065 100644
--- a/gcc/config/loongarch/loongarch-builtins.cc
+++ b/gcc/config/loongarch/loongarch-builtins.cc
@@ -537,6 +537,11 @@ AVAIL_ALL (lasx_frecipe, ISA_HAS_LASX && ISA_HAS_FRECIPE)
 #define CODE_FOR_lsx_vaddwod_q_du_d    CODE_FOR_lsx_addwod_q_du_d_punned
 #define CODE_FOR_lsx_vmulwod_q_du_d    CODE_FOR_lsx_mulwod_q_du_d_punned
 
+#define CODE_FOR_lsx_vhaddw_q_d                CODE_FOR_lsx_haddw_q_d_punned
+#define CODE_FOR_lsx_vhaddw_qu_du      CODE_FOR_lsx_haddw_qu_du_punned
+#define CODE_FOR_lsx_vhsubw_q_d                CODE_FOR_lsx_hsubw_q_d_punned
+#define CODE_FOR_lsx_vhsubw_qu_du      CODE_FOR_lsx_hsubw_qu_du_punned
+
 /* LoongArch ASX define CODE_FOR_lasx_mxxx */
 #define CODE_FOR_lasx_xvsadd_b CODE_FOR_ssaddv32qi3
 #define CODE_FOR_lasx_xvsadd_h CODE_FOR_ssaddv16hi3
@@ -841,6 +846,11 @@ AVAIL_ALL (lasx_frecipe, ISA_HAS_LASX && ISA_HAS_FRECIPE)
 #define CODE_FOR_lasx_xvaddwod_q_du_d  CODE_FOR_lasx_addwod_q_du_d_punned
 #define CODE_FOR_lasx_xvmulwod_q_du_d  CODE_FOR_lasx_mulwod_q_du_d_punned
 
+#define CODE_FOR_lasx_xvhaddw_q_d      CODE_FOR_lasx_haddw_q_d_punned
+#define CODE_FOR_lasx_xvhaddw_qu_du    CODE_FOR_lasx_haddw_qu_du_punned
+#define CODE_FOR_lasx_xvhsubw_q_d      CODE_FOR_lasx_hsubw_q_d_punned
+#define CODE_FOR_lasx_xvhsubw_qu_du    CODE_FOR_lasx_hsubw_qu_du_punned
+
 static const struct loongarch_builtin_description loongarch_builtins[] = {
 #define LARCH_MOVFCSR2GR 0
   DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float),
diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md
index 4b664ae6926..1783c24e635 100644
--- a/gcc/config/loongarch/lsx.md
+++ b/gcc/config/loongarch/lsx.md
@@ -93,10 +93,6 @@ (define_c_enum "unspec" [
   UNSPEC_LSX_VSTX
   UNSPEC_LSX_VEXTL_QU_DU
   UNSPEC_LSX_VSETEQZ_V
-  UNSPEC_LSX_VHADDW_Q_D
-  UNSPEC_LSX_VHADDW_QU_DU
-  UNSPEC_LSX_VHSUBW_Q_D
-  UNSPEC_LSX_VHSUBW_QU_DU
   UNSPEC_LSX_VMADDWEV
   UNSPEC_LSX_VMADDWEV2
   UNSPEC_LSX_VMADDWEV3
@@ -1296,62 +1292,6 @@ (define_insn "fixuns_trunc<FLSX:mode><mode_i>2"
    (set_attr "cnv_mode" "<FINTCNV_2>")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "lsx_vh<optab>w_h<u>_b<u>"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
-       (addsub:V8HI
-         (any_extend:V8HI
-           (vec_select:V8QI
-             (match_operand:V16QI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)
-                        (const_int 5) (const_int 7)
-                        (const_int 9) (const_int 11)
-                        (const_int 13) (const_int 15)])))
-         (any_extend:V8HI
-           (vec_select:V8QI
-             (match_operand:V16QI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)
-                        (const_int 4) (const_int 6)
-                        (const_int 8) (const_int 10)
-                        (const_int 12) (const_int 14)])))))]
-  "ISA_HAS_LSX"
-  "vh<optab>w.h<u>.b<u>\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V8HI")])
-
-(define_insn "lsx_vh<optab>w_w<u>_h<u>"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
-       (addsub:V4SI
-         (any_extend:V4SI
-           (vec_select:V4HI
-             (match_operand:V8HI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)
-                        (const_int 5) (const_int 7)])))
-         (any_extend:V4SI
-           (vec_select:V4HI
-             (match_operand:V8HI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)
-                        (const_int 4) (const_int 6)])))))]
-  "ISA_HAS_LSX"
-  "vh<optab>w.w<u>.h<u>\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V4SI")])
-
-(define_insn "lsx_vh<optab>w_d<u>_w<u>"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
-       (addsub:V2DI
-         (any_extend:V2DI
-           (vec_select:V2SI
-             (match_operand:V4SI 1 "register_operand" "f")
-             (parallel [(const_int 1) (const_int 3)])))
-         (any_extend:V2DI
-           (vec_select:V2SI
-             (match_operand:V4SI 2 "register_operand" "f")
-             (parallel [(const_int 0) (const_int 2)])))))]
-  "ISA_HAS_LSX"
-  "vh<optab>w.d<u>.w<u>\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V2DI")])
-
 (define_insn "lsx_vpackev_b"
   [(set (match_operand:V16QI 0 "register_operand" "=f")
        (vec_select:V16QI
@@ -2979,9 +2919,11 @@ (define_expand "reduc_plus_scal_v2di"
    (match_operand:V2DI 1 "register_operand")]
   "ISA_HAS_LSX"
 {
-  rtx tmp = gen_reg_rtx (V2DImode);
+  rtx tmp = gen_reg_rtx (V1TImode);
   emit_insn (gen_lsx_vhaddw_q_d (tmp, operands[1], operands[1]));
-  emit_insn (gen_vec_extractv2didi (operands[0], tmp, const0_rtx));
+  emit_insn (gen_vec_extractv2didi (operands[0],
+                                   gen_lowpart (V2DImode, tmp),
+                                   const0_rtx));
   DONE;
 })
 
@@ -2991,7 +2933,7 @@ (define_expand "reduc_plus_scal_v4si"
   "ISA_HAS_LSX"
 {
   rtx tmp = gen_reg_rtx (V2DImode);
-  rtx tmp1 = gen_reg_rtx (V2DImode);
+  rtx tmp1 = gen_reg_rtx (V1TImode);
   emit_insn (gen_lsx_vhaddw_d_w (tmp, operands[1], operands[1]));
   emit_insn (gen_lsx_vhaddw_q_d (tmp1, tmp, tmp));
   emit_insn (gen_vec_extractv4sisi (operands[0], gen_lowpart (V4SImode,tmp1),
@@ -3150,46 +3092,6 @@ (define_expand "ssadv16qi"
   DONE;
 })
 
-(define_insn "lsx_vhaddw_q_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
-       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "f")
-                     (match_operand:V2DI 2 "register_operand" "f")]
-                    UNSPEC_LSX_VHADDW_Q_D))]
-  "ISA_HAS_LSX"
-  "vhaddw.q.d\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V2DI")])
-
-(define_insn "lsx_vhaddw_qu_du"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
-       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "f")
-                     (match_operand:V2DI 2 "register_operand" "f")]
-                    UNSPEC_LSX_VHADDW_QU_DU))]
-  "ISA_HAS_LSX"
-  "vhaddw.qu.du\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V2DI")])
-
-(define_insn "lsx_vhsubw_q_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
-       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "f")
-                     (match_operand:V2DI 2 "register_operand" "f")]
-                    UNSPEC_LSX_VHSUBW_Q_D))]
-  "ISA_HAS_LSX"
-  "vhsubw.q.d\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V2DI")])
-
-(define_insn "lsx_vhsubw_qu_du"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
-       (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "f")
-                     (match_operand:V2DI 2 "register_operand" "f")]
-                    UNSPEC_LSX_VHSUBW_QU_DU))]
-  "ISA_HAS_LSX"
-  "vhsubw.qu.du\t%w0,%w1,%w2"
-  [(set_attr "type" "simd_int_arith")
-   (set_attr "mode" "V2DI")])
-
 (define_insn "lsx_vmaddwev_d_w<u>"
   [(set (match_operand:V2DI 0 "register_operand" "=f")
        (plus:V2DI
diff --git a/gcc/config/loongarch/predicates.md 
b/gcc/config/loongarch/predicates.md
index fd2d7b9ab55..8f5dfd34d6a 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -699,3 +699,19 @@ (define_special_predicate "vect_par_cnst_even_or_odd_half"
 
   return true;
 })
+
+;; PARALLEL for a vec_select that selects all the even elements of a vector
+;; of MODE.
+(define_special_predicate "vect_par_cnst_even_half"
+  (match_operand 0 "vect_par_cnst_even_or_odd_half")
+{
+  return INTVAL (XVECEXP (op, 0, 0)) == 0;
+})
+
+;; PARALLEL for a vec_select that selects all the odd elements of a vector
+;; of MODE.
+(define_special_predicate "vect_par_cnst_odd_half"
+  (match_operand 0 "vect_par_cnst_even_or_odd_half")
+{
+  return INTVAL (XVECEXP (op, 0, 0)) == 1;
+})
diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md
index 86fc14647e0..5c2cad44ef0 100644
--- a/gcc/config/loongarch/simd.md
+++ b/gcc/config/loongarch/simd.md
@@ -671,6 +671,39 @@ (define_expand 
"<simd_isa>_<x>v<optab>w<ev_od>_<simdfmt_w>_<simdfmt>u_<simdfmt>"
   DONE;
 })
 
+(define_insn "simd_h<optab>w_<mode>_<su>"
+  [(set (match_operand:<WVEC_HALF> 0 "register_operand" "=f")
+       (addsub:<WVEC_HALF>
+         (vec_select:<WVEC_HALF>
+           (any_extend:<WVEC>
+             (match_operand:IVEC 1 "register_operand" "f"))
+           (match_operand:<WVEC> 3 "vect_par_cnst_odd_half"))
+         (vec_select:<WVEC_HALF>
+           (any_extend:<WVEC>
+             (match_operand:IVEC 2 "register_operand" "f"))
+           (match_operand:<WVEC> 4 "vect_par_cnst_even_half"))))]
+  ""
+  "<x>vh<optab>w.<simdfmt_w><u>.<simdfmt><u>\t%<wu>0,%<wu>1,%<wu>2"
+  [(set_attr "type" "simd_int_arith")
+   (set_attr "mode" "<WVEC_HALF>")])
+
+(define_expand "<simd_isa>_<x>vh<optab>w_<simdfmt_w><u>_<simdfmt><u>"
+  [(match_operand:<WVEC_HALF> 0 "register_operand" "=f")
+   (match_operand:IVEC       1 "register_operand" " f")
+   (match_operand:IVEC       2 "register_operand" " f")
+   (any_extend (const_int 0))
+   (addsub (const_int 0) (const_int 0))]
+  ""
+{
+  int nelts = GET_MODE_NUNITS (<WVEC_HALF>mode);
+  rtx op3 = loongarch_gen_stepped_int_parallel (nelts, 1, 2);
+  rtx op4 = loongarch_gen_stepped_int_parallel (nelts, 0, 2);
+  rtx insn = gen_simd_h<optab>w_<mode>_<su> (operands[0], operands[1],
+                                            operands[2], op3, op4);
+  emit_insn (insn);
+  DONE;
+})
+
 ; For "historical" reason we need a punned version of q_d variants.
 (define_mode_iterator DIVEC [(V2DI "ISA_HAS_LSX") (V4DI "ISA_HAS_LASX")])
 
@@ -705,6 +738,21 @@ (define_expand "<simd_isa>_<optab>w<ev_od>_q_du_d_punned"
   DONE;
 })
 
+(define_expand "<simd_isa>_h<optab>w_q<u>_d<u>_punned"
+  [(match_operand:DIVEC 0 "register_operand" "=f")
+   (match_operand:DIVEC 1 "register_operand" "f")
+   (match_operand:DIVEC 2 "register_operand" "f")
+   (any_extend (const_int 0))
+   (addsub (const_int 0) (const_int 0))]
+  ""
+{
+  rtx t = gen_reg_rtx (<WVEC_HALF>mode);
+  emit_insn (gen_<simd_isa>_<x>vh<optab>w_q<u>_d<u> (t, operands[1],
+                                                    operands[2]));
+  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, t));
+  DONE;
+})
+
 ; The LoongArch SX Instructions.
 (include "lsx.md")
 
-- 
2.48.1

Reply via email to