https://gcc.gnu.org/g:6122c67069b9a17a7e384ae91a0995bf4ccc9200

commit r16-8874-g6122c67069b9a17a7e384ae91a0995bf4ccc9200
Author: Lulu Cheng <[email protected]>
Date:   Thu Apr 30 15:56:30 2026 +0800

    LoongArch: Fix ICE caused by incomplete split conditions [PR125057].
    
    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.
    
    (cherry picked from commit 1bb9817fa87644db91d713808a78d571086d0d78)

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

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 134ed47afdf3..4a0a9bafa813 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 b2a3def11ad6..1059eee37ca3 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 000000000000..698bddd8d083
--- /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 000000000000..9b3ac47fad69
--- /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