https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48609
--- Comment #14 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:b085ae4b49b41e146c0a6a6c16c8c588438b9528 commit r17-3637-gb085ae4b49b41e146c0a6a6c16c8c588438b9528 Author: Roger Sayle <[email protected]> Date: Tue Aug 25 09:02:51 2026 -0500 PR target/48609: RTL simplifications for x86 complex arg passing. Very many thanks to Richard Sandiford for his inspired feedback/proof-of-concept that addressed the big endian flaws in my original patch. His suggestion to use an RTL get_ref_base_and_offset is inspired, and significantly cleans up this patch. Chapeau. 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. 2026-08-25 Roger Sayle <[email protected]> Richard Sandiford <[email protected]> gcc/ChangeLog PR target/48609 * rtl.cc (rtvec_series_p): Enhance to allow START to be a poly_int64 instead of just an int. * rtl.h (rtvec_series_p): Update function prototype. * rtlanal.cc (vec_series_highpart_p): Now that rtxvec_series_p can handle poly_int64, we handle modes that aren't constant size. (vec_series_lowpart_p): Likewise. (get_ref_base_and_offset): New function to determine the base RTX and byte offset of an arbitrary expression, typically a SUBREG. * rtlanal.h (get_ref_base_and_offset): Prototype here. * simplify-rtx.cc (simplify_binary_operation_1) <case VEC_CONCAT>: Generalize the existing (vec_concat (first_half) (second_half)) optimization using the new get_ref_base_and_offset function. gcc/testsuite/ChangeLog PR target/48609 * gcc.target/i386/pr48609.c: New test case.
