https://gcc.gnu.org/g:ec31d8cb81aa2f9b74c3b91fb87080b9c86cea23
commit r17-2322-gec31d8cb81aa2f9b74c3b91fb87080b9c86cea23 Author: Roger Sayle <[email protected]> Date: Fri Jul 10 22:59:24 2026 +0100 PR target/99668: Improved complex to vector RTL expansion. This patch improves the RTL expansion of casts (VIEW_CONVERT_EXPR) from complex numbers to two-component vectors with the same inner type. Currently, expand spills the complex number to memory to perform this conversion. With the patch below we now convert the V_C_E into the equivalent of (v2x){__real__ z,__imag__ z}, using the backend's vec_init_optab. The motivating example from the Bugzilla PR is: typedef double v2df __attribute__((vector_size(16))); v2df foo (_Complex double x) { return *(v2df *)&x; } Currently, with -O2 GCC implements this by spilling to memory: foo: movsd %xmm0, -24(%rsp) movsd %xmm1, -16(%rsp) movupd -24(%rsp), %xmm0 ret with this enhancement to RTL expansion, we now generate: foo: unpcklpd %xmm1, %xmm0 ret The improvement with -m32 -msse2 -O2 is even more pronounced. From: subl $28, %esp movsd 32(%esp), %xmm1 movsd 40(%esp), %xmm2 movsd %xmm1, (%esp) movsd %xmm2, 8(%esp) movupd (%esp), %xmm0 addl $28, %esp ret To: movq 4(%esp), %xmm0 movhpd 12(%esp), %xmm0 ret 2026-07-10 Roger Sayle <[email protected]> Richard Biener <[email protected]> gcc/ChangeLog PR target/99668 * expr.cc (try_expand_complex_as_vector): Try to use vec_init_optab to convert a complex number to a two-component vector with the same inner type. (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Check whether the above function can be used to implement this VIEW_CONVERT_EXPR. gcc/testsuite/ChangeLog PR target/99668 * gcc.target/i386/pr99668.c: New test case. Diff: --- gcc/expr.cc | 45 +++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr99668.c | 12 +++++++++ 2 files changed, 57 insertions(+) diff --git a/gcc/expr.cc b/gcc/expr.cc index f42aab21272f..9933286df849 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -11382,6 +11382,45 @@ expand_expr_real_gassign (gassign *g, rtx target, machine_mode tmode, return r; } +/* A subroutine of expand_expr_real_1. Attempt to VIEW_CONVERT_EXPR + the complex expression OP0 to the vector mode MODE. Store the + result at TARGET if possible (if TARGET is nonzero). Returns + NULL_RTX on failure. */ +static rtx +try_expand_complex_as_vector (machine_mode mode, rtx op0, rtx target) +{ + if (COMPLEX_MODE_P (GET_MODE (op0)) + && VECTOR_MODE_P (mode) + && known_eq (GET_MODE_NUNITS (mode), 2) + && GET_MODE_INNER (mode) == GET_MODE_INNER (GET_MODE (op0))) + { + enum insn_code icode = convert_optab_handler (vec_init_optab, mode, + GET_MODE_INNER (mode)); + if (icode != CODE_FOR_nothing) + { + if (!target || !REG_P (target)) + target = gen_reg_rtx (mode); + rtx rpart = read_complex_part (op0, false); + rtx ipart = read_complex_part (op0, true); + if (!REG_P (rpart) && !CONSTANT_P (rpart)) + rpart = force_reg (GET_MODE_INNER (mode), rpart); + if (!REG_P (ipart) && !CONSTANT_P (ipart)) + ipart = force_reg (GET_MODE_INNER (mode), ipart); + rtvec vec = rtvec_alloc (2); + RTVEC_ELT (vec, 0) = rpart; + RTVEC_ELT (vec, 1) = ipart; + rtx par = gen_rtx_PARALLEL (mode, vec); + rtx_insn *insn = GEN_FCN (icode) (target, par); + if (insn) + { + emit_insn (insn); + return target; + } + } + } + return NULL_RTX; +} + rtx expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, enum expand_modifier modifier, rtx *alt_rtl, @@ -12798,6 +12837,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, return extract_bit_field (op0, TYPE_PRECISION (type), 0, TYPE_UNSIGNED (type), NULL_RTX, mode, mode, false, NULL); + /* If source is a complex number and destination is a + two-component vector with same inner type, try to use + vector initialization. */ + else if ((temp = try_expand_complex_as_vector (mode, op0, target)) + != NULL_RTX) + return temp; /* As a last resort, spill op0 to memory, and reload it in a different mode. */ else if (!MEM_P (op0)) diff --git a/gcc/testsuite/gcc.target/i386/pr99668.c b/gcc/testsuite/gcc.target/i386/pr99668.c new file mode 100644 index 000000000000..90bac6950831 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr99668.c @@ -0,0 +1,12 @@ +/* PR target/99668 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2" } */ + +typedef double v2df __attribute__((vector_size(16))); +v2df foo (_Complex double x) +{ + return *(v2df *)&x; +} + +/* { dg-final { scan-assembler-not "\\tmovsd" } } */ +/* { dg-final { scan-assembler-not "movupd" } } */
