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