On Wed, 2026-01-14 at 12:00 +0800, Lulu Cheng wrote:
> 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.
>
> ---
> gcc/config/loongarch/loongarch.cc | 21 ++----------------
> -
> .../loongarch/vector/lasx/pr123521.c | 11 ++++++++++
> 2 files changed, 13 insertions(+), 19 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..1ce3cd4185d 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -10438,27 +10438,10 @@ 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 = gen_reg_rtx (imode);
> + loongarch_emit_move (temp, same);
> }
The code after this change is:
if (imode == GET_MODE (same))
temp = same;
else
{
temp = gen_reg_rtx (imode);
loongarch_emit_move (temp, same);
}
temp = force_reg (imode, temp);
But to me the lines above now look equivalent to a simple
temp = force_reg (imode, same);
or am I missing something?
--
Xi Ruoyao <[email protected]>