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]>

Reply via email to