Richard Biener <[email protected]> writes:
> On Sat, Jun 27, 2026 at 8:00 PM Roger Sayle <[email protected]>
> wrote:
>>
>>
>>
>> This patch adds an RTL simplification to simplify-rtx.cc to resolve
>>
>> PR target/48609, inefficient passing of complex values on x86.
>>
>>
>>
>> The motivating example, for the bugzilla PR, is:
>>
>>
>>
>> typedef _Complex float SCtype;
>>
>> extern SCtype bar;
>>
>> void foo (SCtype x)
>>
>> {
>>
>>   bar = x;
>>
>> }
>>
>>
>>
>> which currently with -O2 generates some spurious instructions:
>>
>>
>>
>> foo:    movdqa  %xmm0, %xmm1
>>
>>         shufps  $85, %xmm0, %xmm0
>>
>>         unpcklps        %xmm0, %xmm1
>>
>>         movlps  %xmm1, bar(%rip)
>>
>>         ret
>>
>>
>>
>> with this patch we now generate (the optimal):
>>
>>
>>
>> foo:    movlps  %xmm0, bar(%rip)
>>
>>         ret
>>
>>
>>
>> The insight is that combine reports these attempts:
>>
>>
>>
>> Trying 7, 4 -> 14:
>>
>>     7: {r111:SI#0=r105:DI 0>>0x20;clobber flags:CC;}
>>
>>       REG_UNUSED flags:CC
>>
>>       REG_DEAD r105:DI
>>
>>     4: r108:SI=r105:DI#0
>>
>>    14: r112:V2SF=vec_concat(r108:SI#0,r111:SI#0)
>>
>>       REG_DEAD r111:SI
>>
>>       REG_DEAD r108:SI
>>
>> Failed to match this instruction:
>>
>> (set (reg:V2SF 112 [ _7 ])
>>
>>     (vec_concat:V2SF (subreg:SF (subreg:SI (reg:DI 105 [ xD.2967 ]) 0) 0)
>>
>>         (subreg:SF (subreg:SI (zero_extract:DI (reg:DI 105 [ xD.2967 ])
>>
>>                     (const_int 32 [0x20])
>>
>>                     (const_int 32 [0x20])) 0) 0)))
>>
>> Failed to match this instruction:
>>
>> (set (reg:V2SF 112 [ _7 ])
>>
>>     (vec_concat:V2SF (subreg:SF (subreg:SI (reg:DI 105 [ xD.2967 ]) 0) 0)
>>
>>         (subreg:SF (subreg:SI (lshiftrt:DI (reg:DI 105 [ xD.2967 ])
>>
>>                     (const_int 32 [0x20])) 0) 0)))
>>
>>
>>
>> Conceptually, this pattern is the equivalent of the RTL expression
>>
>> (vec_concat (subreg_lowpart (reg X)) (subreg_highpart (reg X)) which
>>
>> of course is equal to the original (reg X).  The ABI splits the
>>
>> complex argument into __real__ and __imag__ parts, which it then
>>
>> tries to recombine with vec_concat, resulting in this strange no-op.
>>
>>
>>
>> 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?
>
> Thanks for catching - I wonder whether vector lane endianess can play
> a role here and be different from word endianess?

Yeah, I think endianness is a concern.  vec_concat operates in memory
order, so element 0 is always the first in memory.  Similarly, subreg
offsets operate in memory order, so SUBREG_BYTE 0 is always first in
memory.

So I think it's not:

  (vec_concat (subreg lowpart (subreg highpart))

but rather:

  (vec_concat (subreg at offset 0) (subreg at offset N/2))

Richard

> I suppose there must be similar simplifications around, so you're
> conviced this is fine?
>
> ISTR both arm and powerpc have/had their "difficulties" with vectors
> and big-endian operation.
>
> Richard?
>
>>
>>
>>
>>
>>
>> 2026-06-27  Roger Sayle  <[email protected]>
>>
>>
>>
>> gcc/ChangeLog
>>
>>         PR target/48609
>>
>>         * simplify-rtx.cc (simplify_binary_operation_1) <case VEC_CONCAT>:
>>
>>         Optimize VEC_CONCAT of a low-part with a high-part as a no-op.
>>
>>
>>
>> gcc/testsuite/ChangeLog
>>
>>         PR target/48609
>>
>>         * gcc.target/i386/pr48609.c: New test case.
>>
>>
>>
>>
>>
>> Thanks in advance,
>>
>> Roger
>>
>> --
>>
>>

Reply via email to