During the analysis of program, it was discovered that the vector statement
"b[m] = a[n]" can achieve the corresponding function through the combination
of the "[x]vld + [x]vbitsel.v" instruction. The index operations during data
loading from memory addresses can be reduced by using the "vextrins.{b/h/w/d}"
or "xvinsve0.{w/d}" instructions for replacement, thus achieving optimization.

such as:
v4i32 foo (v4i32 a, v4i32 b)
{
  b[0] = a[0];
  return b;
}

before asm:
        la.local        $r12,.LC0  // {0,5,6,7}
        vinsgr2vr.d     $vr2,$r4,0
        vinsgr2vr.d     $vr1,$r6,0
        vinsgr2vr.d     $vr2,$r5,1
        vinsgr2vr.d     $vr1,$r7,1
        vld     $vr0,$r12,0
        vshuf.w $vr0,$vr1,$vr2
        vpickve2gr.du   $r4,$vr0,0
        vpickve2gr.du   $r5,$vr0,1
        jr      $r1

after asm:
        vinsgr2vr.d     $vr1,$r4,0
        vinsgr2vr.d     $vr0,$r6,0
        vinsgr2vr.d     $vr1,$r5,1
        vinsgr2vr.d     $vr0,$r7,1
        vextrins.w      $vr0,$vr1,0
        vpickve2gr.du   $r4,$vr0,0
        vpickve2gr.du   $r5,$vr0,1
        jr      $r1

For other types of optimization offects, please refer to the test cases.

gcc/ChangeLog:

        * config/loongarch/lasx.md (lasx_xvinsve0_<mode>_wd_0): Add
        template implementation.
        (lasx_xvinsve0_<mode>_wd_lasx): Dito.
        * config/loongarch/loongarch.cc
        (loongarch_expand_vec_perm_const): Add the processing of vselect
        vconcat with lsx.
        * config/loongarch/lsx.md (lsx_vextrins_<mode>_all):  Add template
        implemention.
        (lsx_vextrins_<lsxfmt>): Delete.
        (lsx_vextrins_<lsxfmt_f>): Modify.
        * config/loongarch/predicates.md (vextrins_parallel_operand): Add
        the check for "parallel".
        (vextrins_parallel_operand_lasx): Dito.

gcc/testsuite/ChangeLog:

        * gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-check.h: 
New test.
        * gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d-run.c: 
New test.
        * gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d.c: New 
test.
        * gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w-run.c: 
New test.
        * gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b-run.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-check.h: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d-run.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h-run.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w-run.c: New 
test.
        * gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w.c: New 
test.
---
 gcc/config/loongarch/lasx.md                  |  84 +++++++++++
 gcc/config/loongarch/loongarch.cc             |   7 +-
 gcc/config/loongarch/lsx.md                   |  52 ++++++-
 gcc/config/loongarch/predicates.md            |  72 +++++++++
 .../lasx/lasx-vec-optimize-xvbitsel-check.h   |  90 +++++++++++
 .../lasx/lasx-vec-optimize-xvbitsel-d-run.c   |  37 +++++
 .../lasx/lasx-vec-optimize-xvbitsel-d.c       |  33 ++++
 .../lasx/lasx-vec-optimize-xvbitsel-w-run.c   |  49 ++++++
 .../lasx/lasx-vec-optimize-xvbitsel-w.c       |  45 ++++++
 .../lsx/lsx-vec-optimize-vbitsel-b-run.c      |  54 +++++++
 .../vector/lsx/lsx-vec-optimize-vbitsel-b.c   |  52 +++++++
 .../lsx/lsx-vec-optimize-vbitsel-check.h      | 142 ++++++++++++++++++
 .../lsx/lsx-vec-optimize-vbitsel-d-run.c      |  31 ++++
 .../vector/lsx/lsx-vec-optimize-vbitsel-d.c   |  29 ++++
 .../lsx/lsx-vec-optimize-vbitsel-h-run.c      |  38 +++++
 .../vector/lsx/lsx-vec-optimize-vbitsel-h.c   |  36 +++++
 .../lsx/lsx-vec-optimize-vbitsel-w-run.c      |  37 +++++
 .../vector/lsx/lsx-vec-optimize-vbitsel-w.c   |  33 ++++
 18 files changed, 913 insertions(+), 8 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-check.h
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-check.h
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w-run.c
 create mode 100644 
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w.c

diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
index 23ba70c97dc..d9c057f4c6d 100644
--- a/gcc/config/loongarch/lasx.md
+++ b/gcc/config/loongarch/lasx.md
@@ -3476,6 +3476,90 @@ (define_insn "lasx_xvinsve0_<lasxfmt_f>_scalar"
   [(set_attr "type" "simd_insert")
    (set_attr "mode" "<MODE>")])
 
+;; Select the 0th element for insertion, such as b[m] = a[0].
+(define_insn_and_split "lasx_xvinsve0_<mode>_wd_0"
+  [(set (match_operand:LASX_WD 0 "register_operand" "=f")
+    (vec_select:LASX_WD
+      (vec_concat:<VEMODE256>
+      (match_operand:LASX_WD 1 "register_operand" "f")
+      (match_operand:LASX_WD 2 "register_operand" "0"))
+      (match_operand:LASX_WD 3 "vextrins_parallel_operand")))]
+  "ISA_HAS_LASX"
+  "#"
+  "&&"
+  [(set (match_dup 0)
+       (unspec:LASX_WD[(match_dup 2)
+                       (match_dup 1)
+                       (match_dup 4)]
+                       UNSPEC_LASX_XVINSVE0))]
+  {
+    int dst_idx = -1;
+    int nunits = XVECLEN (operands[3], 0);
+
+    for (int i = 0; i< nunits; i++)
+    {
+       int val = INTVAL (XVECEXP (operands[3], 0, i));
+       if ( val < nunits)
+       {
+           dst_idx = i;
+           break;
+       }
+    }
+    operands[4] = GEN_INT (dst_idx);
+    emit_insn (gen_lasx_xvinsve0_<lasxfmt_f> (operands[0],
+               operands[2], operands[1], operands[4]));
+    DONE;
+  }
+  [(set_attr "type" "simd_insert")
+   (set_attr "mode" "<MODE>")])
+
+;; Since xvinsve0.{w/d} only supports inserting the lowest pisitioned element,
+;; the insertion of non-zero position elements is achieved by using "xvpickve.{
+;; w/d} + xvinsve0.{w/d}".
+(define_insn_and_split "lasx_xvinsve0_<mode>_wd_lasx"
+  [(set (match_operand:LASX_WD 0 "register_operand" "=f")
+    (vec_select:LASX_WD
+      (vec_concat:<VEMODE256>
+      (match_operand:LASX_WD 1 "register_operand" "f")
+      (match_operand:LASX_WD 2 "register_operand" "0"))
+      (match_operand:LASX_WD 3 "vextrins_parallel_operand_lasx")))]
+  "ISA_HAS_LASX"
+  "#"
+  "&&"
+  [(set (match_dup 4)
+       (unspec:LASX_WD[(match_dup 1) (match_dup 5)] UNSPEC_LASX_XVPICKVE))
+   (set (match_dup 0)
+       (unspec:LASX_WD[(match_dup 2)
+                       (match_dup 4)
+                       (match_dup 6)]
+                       UNSPEC_LASX_XVINSVE0))]
+  {
+    int src_idx = -1, dst_idx = -1;
+    int nunits = XVECLEN (operands[3], 0);
+
+    for (int i = 0; i< nunits; i++)
+    {
+       int val = INTVAL (XVECEXP (operands[3], 0, i));
+       if ( val < nunits)
+       {
+           src_idx = val;
+           dst_idx = i;
+           break;
+       }
+    }
+
+    operands[4] = gen_reg_rtx (<MODE>mode);
+    operands[5] = GEN_INT (src_idx);
+    operands[6] = GEN_INT (dst_idx);
+    emit_insn (gen_lasx_xvpickve_<lasxfmt_f> (operands[4],
+                       operands[1],operands[5]));
+    emit_insn (gen_lasx_xvinsve0_<lasxfmt_f> (operands[0],
+                       operands[2], operands[4], operands[6]));
+    DONE;
+  }
+  [(set_attr "type" "simd_insert")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "lasx_xvpickve_<lasxfmt_f>"
   [(set (match_operand:LASX_WD 0 "register_operand" "=f")
        (unspec:LASX_WD [(match_operand:LASX_WD 1 "register_operand" "f")
diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index bf401602394..3001d552574 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -9687,9 +9687,7 @@ loongarch_expand_vec_perm_const (struct expand_vec_perm_d 
*d)
   unsigned int remapped[MAX_VECT_LEN];
   unsigned char perm2[MAX_VECT_LEN];
 
-  if (GET_MODE_SIZE (d->vmode) == 16)
-    return loongarch_expand_lsx_shuffle (d);
-  else
+  if (GET_MODE_SIZE (d->vmode) == 16 || GET_MODE_SIZE (d->vmode) == 32)
     {
       if (d->one_vector_p)
        {
@@ -9716,6 +9714,9 @@ loongarch_expand_vec_perm_const (struct expand_vec_perm_d 
*d)
            return true;
        }
 
+      if (GET_MODE_SIZE (d->vmode) == 16)
+       return loongarch_expand_lsx_shuffle (d);
+
       if (loongarch_is_imm_set_shuffle (d))
        return true;
 
diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md
index 051ce18bd7e..0baaf156ec6 100644
--- a/gcc/config/loongarch/lsx.md
+++ b/gcc/config/loongarch/lsx.md
@@ -169,7 +169,9 @@ (define_mode_attr VTRUNCMODE
 
 ;; Double-sized Vector MODE with same element type. "Vector, Enlarged-MODE"
 (define_mode_attr VEMODE
-  [(V4SF "V8SF")
+  [(V16QI "V32QI")
+   (V8HI "V16HI")
+   (V4SF "V8SF")
    (V4SI "V8SI")
    (V2DI "V4DI")
    (V2DF "V4DF")])
@@ -1467,6 +1469,46 @@ (define_insn "lsx_vilvl_d_f"
   [(set_attr "type" "simd_permute")
    (set_attr "mode" "V2DF")])
 
+;; Perform the insertion operation for any element of the vector.
+(define_insn_and_split "lsx_vextrins_<mode>_all"
+  [(set (match_operand:LSX 0 "register_operand" "=f")
+    (vec_select:LSX
+      (vec_concat:<VEMODE>
+      (match_operand:LSX 1 "register_operand" "f")
+      (match_operand:LSX 2 "register_operand" "0"))
+      (match_operand:LSX 3 "vextrins_parallel_operand")))]
+  "ISA_HAS_LSX"
+  "#"
+  "&&"
+  [(set (match_dup 0)
+       (unspec:LSX[(match_dup 2)
+                   (match_dup 1)
+                   (match_dup 4)]
+                   UNSPEC_LSX_VEXTRINS))]
+  {
+    int src_idx = -1, dst_idx = -1;
+    int nunits = XVECLEN (operands[3], 0);
+
+    for (int i = 0; i< nunits; i++)
+    {
+       int val = INTVAL (XVECEXP (operands[3], 0, i));
+       if ( val < nunits)
+       {
+       src_idx = val;
+       dst_idx = i;
+       break;
+       }
+    }
+
+    int imm = (dst_idx << 4) | src_idx;
+    operands[4] = GEN_INT (imm);
+    emit_insn (gen_lsx_vextrins_<lsxfmt_f> (operands[0], operands[2],
+               operands[1], operands[4]));
+    DONE;
+  }
+  [(set_attr "type" "simd_insert")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "smax<mode>3"
   [(set (match_operand:ILSX 0 "register_operand" "=f,f")
        (smax:ILSX (match_operand:ILSX 1 "register_operand" "f,f")
@@ -2213,10 +2255,10 @@ (define_insn "lsx_vbsll_<lsxfmt>"
   [(set_attr "type" "simd_shift")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "lsx_vextrins_<lsxfmt>"
-  [(set (match_operand:ILSX 0 "register_operand" "=f")
-       (unspec:ILSX [(match_operand:ILSX 1 "register_operand" "0")
-                     (match_operand:ILSX 2 "register_operand" "f")
+(define_insn "lsx_vextrins_<lsxfmt_f>"
+  [(set (match_operand:LSX 0 "register_operand" "=f")
+       (unspec:LSX[(match_operand:LSX 1 "register_operand" "0")
+                     (match_operand:LSX 2 "register_operand" "f")
                      (match_operand 3 "const_uimm8_operand" "")]
                     UNSPEC_LSX_VEXTRINS))]
   "ISA_HAS_LSX"
diff --git a/gcc/config/loongarch/predicates.md 
b/gcc/config/loongarch/predicates.md
index ced79fe6f50..818b42ad2f9 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -756,3 +756,75 @@ (define_special_predicate "vect_par_cnst_high_half"
 {
   return loongarch_check_vect_par_cnst_half (op, mode, true);;
 })
+
+;; Return true if OP is a PARALLEL suitable for insert instructions.
+;; It selects exactly one element from the first operand (index < NUNITS)
+;; and the remaining elements from the second operand (index = NUNITS +i).
+(define_special_predicate "vextrins_parallel_operand"
+  (match_code "parallel")
+{
+  int nunits = XVECLEN (op, 0);
+  int nelts = GET_MODE_NUNITS (mode);
+  int size = GET_MODE_BITSIZE (mode);
+
+  if (!known_eq (nelts, nunits))
+    return false;
+
+  int src_found = -1, dst_found = -1;
+  for (int i = 0; i < nunits; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i);
+      if (!CONST_INT_P (elt))
+       return false;
+
+      int val = INTVAL (elt);
+      if (val < nunits)
+      {
+       if (src_found >= 0)
+           return false;
+       src_found = val;
+       dst_found = i;
+      }
+      else if (val != i + nunits)
+       return false;
+    }
+
+  /* 0->1 and 1->0 use vilvl.d or vilvh.d, not vextrins.d.  */
+  if (nunits == 2 && (src_found ^ dst_found) && src_found >= 0)
+    return  false;
+
+  return size == 256 ? src_found ==0 : src_found >= 0;
+})
+
+;; Processing is not the insertion of a 256 bit vector
+;; by selecting the lowest bit element.
+(define_special_predicate "vextrins_parallel_operand_lasx"
+  (match_code "parallel")
+{
+  int nunits = XVECLEN (op, 0);
+  int nelts = GET_MODE_NUNITS (mode);
+  int size = GET_MODE_BITSIZE (mode);
+
+  if (!known_eq (nelts, nunits))
+    return false;
+
+  int src_found = -1;
+  for (int i = 0; i < nunits; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i);
+      if (!CONST_INT_P (elt))
+       return false;
+
+      int val = INTVAL (elt);
+      if (val < nunits)
+      {
+       if (src_found >= 0)
+           return false;
+       src_found = val;
+      }
+      else if (val != i + nunits)
+       return false;
+      }
+
+  return size == 256 && src_found > 0 ;
+})
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-check.h
 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-check.h
new file mode 100644
index 00000000000..cc829478167
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-check.h
@@ -0,0 +1,90 @@
+#include <stdio.h>
+
+/* ---------- 测试宏 ---------- */
+#define TEST_F32(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v8f32 a = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };           \
+      v8f32 b = { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f };   \
+      v8f32 r = func (a, b);                                                  \
+      float exp[8];                                                           \
+      for (int i = 0; i < 8; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 8; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_S32(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v8i32 a = { 1, 2, 3, 4, 5, 6, 7, 8 };                                   \
+      v8i32 b = { 10, 11, 12, 13, 14, 15, 16, 17 };                           \
+      v8i32 r = func (a, b);                                                  \
+      int exp[8];                                                             \
+      for (int i = 0; i < 8; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 8; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %d, expected %d\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_F64(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v4f64 a = { 1.0, 2.0, 3.0, 4.0 };                                       \
+      v4f64 b = { 10.0, 11.0, 12.0, 13.0 };                                   \
+      v4f64 r = func (a, b);                                                  \
+      double exp[4];                                                          \
+      for (int i = 0; i < 4; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 4; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_S64(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v4i64 a = { 1, 2, 3, 4 };                                               \
+      v4i64 b = { 10, 11, 12, 13 };                                           \
+      v4i64 r = func (a, b);                                                  \
+      long long exp[4];                                                       \
+      for (int i = 0; i < 4; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 4; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %lld, expected %lld\n",     \
+                      #func, i, (long long)r[i], (long long)exp[i]);          \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d-run.c
new file mode 100644
index 00000000000..8d0df935b54
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d-run.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-mlasx -O3" } */
+
+#include "lasx-vec-optimize-xvbitsel-check.h"
+#include "lasx-vec-optimize-xvbitsel-d.c"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(name, type, m, n)                                      \
+  TEST_##name (foo##m##_##n##_##type, m, n);
+
+#define RUN_ROW_TESTS(name, type, m)                                          \
+  RUN_TEST_FOR_N (name, type, m, 0)                                           \
+  RUN_TEST_FOR_N (name, type, m, 1)                                           \
+  RUN_TEST_FOR_N (name, type, m, 2)                                           \
+  RUN_TEST_FOR_N (name, type, m, 3)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* 测试 v4i64 系列 */
+  RUN_ROW_TESTS (S64, v4i64, 0);
+  RUN_ROW_TESTS (S64, v4i64, 1);
+  RUN_ROW_TESTS (S64, v4i64, 2);
+  RUN_ROW_TESTS (S64, v4i64, 3);
+
+  /* 测试 v4i64 系列 */
+  RUN_ROW_TESTS (F64, v4f64, 0);
+  RUN_ROW_TESTS (F64, v4f64, 1);
+  RUN_ROW_TESTS (F64, v4f64, 2);
+  RUN_ROW_TESTS (F64, v4f64, 3);
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d.c
new file mode 100644
index 00000000000..70dbb8ee3c2
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-d.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+/* { dg-final { scan-assembler-times "xvinsve0.d" 32 } } */
+
+#include <lasxintrin.h>
+
+#define FUNC_NAME(m, n, type) foo##m##_##n##_##type
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n, type) (type a,    \
+                                                                   type b)    \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_D(m)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v4i64, m, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i64, m, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i64, m, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i64, m, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f64, m, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f64, m, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f64, m, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f64, m, 3)
+
+#define FOR_J()                                                               \
+  FOR_D (0)                                                                   \
+  FOR_D (1)                                                                   \
+  FOR_D (2)                                                                   \
+  FOR_D (3)
+
+FOR_J ()
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w-run.c
new file mode 100644
index 00000000000..c1400566067
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w-run.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-mlasx -O3" } */
+
+#include "lasx-vec-optimize-xvbitsel-check.h"
+#include "lasx-vec-optimize-xvbitsel-w.c"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(name, type, m, n)                                      \
+  TEST_##name (foo##m##_##n##_##type, m, n);
+
+#define RUN_ROW_TESTS(name, type, m)                                          \
+  RUN_TEST_FOR_N (name, type, m, 0)                                           \
+  RUN_TEST_FOR_N (name, type, m, 1)                                           \
+  RUN_TEST_FOR_N (name, type, m, 2)                                           \
+  RUN_TEST_FOR_N (name, type, m, 3)                                           \
+  RUN_TEST_FOR_N (name, type, m, 4)                                           \
+  RUN_TEST_FOR_N (name, type, m, 5)                                           \
+  RUN_TEST_FOR_N (name, type, m, 6)                                           \
+  RUN_TEST_FOR_N (name, type, m, 7)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* 测试 v8i32 系列 */
+  RUN_ROW_TESTS (S32, v8i32, 0);
+  RUN_ROW_TESTS (S32, v8i32, 1);
+  RUN_ROW_TESTS (S32, v8i32, 2);
+  RUN_ROW_TESTS (S32, v8i32, 3);
+  RUN_ROW_TESTS (S32, v8i32, 4);
+  RUN_ROW_TESTS (S32, v8i32, 5);
+  RUN_ROW_TESTS (S32, v8i32, 6);
+  RUN_ROW_TESTS (S32, v8i32, 7);
+
+  /* 测试 v8f32 系列 */
+  RUN_ROW_TESTS (F32, v8f32, 0);
+  RUN_ROW_TESTS (F32, v8f32, 1);
+  RUN_ROW_TESTS (F32, v8f32, 2);
+  RUN_ROW_TESTS (F32, v8f32, 3);
+  RUN_ROW_TESTS (F32, v8f32, 4);
+  RUN_ROW_TESTS (F32, v8f32, 5);
+  RUN_ROW_TESTS (F32, v8f32, 6);
+  RUN_ROW_TESTS (F32, v8f32, 7);
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w.c
new file mode 100644
index 00000000000..5ac9f0d0992
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-vec-optimize-xvbitsel-w.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+/* { dg-final { scan-assembler-times "xvinsve0.w" 128 } } */
+
+#include <lasxintrin.h>
+
+#define FUNC_NAME(m, n, type) foo##m##_##n##_##type
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n, type) (type a,    \
+                                                                   type b)    \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_W(m)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 4)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 5)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 6)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i32, m, 7)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 4)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 5)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 6)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8f32, m, 7)
+
+#define FOR_I()                                                               \
+  FOR_W (0)                                                                   \
+  FOR_W (1)                                                                   \
+  FOR_W (2)                                                                   \
+  FOR_W (3)                                                                   \
+  FOR_W (4)                                                                   \
+  FOR_W (5)                                                                   \
+  FOR_W (6)                                                                   \
+  FOR_W (7)
+
+FOR_I ()
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b-run.c
new file mode 100644
index 00000000000..0ea8f84e365
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b-run.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+/* { dg-options "-mlsx -O3" } */
+
+#include "lsx-vec-optimize-vbitsel-b.c"
+#include "lsx-vec-optimize-vbitsel-check.h"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(m, n) TEST_Q8 (foo##m##_##n, m, n);
+
+#define RUN_ROW_TESTS(m)                                                      \
+  RUN_TEST_FOR_N (m, 0)                                                       \
+  RUN_TEST_FOR_N (m, 1)                                                       \
+  RUN_TEST_FOR_N (m, 2)                                                       \
+  RUN_TEST_FOR_N (m, 3)                                                       \
+  RUN_TEST_FOR_N (m, 4)                                                       \
+  RUN_TEST_FOR_N (m, 5)                                                       \
+  RUN_TEST_FOR_N (m, 6)                                                       \
+  RUN_TEST_FOR_N (m, 7)                                                       \
+  RUN_TEST_FOR_N (m, 8)                                                       \
+  RUN_TEST_FOR_N (m, 9)                                                       \
+  RUN_TEST_FOR_N (m, 10)                                                      \
+  RUN_TEST_FOR_N (m, 11)                                                      \
+  RUN_TEST_FOR_N (m, 12)                                                      \
+  RUN_TEST_FOR_N (m, 13)                                                      \
+  RUN_TEST_FOR_N (m, 14)                                                      \
+  RUN_TEST_FOR_N (m, 15)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* v16i8 */
+  RUN_ROW_TESTS (0)
+  RUN_ROW_TESTS (1)
+  RUN_ROW_TESTS (2)
+  RUN_ROW_TESTS (3)
+  RUN_ROW_TESTS (4)
+  RUN_ROW_TESTS (5)
+  RUN_ROW_TESTS (6)
+  RUN_ROW_TESTS (7)
+  RUN_ROW_TESTS (8)
+  RUN_ROW_TESTS (9)
+  RUN_ROW_TESTS (10)
+  RUN_ROW_TESTS (11)
+  RUN_ROW_TESTS (12)
+  RUN_ROW_TESTS (13)
+  RUN_ROW_TESTS (14)
+  RUN_ROW_TESTS (15)
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b.c
new file mode 100644
index 00000000000..3afe90ae6c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-b.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+/* { dg-final { scan-assembler-times "vextrins.b" 256 } } */
+
+#include <lsxintrin.h>
+
+#define FUNC_NAME(m, n) foo##m##_##n
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n) (type a, type b)  \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_J(i)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 4)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 5)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 6)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 7)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 8)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 9)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 10)                                      \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 11)                                      \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 12)                                      \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 13)                                      \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 14)                                      \
+  DEFINE_FUNC_BYTE_INSERT (v16i8, i, 15)
+
+#define FOR_I()                                                               \
+  FOR_J (0)                                                                   \
+  FOR_J (1)                                                                   \
+  FOR_J (2)                                                                   \
+  FOR_J (3)                                                                   \
+  FOR_J (4)                                                                   \
+  FOR_J (5)                                                                   \
+  FOR_J (6)                                                                   \
+  FOR_J (7)                                                                   \
+  FOR_J (8)                                                                   \
+  FOR_J (9)                                                                   \
+  FOR_J (10)                                                                  \
+  FOR_J (11)                                                                  \
+  FOR_J (12)                                                                  \
+  FOR_J (13)                                                                  \
+  FOR_J (14)                                                                  \
+  FOR_J (15)
+
+FOR_I ()
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-check.h
 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-check.h
new file mode 100644
index 00000000000..9aaa3d99a6f
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-check.h
@@ -0,0 +1,142 @@
+#include <stdio.h>
+
+/* 测试宏 */
+#define TEST_Q8(func, idx, ins_idx)                                           \
+  do                                                                          \
+    {                                                                         \
+      v16i8 a, b;                                                             \
+      for (int i = 0; i < 16; i++)                                            \
+        {                                                                     \
+          a[i] = i;                                                           \
+          b[i] = i + 16;                                                      \
+        }                                                                     \
+      v16i8 r = func (a, b);                                                  \
+      signed char exp[16];                                                    \
+      for (int i = 0; i < 16; i++)                                            \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 16; i++)                                            \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_H16(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v8i16 a, b;                                                             \
+      for (int i = 0; i < 8; i++)                                             \
+        {                                                                     \
+          a[i] = i;                                                           \
+          b[i] = i + 8;                                                       \
+        }                                                                     \
+      v8i16 r = func (a, b);                                                  \
+      unsigned short exp[8];                                                  \
+      for (int i = 0; i < 8; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 8; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_F32(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v4f32 a = { 1.0f, 2.0f, 3.0f, 4.0f };                                   \
+      v4f32 b = { 10.0f, 11.0f, 12.0f, 13.0f };                               \
+      v4f32 r = func (a, b);                                                  \
+      float exp[4];                                                           \
+      for (int i = 0; i < 4; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 4; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_S32(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v4i32 a = { 1, 2, 3, 4 };                                               \
+      v4i32 b = { 10, 11, 12, 13 };                                           \
+      v4i32 r = func (a, b);                                                  \
+      int exp[4];                                                             \
+      for (int i = 0; i < 4; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 4; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %d, expected %d\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_F64(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v2f64 a = { 1.0, 2.0 };                                                 \
+      v2f64 b = { 3.0, 4.0 };                                                 \
+      v2f64 r = func (a, b);                                                  \
+      double exp[2];                                                          \
+      for (int i = 0; i < 2; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 2; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %f, expected %f\n", #func,  \
+                      i, r[i], exp[i]);                                       \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
+
+#define TEST_S64(func, idx, ins_idx)                                          \
+  do                                                                          \
+    {                                                                         \
+      v2i64 a = { 1, 2 };                                                     \
+      v2i64 b = { 3, 4 };                                                     \
+      v2i64 r = func (a, b);                                                  \
+      long long exp[2];                                                       \
+      for (int i = 0; i < 2; i++)                                             \
+        exp[i] = b[i];                                                        \
+      exp[ins_idx] = a[idx];                                                  \
+      for (int i = 0; i < 2; i++)                                             \
+        {                                                                     \
+          if (r[i] != exp[i])                                                 \
+            {                                                                 \
+              printf ("%s failed at index %d: got %lld, expected %lld\n",     \
+                      #func, i, (long long)r[i], (long long)exp[i]);          \
+              fail = 1;                                                       \
+            }                                                                 \
+        }                                                                     \
+    }                                                                         \
+  while (0)
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d-run.c
new file mode 100644
index 00000000000..a0617474573
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d-run.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-mlsx -O3" } */
+
+#include "lsx-vec-optimize-vbitsel-check.h"
+#include "lsx-vec-optimize-vbitsel-d.c"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(name, type, m, n)                                      \
+  TEST_##name (foo##m##_##n##type, m, n);
+
+#define RUN_ROW_TESTS(name, type, m)                                          \
+  RUN_TEST_FOR_N (name, type, m, 0)                                           \
+  RUN_TEST_FOR_N (name, type, m, 1)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* v2i64 */
+  RUN_ROW_TESTS (S64, v2i64, 0)
+  RUN_ROW_TESTS (S64, v2i64, 1)
+
+  /* v2i64 */
+  RUN_ROW_TESTS (F64, v2f64, 0)
+  RUN_ROW_TESTS (F64, v2f64, 1)
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d.c
new file mode 100644
index 00000000000..860cb09bd6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-d.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+/* { dg-final { scan-assembler-times "vilvl.d" 2 } } */
+/* { dg-final { scan-assembler-times "vilvh.d" 2 } } */
+/* { dg-final { scan-assembler-times "vextrins.d" 4 } } */
+
+#include <lsxintrin.h>
+
+#define FUNC_NAME(m, n, type) foo##m##_##n##type
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n, type) (type a,    \
+                                                                   type b)    \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_J(i)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v2i64, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v2i64, i, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v2f64, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v2f64, i, 1)
+
+#define FOR_I()                                                               \
+  FOR_J (0)                                                                   \
+  FOR_J (1)
+
+FOR_I ()
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h-run.c
new file mode 100644
index 00000000000..e7c50eeb196
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h-run.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-mlsx -O3" } */
+
+#include "lsx-vec-optimize-vbitsel-check.h"
+#include "lsx-vec-optimize-vbitsel-h.c"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(m, n) TEST_H16 (foo##m##_##n, m, n);
+
+#define RUN_ROW_TESTS(m)                                                      \
+  RUN_TEST_FOR_N (m, 0)                                                       \
+  RUN_TEST_FOR_N (m, 1)                                                       \
+  RUN_TEST_FOR_N (m, 2)                                                       \
+  RUN_TEST_FOR_N (m, 3)                                                       \
+  RUN_TEST_FOR_N (m, 4)                                                       \
+  RUN_TEST_FOR_N (m, 5)                                                       \
+  RUN_TEST_FOR_N (m, 6)                                                       \
+  RUN_TEST_FOR_N (m, 7)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* v16i8 */
+  RUN_ROW_TESTS (0)
+  RUN_ROW_TESTS (1)
+  RUN_ROW_TESTS (2)
+  RUN_ROW_TESTS (3)
+  RUN_ROW_TESTS (4)
+  RUN_ROW_TESTS (5)
+  RUN_ROW_TESTS (6)
+  RUN_ROW_TESTS (7)
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h.c
new file mode 100644
index 00000000000..0cacfeff518
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-h.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+/* { dg-final { scan-assembler-times "vextrins.h" 64 } } */
+
+#include <lsxintrin.h>
+
+#define FUNC_NAME(m, n) foo##m##_##n
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n) (type a, type b)  \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_J(i)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 4)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 5)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 6)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v8i16, i, 7)
+
+#define FOR_I()                                                               \
+  FOR_J (0)                                                                   \
+  FOR_J (1)                                                                   \
+  FOR_J (2)                                                                   \
+  FOR_J (3)                                                                   \
+  FOR_J (4)                                                                   \
+  FOR_J (5)                                                                   \
+  FOR_J (6)                                                                   \
+  FOR_J (7)
+
+FOR_I ()
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w-run.c
 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w-run.c
new file mode 100644
index 00000000000..cf8e4a360ae
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w-run.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-mlsx -O3" } */
+
+#include "lsx-vec-optimize-vbitsel-check.h"
+#include "lsx-vec-optimize-vbitsel-w.c"
+#include <stdio.h>
+
+#define RUN_TEST_FOR_N(name, type, m, n)                                      \
+  TEST_##name (foo##m##_##n##type, m, n);
+
+#define RUN_ROW_TESTS(name, type, m)                                          \
+  RUN_TEST_FOR_N (name, type, m, 0)                                           \
+  RUN_TEST_FOR_N (name, type, m, 1)                                           \
+  RUN_TEST_FOR_N (name, type, m, 2)                                           \
+  RUN_TEST_FOR_N (name, type, m, 3)
+
+int
+main ()
+{
+  int fail = 0;
+
+  /* v4i32 */
+  RUN_ROW_TESTS (S32, v4i32, 0)
+  RUN_ROW_TESTS (S32, v4i32, 1)
+  RUN_ROW_TESTS (S32, v4i32, 2)
+  RUN_ROW_TESTS (S32, v4i32, 3)
+
+  /* v4f32 */
+  RUN_ROW_TESTS (F32, v4f32, 0)
+  RUN_ROW_TESTS (F32, v4f32, 1)
+  RUN_ROW_TESTS (F32, v4f32, 2)
+  RUN_ROW_TESTS (F32, v4f32, 3)
+
+  if (fail == 0)
+    printf ("All tests passed.\n");
+  return fail;
+}
diff --git 
a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w.c
new file mode 100644
index 00000000000..739ca026178
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vec-optimize-vbitsel-w.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+/* { dg-final { scan-assembler-times "vextrins.w" 32 } } */
+
+#include <lsxintrin.h>
+
+#define FUNC_NAME(m, n, type) foo##m##_##n##type
+
+#define DEFINE_FUNC_BYTE_INSERT(type, m, n)                                   \
+  __attribute__ ((noinline, noclone)) type FUNC_NAME (m, n, type) (type a,    \
+                                                                   type b)    \
+  {                                                                           \
+    b[n] = a[m];                                                              \
+    return b;                                                                 \
+  }
+
+#define FOR_J(i)                                                              \
+  DEFINE_FUNC_BYTE_INSERT (v4i32, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i32, i, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i32, i, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4i32, i, 3)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f32, i, 0)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f32, i, 1)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f32, i, 2)                                       \
+  DEFINE_FUNC_BYTE_INSERT (v4f32, i, 3)
+
+#define FOR_I()                                                               \
+  FOR_J (0)                                                                   \
+  FOR_J (1)                                                                   \
+  FOR_J (2)                                                                   \
+  FOR_J (3)
+
+FOR_I ()
-- 
2.20.1

Reply via email to