On Tue, Sep 22, 2026 at 4:46 AM liuhongt <[email protected]> wrote:
>
> ix86_split_stlf_stall_load splits a V2DF load from a PARM_DECL into
> movlpd + movhpd, which needs the load address offset by 8. When the
> original address already uses the largest encodable displacement, e.g.
>
> (mem/c:V2DF (plus:DI (reg/f:DI 7 sp)
> (const_int 2147483640 [0x7ffffff8])))
>
> adding 8 gives 0x80000000, which is out of range for the signed 32-bit
> displacement field of an x86 address, and adjust_address ICEs in
> change_address_1 since the address can no longer be validated after
> reload. Skip the split in that case.
>
> Boostrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
> Ok?
>
> gcc/ChangeLog:
>
> PR target/127500
> * config/i386/i386.cc (ix86_split_stlf_stall_load): Don't split
> the load when the address adjusted by 8 is not a valid memory
> address.
>
> gcc/testsuite/ChangeLog:
>
> PR target/127500
> * gcc.target/i386/pr127500.c: New test.
OK.
Thanks,
Uros.
> ---
> gcc/config/i386/i386.cc | 12 +++++++++++-
> gcc/testsuite/gcc.target/i386/pr127500.c | 8 ++++++++
> 2 files changed, 19 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gcc.target/i386/pr127500.c
>
> diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> index bbb60163a75..29e1d2c5808 100644
> --- a/gcc/config/i386/i386.cc
> +++ b/gcc/config/i386/i386.cc
> @@ -25083,7 +25083,17 @@ ix86_split_stlf_stall_load ()
> register. */
> || GET_MODE (src) != E_V2DFmode
> || !MEM_EXPR (src)
> - || TREE_CODE (get_base_address (MEM_EXPR (src))) != PARM_DECL)
> + || TREE_CODE (get_base_address (MEM_EXPR (src))) != PARM_DECL
> + /* Avoid invalid memory address.
> + i.e.
> + (mem/c:V2DF (plus:DI (reg/f:DI 7 sp)
> + (const_int 2147483640 [0x7ffffff8])))
> + Adjusting it by 8 puts the displacement at 0x80000000, out of
> + range for the signed 32-bit field an x86 address can encode. */
> + || !memory_address_addr_space_p (DFmode,
> + XEXP (adjust_address_nv (src,
> DFmode,
> + 8), 0),
> + MEM_ADDR_SPACE (src)))
> continue;
>
> rtx zero = CONST0_RTX (V2DFmode);
> diff --git a/gcc/testsuite/gcc.target/i386/pr127500.c
> b/gcc/testsuite/gcc.target/i386/pr127500.c
> new file mode 100644
> index 00000000000..cde6058fd6f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr127500.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-msse2 -O2" } */
> +
> +typedef double v2df __attribute__((vector_size (16)));
> +
> +struct big { char pad[0x7FFFFFF0]; v2df v; };
> +
> +v2df f (struct big b) { return b.v; }
> --
> 2.34.1
>