https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48609
--- Comment #13 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Roger Sayle <[email protected]>: https://gcc.gnu.org/g:a1ff104826c59ead40f8e864cd1aa1ce2e5fc6ba commit r17-2323-ga1ff104826c59ead40f8e864cd1aa1ce2e5fc6ba Author: Roger Sayle <[email protected]> Date: Fri Jul 10 23:04:03 2026 +0100 PR target/48609: Improve RTL expansion of complex value return. 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. 2026-07-10 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.
