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

Reply via email to