]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Fix ICE caused by incomplete split conditions [PR125057].
authorLulu Cheng <chenglulu@loongson.cn>
Thu, 30 Apr 2026 07:56:30 +0000 (15:56 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Wed, 6 May 2026 09:06:30 +0000 (17:06 +0800)
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
gcc/config/loongarch/loongarch.h
gcc/testsuite/gcc.target/loongarch/vector/lasx/pr125057.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/vector/lsx/lsx-mov-2.c [new file with mode: 0644]

index 134ed47afdf3389af9257ec8e828bf8e8fba1de7..4a0a9bafa8138b4751269ea1ffeb0e723e7aa2df 100644 (file)
@@ -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)
index b2a3def11ad6d10ff6a558e8c9ae4937bda69621..1059eee37ca374e0d8e0114ee8f7322b21c37c2c 100644 (file)
@@ -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 (file)
index 0000000..698bddd
--- /dev/null
@@ -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 (file)
index 0000000..9b3ac47
--- /dev/null
@@ -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);
+}