On Wed, Jul 1, 2026 at 1:07 PM Roger Sayle <[email protected]> wrote:
>
>
> This patch address the inefficient return of complex values (with the x86
> ABI) where the result is returned to the caller in an integer register.
> Currently this results in RTL expansion spilling the value to memory
> and reloading it in an integer register.  The patch below recognizes
> this case, and composes the real and imaginary parts using shifts and
> addition.  The real part always appears first in memory, so is lowpart
> on little-endian targets, and the highpart on big-endian targets.
>
> Consider the new test case:
>
> _Complex float mem;
> _Complex float foo(_Complex float x) { return x; }
> _Complex float bar() { return mem; }
>
> Currently, with -O2 GCC generates:
>
> foo:    movss   %xmm0, -8(%rsp)
>         shufps  $85, %xmm0, %xmm0
>         movss   %xmm0, -4(%rsp)
>         movq    -8(%rsp), %xmm0
>         ret
>
> bar:    movss   mem(%rip), %xmm0
>         movss   %xmm0, -8(%rsp)
>         movss   mem+4(%rip), %xmm0
>         movss   %xmm0, -4(%rsp)
>         movq    -8(%rsp), %xmm0
>         ret
>
> With this patch, we now generate:
>
> foo:    ret
>
> bar:    movl    mem+4(%rip), %edx
>         movl    mem(%rip), %eax
>         salq    $32, %rdx
>         addq    %rdx, %rax
>         movq    %rax, %xmm0
>         ret
>
>
> For those folks noticing that bar could be improved further, I've
> a follow-up patch to the i386's STV2 pass, to perform concatsidi2 in
> SSE registers.
>
> This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> and make -k check, both with and without --target_board=unix{-m32}
> with no new failures.  Ok for mainline?

Seeing a GET_CODE (src) == CONCAT case after the new block I wonder
if that's more specific and should be handled first?  Or would that be
always worse when SCALAR_INT_MODE_P (mode) in which case we
possibly want to add a comment reflecting this.

Can expand_shift fail?  I would expect it might be quite expensive, like
on AVR which IIRC can only shift by a single bit at a time.

That said, I wonder why emit_group_load_1 is the correct place to fix,
is it that the very CONCAT path performs assign_stack_temp ()?

>
> 2026-07-01  Roger Sayle  <[email protected]>
>
> gcc/ChangeLog
>         PR target/48609
>         * expr.cc (emit_group_load_1): When passing a complex value in an
>         integer mode of the same size, explicitly construct (hi<<N)+lo to
>         avoid spilling to memory before reload.
>
> gcc/testsuite/ChangeLog
>         PR target/48609
>         * gcc.target/i386/pr48609-2.c: New test case.
>
>
> Thanks in advance,
> Roger
> --
>

Reply via email to