For Larch, the lower 64 bits of the 128-bit vector register overlap with
the 64-bit floating-point register, and the lower 128 bits of the 256
bit vector register overlap with the 128-bit vector register. so can be
perform vector width reduction operation on the *vpickve2gr instruction.
1. for [x]vpickve2gr.w, when select the lower 32 bits and the upper
32 bits of the lower 64 bits of the vector register, replace to
movfr2gr.s and movfrh2gr.s.
2. for [x]vpickve2gr.d, when select the lower 64 bits of the vector
register, replace to movfr2gr.d.
3. for xvpickve2gr.w, when select the 3rd or 4th 4-byte data of the
vector register, replace to vpickve2gr.w.
4. for xvpickve2gr.d, when select the 2nd 8-byte data of the vector
register, replace to vpickve2gr.d.
gcc/ChangeLog:
* config/loongarch/lasx.md
(lasx_xvpickve2gr_w<u>): Add new condition.
(lasx_xvpickve2gr_wu): Add new condition.
(lasx_xvpickve2gr_w): Add new condition.
* config/loongarch/lsx.md
(lsx_vpickve2gr_<lsxfmt_f><u>): Add new condition.
(lsx_vpickve2gr_<lsxfmt_f>u): Add new condition.
(lsx_vpickve2gr_<lsxfmt_f>): Add new condition.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/vector/lasx/lasx-builtin.c: Adjust test.
* gcc.target/loongarch/vector/lasx/vect-extract-256-128.c:
Adjust test.
* gcc.target/loongarch/vector/lsx/lsx-builtin.c: Adjust test.
* gcc.target/loongarch/vector/lasx/lasx-xvpickve2gr-1.c:
New test.
* gcc.target/loongarch/vector/lsx/lsx-vpickve2gr-1.c: New test.
---
gcc/config/loongarch/lasx.md | 45 +++++++++++++++--
gcc/config/loongarch/lsx.md | 35 +++++++++++--
.../loongarch/vector/lasx/lasx-builtin.c | 8 +--
.../vector/lasx/lasx-xvpickve2gr-1.c | 50 +++++++++++++++++++
.../vector/lasx/vect-extract-256-128.c | 12 ++---
.../loongarch/vector/lsx/lsx-builtin.c | 2 +-
.../loongarch/vector/lsx/lsx-vpickve2gr-1.c | 34 +++++++++++++
7 files changed, 167 insertions(+), 19 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-xvpickve2gr-1.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vpickve2gr-1.c
diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
index 23ba70c97dc..040e46e5287 100644
--- a/gcc/config/loongarch/lasx.md
+++ b/gcc/config/loongarch/lasx.md
@@ -573,7 +573,16 @@ (define_insn "lasx_xvpickve2gr_d<u>"
(match_operand:V4DI 1 "register_operand" "f")
(parallel [(match_operand 2 "const_0_to_3_operand" "")]))))]
"ISA_HAS_LASX"
- "xvpickve2gr.d<u>\t%0,%u1,%2"
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val == 0)
+ return "movfr2gr.d\t%0,%1";
+ else if (val == 1)
+ return "vpickve2gr.d\t%0,%w1,%2";
+
+ return "xvpickve2gr.d<u>\t%0,%u1,%2";
+}
[(set_attr "type" "simd_copy")
(set_attr "mode" "V4DI")])
@@ -3109,17 +3118,45 @@ (define_insn "lasx_xvreplve_<lasxfmt_f>"
[(set_attr "type" "simd_splat")
(set_attr "mode" "<MODE>")])
-(define_insn "lasx_xvpickve2gr_w<u>"
+(define_insn "lasx_xvpickve2gr_wu"
[(set (match_operand:SI 0 "register_operand" "=r")
- (any_extend:SI
+ (zero_extend:SI
(vec_select:SI
(match_operand:V8SI 1 "register_operand" "f")
(parallel [(match_operand 2 "const_0_to_7_operand" "")]))))]
"ISA_HAS_LASX"
- "xvpickve2gr.w<u>\t%0,%u1,%2"
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val <= 3)
+ return "vpickve2gr.wu\t%0,%w1,%2";
+
+ return "xvpickve2gr.wu\t%0,%u1,%2";
+}
[(set_attr "type" "simd_copy")
(set_attr "mode" "V8SI")])
+(define_insn "lasx_xvpickve2gr_w"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (vec_select:SI
+ (match_operand:V8SI 1 "register_operand" "f")
+ (parallel [(match_operand 2 "const_0_to_7_operand" "")]))))]
+ "ISA_HAS_LASX"
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val == 0)
+ return "movfr2gr.s\t%0,%1";
+ else if (val == 1)
+ return "movfrh2gr.s\t%0,%1";
+ else if (val == 2 || val == 3)
+ return "vpickve2gr.w\t%0,%w1,%2";
+
+ return "xvpickve2gr.w\t%0,%u1,%2";
+}
+ [(set_attr "type" "simd_copy")
+ (set_attr "mode" "V8SI")])
(define_insn "lasx_xvmskgez_b"
[(set (match_operand:V32QI 0 "register_operand" "=f")
diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md
index 051ce18bd7e..9c539cdc047 100644
--- a/gcc/config/loongarch/lsx.md
+++ b/gcc/config/loongarch/lsx.md
@@ -459,14 +459,34 @@ (define_insn "lsx_vpickve2gr_<lsxfmt><u>"
[(set_attr "type" "simd_copy")
(set_attr "mode" "<MODE>")])
-(define_insn "lsx_vpickve2gr_<lsxfmt_f><u>"
+(define_insn "lsx_vpickve2gr_<lsxfmt_f>u"
[(set (match_operand:<UNITMODE> 0 "register_operand" "=r")
- (any_extend:<UNITMODE>
+ (zero_extend:<UNITMODE>
(vec_select:<UNITMODE>
(match_operand:LSX_W 1 "register_operand" "f")
(parallel [(match_operand 2 "const_<indeximm>_operand" "")]))))]
"ISA_HAS_LSX"
- "vpickve2gr.<lsxfmt><u>\t%0,%w1,%2"
+ "vpickve2gr.<lsxfmt>u\t%0,%w1,%2"
+ [(set_attr "type" "simd_copy")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "lsx_vpickve2gr_<lsxfmt_f>"
+ [(set (match_operand:<UNITMODE> 0 "register_operand" "=r")
+ (sign_extend:<UNITMODE>
+ (vec_select:<UNITMODE>
+ (match_operand:LSX_W 1 "register_operand" "f")
+ (parallel [(match_operand 2 "const_<indeximm>_operand" "")]))))]
+ "ISA_HAS_LSX"
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val == 0 && <MODE>mode == V4SImode)
+ return "movfr2gr.s\t%0,%1";
+ else if (val == 1 && <MODE>mode == V4SImode)
+ return "movfrh2gr.s\t%0,%1";
+
+ return "vpickve2gr.<lsxfmt>\t%0,%w1,%2";
+}
[(set_attr "type" "simd_copy")
(set_attr "mode" "<MODE>")])
@@ -476,7 +496,14 @@ (define_insn "lsx_vpickve2gr_du"
(match_operand:V2DI 1 "register_operand" "f")
(parallel [(match_operand 2 "const_0_or_1_operand" "")])))]
"ISA_HAS_LSX"
- "vpickve2gr.du\t%0,%w1,%2"
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val == 0)
+ return "movfr2gr.d\t%0,%1";
+
+ return "vpickve2gr.du\t%0,%w1,%2";
+}
[(set_attr "type" "simd_copy")
(set_attr "mode" "V2DI")])
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c
index b9753f5aecb..c5b5e5d8771 100644
--- a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-builtin.c
@@ -3336,22 +3336,22 @@ __lasx_xvldrepl_d (void *_1)
int
__lasx_xvpickve2gr_w (v8i32 _1)
{
- return __builtin_lasx_xvpickve2gr_w (_1, 1);
+ return __builtin_lasx_xvpickve2gr_w (_1, 4);
}
unsigned int
__lasx_xvpickve2gr_wu (v8i32 _1)
{
- return __builtin_lasx_xvpickve2gr_wu (_1, 1);
+ return __builtin_lasx_xvpickve2gr_wu (_1, 4);
}
long
__lasx_xvpickve2gr_d (v4i64 _1)
{
- return __builtin_lasx_xvpickve2gr_d (_1, 1);
+ return __builtin_lasx_xvpickve2gr_d (_1, 2);
}
unsigned long int
__lasx_xvpickve2gr_du (v4i64 _1)
{
- return __builtin_lasx_xvpickve2gr_du (_1, 1);
+ return __builtin_lasx_xvpickve2gr_du (_1, 2);
}
v4i64
__lasx_xvaddwev_q_d (v4i64 _1, v4i64 _2)
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-xvpickve2gr-1.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-xvpickve2gr-1.c
new file mode 100644
index 00000000000..bd1fa409c2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/lasx-xvpickve2gr-1.c
@@ -0,0 +1,50 @@
+
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+#include <lasxintrin.h>
+extern int *x_si0;
+extern int *x_si1;
+extern long long *x_di0;
+extern long long *x_di1;
+/* { dg-final { scan-assembler-times "i32_0:.*\tmovfr2gr\\.s.*i32_0" 1 } } */
+int
+lasx_pickve2gr_i32_0 ()
+{
+ v8i32 a = { x_si0[0], x_si0[1], x_si0[2], x_si0[3],
+ x_si0[4], x_si0[5], x_si0[6], x_si0[7] };
+ v8i32 b = { x_si1[0], x_si1[1], x_si1[2], x_si1[3],
+ x_si1[4], x_si1[5], x_si1[6], x_si1[7] };
+ v8i32 res = a + b;
+ return res[0];
+}
+/* { dg-final { scan-assembler-times "i32_1:.*\tmovfrh2gr\\.s.*i32_1" 1 } } */
+int
+lasx_pickve2gr_i32_1 ()
+{
+ v8i32 a = { x_si0[0], x_si0[1], x_si0[2], x_si0[3],
+ x_si0[4], x_si0[5], x_si0[6], x_si0[7] };
+ v8i32 b = { x_si1[0], x_si1[1], x_si1[2], x_si1[3],
+ x_si1[4], x_si1[5], x_si1[6], x_si1[7] };
+ v8i32 res = a + b;
+ return res[1];
+}
+/* { dg-final { scan-assembler-times "i32_2:.*\tvpickve2gr\\.w.*i32_2" 1 } } */
+int
+lasx_pickve2gr_i32_2 ()
+{
+ v8i32 a = { x_si0[0], x_si0[1], x_si0[2], x_si0[3],
+ x_si0[4], x_si0[5], x_si0[6], x_si0[7] };
+ v8i32 b = { x_si1[0], x_si1[1], x_si1[2], x_si1[3],
+ x_si1[4], x_si1[5], x_si1[6], x_si1[7] };
+ v8i32 res = a + b;
+ return res[2];
+}
+/* { dg-final { scan-assembler-times "i64_0:.*\tmovfr2gr\\.d.*i64_0" 1 } } */
+long long
+lasx_pickve2gr_i64_0 ()
+{
+ v4i64 a = { x_di0[0], x_di0[1], x_di0[2], x_di0[3] };
+ v4i64 b = { x_di1[0], x_di1[1], x_di1[2], x_di1[3] };
+ v4i64 res = a + b;
+ return res[0];
+}
diff --git
a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c
index bdf6e160ace..b541357470c 100644
--- a/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/vect-extract-256-128.c
@@ -7,7 +7,7 @@
/*
**foo1_lo:
** xvld (\$xr[0-9]+),\$r4,0
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
@@ -21,7 +21,7 @@ foo1_lo (__m256 x)
**foo1_hi:
** xvld (\$xr[0-9]+),\$r4,0
** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
@@ -34,7 +34,7 @@ foo1_hi (__m256 x)
/*
**foo2_lo:
** xvld (\$xr[0-9]+),\$r4,0
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
@@ -48,7 +48,7 @@ foo2_lo (__m256d x)
**foo2_hi:
** xvld (\$xr[0-9]+),\$r4,0
** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
@@ -61,7 +61,7 @@ foo2_hi (__m256d x)
/*
**foo3_lo:
** xvld (\$xr[0-9]+),\$r4,0
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
@@ -75,7 +75,7 @@ foo3_lo (__m256i x)
**foo3_hi:
** xvld (\$xr[0-9]+),\$r4,0
** xvpermi.d (\$xr[0-9]+),(\$xr[0-9]+),0xe
-** vpickve2gr.du \$r4,(\$vr[0-9]+),0
+** movfr2gr.d \$r4,(\$f[0-9]+)
** vpickve2gr.du \$r5,(\$vr[0-9]+),1
** jr \$r1
*/
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-builtin.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-builtin.c
index 7ad8f45d840..cdf8953f7bd 100644
--- a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-builtin.c
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-builtin.c
@@ -2299,7 +2299,7 @@ __lsx_vpickve2gr_h (v8i16 _1)
int
__lsx_vpickve2gr_w (v4i32 _1)
{
- return __builtin_lsx_vpickve2gr_w (_1, 1);
+ return __builtin_lsx_vpickve2gr_w (_1, 2);
}
long
__lsx_vpickve2gr_d (v2i64 _1)
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vpickve2gr-1.c
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vpickve2gr-1.c
new file mode 100644
index 00000000000..83651e0022e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-vpickve2gr-1.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+#include <lsxintrin.h>
+extern int *x_si0;
+extern int *x_si1;
+extern long long *x_di0;
+extern long long *x_di1;
+/* { dg-final { scan-assembler-times "i32_0:.*\tmovfr2gr\\.s.*i32_0" 1 } } */
+int
+lsx_pickve2gr_i32_0 ()
+{
+ v4i32 a = { x_si0[0], x_si0[1], x_si0[2], x_si0[3] };
+ v4i32 b = { x_si1[0], x_si1[1], x_si1[2], x_si1[3] };
+ v4i32 res = a + b;
+ return res[0];
+}
+/* { dg-final { scan-assembler-times "i32_1:.*\tmovfrh2gr\\.s.*i32_1" 1 } } */
+int
+lsx_pickve2gr_i32_1 ()
+{
+ v4i32 a = { x_si0[0], x_si0[1], x_si0[2], x_si0[3] };
+ v4i32 b = { x_si1[0], x_si1[1], x_si1[2], x_si1[3] };
+ v4i32 res = a + b;
+ return res[1];
+}
+/* { dg-final { scan-assembler-times "i64:.*\tmovfr2gr\\.d.*i64" 1 } } */
+long long
+lsx_pickve2gr_i64 ()
+{
+ v2i64 a = { x_di0[0], x_di0[1] };
+ v2i64 b = { x_di1[0], x_di1[1] };
+ v2i64 res = a + b;
+ return res[0];
+}
--
2.20.1