x86 SSE: Improved vector initialization/construction.
This patch is a reorganization of x86's vector initialization (vec_init)
functionality to generate more efficient implementations in most/many
cases. Previously, for most (128-bit and 256-bit) vectors types,
i386-expand.cc made use of "concat" recursion to divide-and-conquor;
splitting each vector into upper and lower halves, initializing them,
then concatenating the results together. Simple and orthogonal, but
alas inefficient. This idiom is unable to take advantage of SSE's
zero extension semantics, shuffle/permutation instructions, byte-level
shifts, element insertion instructions nor vector-mode logic operations.
Unfortunately the reality is that these ISAs are irregular, as are the
patterns provided by the backend expose their instructions (which are
often available in one mode but not another).
The patch below recognizes/accepts these asymmetries, and provides
"custom" vector initialization functions for most 128-bit and 256-bit
vector modes. There are too many optimization/improvements to list
them all, but some examples are given below:
v4si f1(int x, int y) { return (v4si){x,y,0,0}; }
Before with -O2:
f1_old: movd %edi, %xmm0
movd %esi, %xmm1
punpckldq %xmm1, %xmm0
movq %xmm0, %xmm0
ret
After with -O2:
f1_new: movd %edi, %xmm0
movd %esi, %xmm1
punpckldq %xmm1, %xmm0
ret
v4si f2(int x) { return (v4si){0,x,x,0}; }
Before with -O2:
f2_old: movd %edi, %xmm2
pxor %xmm0, %xmm0
movd %edi, %xmm1
punpckldq %xmm2, %xmm0
punpcklqdq %xmm1, %xmm0
ret
f2_new: movd %edi, %xmm0
shufps $65, %xmm0, %xmm0
ret
After with -O2 -mavx2:
f4_new: movzbl %dil, %eax
vmovd %eax, %xmm0
vpinsrb $9, %edi, %xmm0, %xmm0
ret
Unfortunately, despite all of the goodness there remains one testsuite
regression: avx512vl-concatv4si-1.c whose f2 function currently expects
3 instructions before the return:
which actually contains our two optimal instructions, but between
combine, simplify-rtx and sse.md's define_insn_and_splits, we fail
to notice that the remaining operations (converting V2SI to V4SI)
are a no-op. I beg the reviewers'/maintainers' indulgence to allow
this to fail for the time being, to be solved in a follow-up patch.
This current patch is large enough already, and this remaining quirk
needs to be resolved outside the RTL expansion pass, in the later
RTL optimizers (where it is currently a missed optimization).
2026-08-01 Roger Sayle <roger@nextmovesoftware.com>
Hongtao Liu <hongtao.liu@intel.com>
gcc/ChangeLog
* config/i386/i386-expand.cc (ix86_expand_vector_init_one_nonzero):
Improved implementations for V2DI, V2DF, V4SI, V4SF, V4DI and V4DF
modes. Return false for V2SI and V2SF modes if the one non-zero
element isn't the first/lowest. Improved implementations for V8HI,
V16QI, V2HI and V8QI modes.
(nonzero_int_const_count): New helper function to count the
number of non-zero integer constants in a given array.
(nonzero_float_const_count): Likewise for SFmode floats.
(nonzero_double_const_count): Likewise for DFmode doubles.
(ix86_expand_vector_init_insert): New function to initialize a
V4SI, V8HI or V16QI vector using a sequence of pinsr[bwd] insns.
(onevar_perm_p): New local helper function.
(twovar_perm_p): Likewise.
(ix86_expand_vector_init_v2di): New mode-specific function.
(ix86_expand_vector_init_v2df): Likewise.
(ix86_expand_vector_init_v4si): Likewise.
(ix86_expand_vector_init_v4sf): Likewise.
(ix86_expand_vector_init_v8hi): Likewise.
(ix86_expand_vector_init_v16qi): Likewise.
(ix86_expand_vector_init_v4di): Likewise.
(ix86_expand_vector_init_v4df): Likewise.
(ix86_expand_vector_init_v8si): Likewise.
(ix86_expand_vector_init_v8sf): Likewise.
(ix86_expand_vector_init_general): Call the above custom helper
functions for the relevant modes.
* config/i386/sse.md (*vec_interleave_lowv4si_sse): New pattern
for (V4SImode) unpcklps on TARGET_SSE but not TARGET_SSE2.