https://gcc.gnu.org/g:1a4eb0479ce0827b55a6190ddf13ade330d619e6

commit r16-6815-g1a4eb0479ce0827b55a6190ddf13ade330d619e6
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]>

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 437742c74210..30f8bc057470 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -10436,32 +10436,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;
+}

Reply via email to