On Mon Oct 5, 2026 at 2:26 AM PDT, Roger Sayle wrote:
> Hi Hongtao,
> Sorry for the delay in getting back to you with your suggested
> corrections. Please find a revised version of the previous patch
> implementing the bug-fix (typo) you spotted, and various whitespace
> issue corrections.
>
> This revision retains the all_same_p terminating case for the
> recursion, that you proposed could perhaps be removed, because
> although this path is not currently triggered (as explained not
> all of the possible optimizations are implemented yet), it's
> better practice to keep the terminating conditions explicit in
> a recursive function, than require an (undocumented) invariant
> of all the function's callers.
>
> Your insightful comment:
>> We can stop here until we find real opportunity in real workload.
> led me to investigate the opportunities for improvement.
>
> Using the following hack (not a proposed patch):
>
> diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
> index 9e112d01734..8e6942458d9 100644
> --- a/gcc/config/i386/i386-expand.cc
> +++ b/gcc/config/i386/i386-expand.cc
> @@ -20550,6 +20550,49 @@ ix86_expand_vector_init (bool mmx_ok, rtx target,
> rtx vals)
> gcc_unreachable ();
> }
>
> + unsigned int ni = 0;
> + unsigned int ai = 0;
> + unsigned char buffer[128];
> + for (i = 0; i < n_elts; i++)
> + {
> + x = XVECEXP (vals, 0, i);
> + if (x == CONST0_RTX (inner_mode))
> + buffer[i] = '0';
> + else
> + {
> + int j = 0;
> + while (j < i)
> + {
> + if (rtx_equal_p (x, XVECEXP (vals, 0, j)))
> + {
> + buffer[i] = buffer[j];
> + break;
> + }
> + j++;
> + }
> +
> + if (j == i)
> + {
> + if (CONST_SCALAR_INT_P (x)
> + || CONST_DOUBLE_P (x)
> + || CONST_FIXED_P (x))
> + {
> + ni++;
> + buffer[i] = (ni < 10) ? ni + '0' : '_';
> + }
> + else
> + {
> + buffer[i] = (ai < 26) ? ai + 'a' : '_';
> + ai++;
> + }
> + }
> + }
> + }
> + buffer[n_elts] = '\0';
> + FILE *fp = fopen("/tmp/gcc.log","a");
> + fprintf(fp,"%s: %s\n",mode_name[mode],buffer);
> + fclose(fp);
> +
> for (i = 0; i < n_elts; ++i)
> {
> x = XVECEXP (vals, 0, i);
>
> I was able analyze all the vector initializations in stage 2 and 3 of
> a gcc bootstrap, which produced the following histogram:
>
> 9621 V2DI: ab
> 1570 V2SI: ab
> 1164 V2SF: ab
> 950 V2DF: ab
> 796 V2HI: ab
> 722 V2DI: a0
> 619 V4SI: abcd
> 463 V2DI: 0a
> 301 V4SI: a000
> 294 V4SF: abcd
> 279 V2SI: aa
> 146 V2SF: aa
> 144 V4DF: abcd
> 123 V4SI: ab00
> 100 V2DF: aa
> 98 V4SF: aaaa
> 56 V8SF: abaaaaaa
> 56 V8SF: aabcdefg
> 50 V4SF: abaa
> 50 V4SF: aabc
> 48 V2DI: 1a
> 40 V4DF: abaa
> 40 V4DF: aabc
> 40 V4DF: aaaa
> 33 V2SI: a0
> 24 V8SF: abcdefgh
> 22 V4SI: aabc
> 21 V2SI: 0a
> 20 V4HI: abcd
> 18 V2TI: ab
> 18 V2DI: a1
> 16 V4SI: 000a
> 12 V4SI: abbb
> 12 V4SI: a111
> 12 V4SI: 100a
> 12 V4HI: abbb
> 12 V2HI: aa
> 12 V16QI: abcdefghijklmnop
> 9 V4SI: aabb
> 6 V4SI: aaab
> 6 V4SI: a120
> 4 V4TI: abcd
> 4 V4QI: 00ab
> 4 V4DI: abcd
> 4 V2SI: a1
> 4 V2SI: 1a
> 3 V4SI: abbc
> 2 V4SI: a123
> 2 V4SI: 1a00
> 2 V4QI: aabb
> 2 V4QI: 1ab2
>
> Confirming that you're right, and my ideas for optimizations such as
> implementing (v16qi){a,a,a,a,a,a,0,0,0,0,0,0,0,0,0,0} in two instructions
> using a vpbroadcastb followed by psrldq would probably have no significant
> impact in the real world. There are some interesting opportunities, and
> one surprising insight is that GCC appears to make heavy use of "short"
> vectors such as "V2SI" and "V4QI" (not the 128, 256 or 512-bit vectors
> supported by the hardware), which was a surpise to me.
>
> If anyone would like to post/send me the results of running the above hack
> on SPEC, the linux kernel or a code base of their choice (note it isn't
> threadsafe, so make -j1), I'd be happy to prioritize any interesting/
> frequent vector patterns.
>
>
> 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?
Ok.
>
>
> 2026-10-05 Roger Sayle <[email protected]>
> Hongtao Liu <[email protected]>
>
> gcc/ChangeLog
> * config/i386/i386-expand.cc (ix86_expand_vector_init_insert)
> <case E_V16QImode>: We don't need to zero extend var, if the
> high bytes will be overwritten.
> <case E_V8HImode>: Likewise for V8HImode. Whitespace fix.
> (ix86_expand_vector_init_qi4): New helper function to effectively
> load a V4QImode vector into an SImode register or constant.
> (ix86_expand_vector_init_qi8): Likewise, to effectively load
> a V8QImode vector into a DImode register or constant.
> (ix86_expand_vector_init_v16qi): Change return type to void,
> and never fail. Fallback to V2DI on TARGET64 and V4SI otherwise
> using the above helper functions.
> (ix86_expand_vector_init_general): Update call to
> ix86_expand_vector_init_v16qi now that it can't fail.
>
> gcc/testsuite/ChangeLog
> * gcc.target/i386/avx2-init-v16qi-1.c: New test case.
> * gcc.target/i386/avx-init-v16qi-1.c: Add more test vectors.
> * gcc.target/i386/sse-init-v16qi-1.c: Likewise.
> * gcc.target/i386/sse2-init-v16qi-2.c: Likewise.
> * gcc.target/i386/sse2-init-v16qi-3.c: Likewise.
> * gcc.target/i386/sse4_1-init-v16qi-1.c: Likewise.
>
>
> Thanks again,
> Roger
> --
>
>> -----Original Message-----
>> From: Hongtao Liu <[email protected]>
>> Sent: 08 September 2026 04:45
>> Subject: Re: [PATCH] Improve V16QI vector initialization on x86 SSE.
>>
>> On Wed, Sep 2, 2026 at 11:01 PM Roger Sayle <[email protected]>
>> wrote:
>> > vpinsrb $1, %esi, %xmm0, %xmm0
>> > vpbroadcastw %xmm0, %xmm0
>> > ret
>> >
>> > bar: vmovdqa .LC0(%rip), %xmm0
>> > vpinsrb $0, %edi, %xmm0, %xmm0
>> > vpinsrb $8, %edi, %xmm0, %xmm0
>> > ret
>> >
>> > There's still more that can be done/improved, but I stopped here
>> > (1) because the patch is already quite large and (2) I'm not sure if
>> > the final bar above is optimal (yes in number of instructions), or if
>> > (v2di){0x12345678abcdefLL,0} is better written as movabs+movq?
>> We can stop here until we find real opportunity in real workload.
>>
>> >+ for (i = 0; i < 4; i++)
>> >+ if (CONST_INT_P (ops[i]) && ops[i] != const0_rtx)
>> >+ {
>> >+ val += (UINTVAL (ops[0]) & 0xff) << (i*8);
>>
>> typo, should be ops[i], not ops[0]?
>> >+ vars[i] = const0_rtx;
>> >+ }
>>
>> >+ bool all_same_p = true;
>> >+ for (i = 1; i < 16; i++)
>> >+ if (!rtx_equal_p (ops[i], ops[0]))
>> >+ {
>> >+ all_same_p = false;
>> >+ break;
>> >+ }
>> >+ if (all_same_p)
>> We already handle all_same_p in ix86_expand_vector_init before it reaches
>> _general, and I didn't see any place with recursively call which needs to
>> handle
>> all_same_p, so perhaps just remove the code for all_same_p.
>>