https://gcc.gnu.org/g:9f4a1f84a6d2d2316d73a067497e8ec3d23746d7
commit r14-12243-g9f4a1f84a6d2d2316d73a067497e8ec3d23746d7 Author: Lulu Cheng <[email protected]> Date: Mon Jan 12 17:23:41 2026 +0800 LoongArch: Fix bug123521. In the vector initialization process, optimization can be performed if it can be determined that all elements are the same, or if the upper or lower halves are identical. However, during this optimization, when the identical element is an immediate value larger than 10 bits, an internal compiler error (ICE) occurs. The reason is that in such cases, the function `simplify_gen_subreg (imode, reg_tmp, GET_MODE (reg_tmp), 0)` is called, where `imode` is `E_DImode`. The mode of `reg_tmp` in `GET_MODE (reg_tmp)` is taken from the immediate value's mode, which is `E_VOIDmode`. This results in a move from `E_VOIDmode` to `E_DImode`, an operation not supported by LoongArch. PR target/123521 gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_expand_vector_init_same): Fixed a bug in the vector initialization section.. gcc/testsuite/ChangeLog: * gcc.target/loongarch/vector/lasx/pr123521.c: New test. Suggested-by: Xi Ruoyao <[email protected]> (cherry picked from commit 1a4eb0479ce0827b55a6190ddf13ade330d619e6) Diff: --- gcc/config/loongarch/loongarch.cc | 27 +--------------------- .../gcc.target/loongarch/vector/lasx/pr123521.c | 11 +++++++++ 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 547219ce5558..b58405631857 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -10021,32 +10021,7 @@ loongarch_expand_vector_init_same (rtx target, rtx vals, unsigned nvar) } } - if (imode == GET_MODE (same)) - temp = same; - else if (GET_MODE_SIZE (imode) >= UNITS_PER_WORD) - { - if (GET_CODE (same) == MEM) - { - rtx reg_tmp = gen_reg_rtx (GET_MODE (same)); - loongarch_emit_move (reg_tmp, same); - temp = simplify_gen_subreg (imode, reg_tmp, GET_MODE (reg_tmp), 0); - } - else - temp = simplify_gen_subreg (imode, same, GET_MODE (same), 0); - } - else - { - if (GET_CODE (same) == MEM) - { - rtx reg_tmp = gen_reg_rtx (GET_MODE (same)); - loongarch_emit_move (reg_tmp, same); - temp = lowpart_subreg (imode, reg_tmp, GET_MODE (reg_tmp)); - } - else - temp = lowpart_subreg (imode, same, GET_MODE (same)); - } - - temp = force_reg (imode, temp); + temp = force_reg (imode, same); switch (vmode) { diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr123521.c b/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr123521.c new file mode 100644 index 000000000000..9ccf391d38d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lasx/pr123521.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -msimd=lasx" } */ + +typedef long long v4i64 __attribute__ ((vector_size (32), aligned (32))); +extern long long *x_si; +v4i64 +test (void) +{ + v4i64 a = { x_si[1], x_si[0], 0x411, 0x411 }; + return a; +}
