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