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);
+}