Pushed to r17-350 and  r16-8874.

在 2026/4/30 下午4:21, Lulu Cheng 写道:
Since the split conditions in loongarch_split_vector_move are incomplete,
the following RTL:

        (set (reg:V4DI 32 $f0) (subreg:V4DI (reg:V2DI 32 $f0) 0))

is incorrectly split, leading to an ICE.

This patch fixes the issue by completing the split conditions.

        PR target/125057

gcc/ChangeLog:

        * config/loongarch/loongarch.cc
        (loongarch_split_vector_move): Complete the split condition.
        * config/loongarch/loongarch.h (LSX_REG_RTX_P): Delete.
        (LASX_REG_RTX_P): Delete.
        (GP_REG_RTX_P): Define macro.

gcc/testsuite/ChangeLog:

        * gcc.target/loongarch/vector/lasx/pr125057.c: New test.
        * gcc.target/loongarch/vector/lsx/lsx-mov-2.c: New test.

---
  gcc/config/loongarch/loongarch.cc             | 41 +++++++++++++++++--
  gcc/config/loongarch/loongarch.h              |  3 +-
  .../loongarch/vector/lasx/pr125057.c          | 25 +++++++++++
  .../loongarch/vector/lsx/lsx-mov-2.c          | 13 ++++++
  4 files changed, 76 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/gcc.target/loongarch/vector/lasx/pr125057.c
  create mode 100644 gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-mov-2.c

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 134ed47afdf..4a0a9bafa81 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -5108,8 +5108,37 @@ loongarch_split_vector_move (rtx dest, rtx src)
    machine_mode mode = GET_MODE (dest);
    bool lsx_p = LSX_SUPPORTED_MODE_P (mode);
- if (FP_REG_RTX_P (dest))
-    {
+  if (FP_REG_RTX_P (dest) && GP_REG_RTX_P (src))
+    {
+    /* Since the LoongArch architecture has not yet implemented vector
+       parameter passing, the following operations are required when
+       a function returns a vector type that needs to be passed to a
+       vector register.
+
+       As shown in the following instruction sequence:
+
+       (call_insn 5 6 12 2 (parallel [
+            (set (reg:V2DI 4 $r4)
+                 (call (mem:SI (symbol_ref:DI ("bar"))
+                               (const_int 0 [0])))
+                 (clobber (reg:SI 1 $r1)))]))
+       (insn 12 5 7 2 (set (reg:V2DI 32 $f0)
+                          (reg:V2DI 4 $r4)))
+
+       insn 12 will be split here as follows:
+       (insn 15 5 16 2 (set (reg:V2DI 32 $f0)
+                           (vec_merge:V2DI
+                               (vec_duplicate:V2DI (reg:DI 4 $r4))
+                               (reg:V2DI 32 $f0)
+                               (const_int 1 [0x1]))))
+       (insn 16 15 7 2 (set (reg:V2DI 32 $f0)
+                           (vec_merge:V2DI
+                               (vec_duplicate:V2DI (reg:DI 5 $r5 [+8 ]))
+                               (reg:V2DI 32 $f0)
+                               (const_int 2 [0x2]))))
+
+       This can be reproduced with the test case lsx-mov-2.c.
+     */
        gcc_assert (!MEM_P (src));
rtx (*gen_vinsgr2vr_d) (rtx, rtx, rtx, rtx);
@@ -5138,8 +5167,12 @@ loongarch_split_vector_move (rtx dest, rtx src)
                                          GEN_INT (1 << index)));
        }
      }
-  else if (FP_REG_RTX_P (src))
+  else if (FP_REG_RTX_P (src) && GP_REG_RTX_P (dest))
      {
+      /* Transfer vector data from vector registers to GPRs, generally
+        for vector argument handling.
+        This can be reproduced with the test case lsx-mov-1.c.
+       */
        gcc_assert (!MEM_P (dest));
rtx (*gen_vpickve2gr_d) (rtx, rtx, rtx);
@@ -5166,7 +5199,7 @@ loongarch_split_vector_move (rtx dest, rtx src)
          emit_insn (gen_vpickve2gr_d (d, new_src, GEN_INT (index)));
        }
      }
-  else
+  else if (GP_REG_RTX_P (src) && GP_REG_RTX_P (dest))
      {
        /* This part of the code is designed to handle the following situations:
         (set (reg:V2DI 4 $r4)
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index b2a3def11ad..1059eee37ca 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -368,8 +368,7 @@ along with GCC; see the file COPYING3.  If not see
    ((unsigned int) ((int) (REGNO) - LASX_REG_FIRST) < LASX_REG_NUM)
#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
-#define LSX_REG_RTX_P(X) (REG_P (X) && LSX_REG_P (REGNO (X)))
-#define LASX_REG_RTX_P(X) (REG_P (X) && LASX_REG_P (REGNO (X)))
+#define GP_REG_RTX_P(X) (REG_P (X) && GP_REG_P (REGNO (X)))
/* Select a register mode required for caller save of hard regno REGNO. */
  #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr125057.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr125057.c
new file mode 100644
index 00000000000..698bddd8d08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr125057.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O2" } */
+
+#include <lasxintrin.h>
+#include <lsxintrin.h>
+
+#define TEST(to, from)                                                         
\
+__m256i                                                                        
        \
+vext2xv_##to##_##from (const short *p)                                         
\
+{                                                                              
\
+  return __lasx_vext2xv_##to##_##from (__lasx_cast_128 (__lsx_vld (p, 0)));    
\
+}
+
+TEST (h, b)
+TEST (w, b)
+TEST (d, b)
+TEST (w, h)
+TEST (d, h)
+TEST (d, w)
+TEST (hu, bu)
+TEST (wu, bu)
+TEST (du, bu)
+TEST (wu, hu)
+TEST (du, hu)
+TEST (du, wu)
diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-mov-2.c 
b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-mov-2.c
new file mode 100644
index 00000000000..9b3ac47fad6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-mov-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O2" } */
+
+#include <lsxintrin.h>
+
+extern __m128i bar (void);
+extern int *p;
+
+void
+foo ()
+{
+  __lsx_vst (bar(), (void *)p, 0);
+}

Reply via email to