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]>
---
gcc/config/loongarch/loongarch.cc | 27 +------------------
.../loongarch/vector/lasx/pr123521.c | 11 ++++++++
2 files changed, 12 insertions(+), 26 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/vector/lasx/pr123521.c
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 0b50aa214fd..983779401b4 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 00000000000..9ccf391d38d
--- /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;
+}
--
2.34.1