[PATCH] x86: Replace -mno-sse4.1 with -mno-sse3 in commit f0bd50e8317 tests
"H.J. Lu" <[email protected]> Sun, 2 Aug 2026 12:32:49 +0800
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAMe9rOrU-9fCaqTOHj+YwoDU72427gev3p9r7A4LphjXHp=6Bg@mail.gmail.com> |
On Sun, Aug 2, 2026 at 11:06 AM H.J. Lu <[email protected]> wrote: > > On Wed, Jul 22, 2026 at 4:05 PM Hongtao Liu <[email protected]> wrote: > > > > On Tue, Jul 21, 2026 at 5:11 PM Roger Sayle <[email protected]> wrote: > > > > > > > > > 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 > > > > > > v4si f3(int x) { return (v4si){x,1,x,2}; } > > > > > > Before with -O2: > > > f3_old: movl $2, %eax > > > movd %edi, %xmm0 > > > movd %eax, %xmm2 > > > movl $1, %eax > > > movdqa %xmm0, %xmm1 > > > movd %eax, %xmm3 > > > punpckldq %xmm2, %xmm1 > > > punpckldq %xmm3, %xmm0 > > > punpcklqdq %xmm1, %xmm0 > > > ret > > > > > > After with -O2: > > > f3_new: movd %edi, %xmm0 > > > shufps $68, %xmm0, %xmm0 > > > por .LC0(%rip), %xmm0 > > > ret > > > > > > v16qi f4(char x) { return (v16qi){x,0,0,0,0,0,0,0,0,x,0,0,0,0,0,0}; } > > > > > > Before with -O2 -mavx2: > > > f4_old: vmovd %edi, %xmm0 > > > xorl %eax, %eax > > > vpxor %xmm1, %xmm1, %xmm1 > > > vpinsrb $1, %eax, %xmm0, %xmm0 > > > vpinsrb $1, %edi, %xmm1, %xmm1 > > > vpmovzxwd %xmm0, %xmm0 > > > vpmovzxwd %xmm1, %xmm1 > > > vpmovzxdq %xmm1, %xmm1 > > > vpmovzxdq %xmm0, %xmm0 > > > vpunpcklqdq %xmm1, %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: > > > > > > orig: vmovd (%rdi), %xmm2 > > > vpinsrd $1, 4(%rdi), %xmm2, %xmm1 > > > vpunpcklqdq %xmm1, %xmm0, %xmm16 > > > ret > > > > > > where actually an optimal implementation should require only two: > > > > > > ideal: vpinsrd $2, (%rdi), %xmm0, %xmm0 > > > vpinsrd $3, 4(%rdi), %xmm0, %xmm0 > > > ret > > > > > > but unfortunately with this patch we currently (for now) generate: > > > > > > curr: vmovd %xmm0, %eax > > > vpextrd $1, %xmm0, %edx > > > vmovd %eax, %xmm0 > > > vpinsrd $1, %edx, %xmm0, %xmm0 > > > vpinsrd $2, (%rdi), %xmm0, %xmm0 > > > vpinsrd $3, 4(%rdi), %xmm0, %xmm0 > > > vmovdqa32 %xmm0, %xmm16 > > > ret > > > > > > 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). > > > > > > > > > + else if (TARGET_SSE2) > > + { > > + rtx tmp2 = gen_reg_rtx (V2DImode); > > + emit_move_insn (tmp2, gen_lowpart (V2DImode, tmp)); > > + emit_insn (gen_vec_shl_v2di (target, tmp, GEN_INT (64))); > > > > Looks like a typo, should be tmp2 instead of tmp? > > > > + case E_V2DFmode: > > + if (!REG_P (var) || !MEM_P (var)) > > + var = force_reg (DFmode, var); > > + x = gen_rtx_VEC_CONCAT (V2DFmode, var, CONST0_RTX (DFmode)); > > + if (!one_var) > > + emit_insn (gen_rtx_SET (target, x)); > > + else if (TARGET_SSE2) > > + { > > + tmp = gen_reg_rtx (V2DFmode); > > + emit_insn (gen_rtx_SET (tmp, x)); > > + emit_insn (gen_vec_shl_v2df (target, tmp, GEN_INT (64))); > > + } > > + else > > + { > > + rtx tmp1 = gen_reg_rtx (V2DFmode); > > + emit_insn (gen_rtx_SET (tmp1, x)); > > + rtx tmp2 = gen_reg_rtx (V4SImode); > > + emit_move_insn (tmp2, gen_lowpart (V4SImode, tmp1)); > > + emit_insn (gen_sse_shufps_v4si (tmp2, tmp2, tmp2, > > + GEN_INT (2), GEN_INT (3), > > + GEN_INT (4), GEN_INT (5))); > > + emit_move_insn (target, gen_lowpart (V2DFmode, tmp2)); > > + } > > > > vec_initv2df is guarded under TARGET_SSE2, so I think the else part is > > redundant. > > > > +static int > > +nonzero_int_const_count (rtx *ops, int n) > > +{ > > + int result = 0; > > + int i; > > + for (i = 0; i < n; i++) > > + if (CONST_INT_P (ops[i]) && ops[i] != const0_rtx) ---- here > > check CONST_INT_P (ops[i]) > > + result++; > > + return result; > > +} > > > > ... > > + else if (nonzero_int_const_count (ops, 4) >= 2) > > + { > > + rtx csts[4]; > > + int i; > > + for (i = 0; i < 4; i++) > > + if (CONST_DOUBLE_P (ops[i])) ---- here check > > CONST_DOUBLE_P (ops[i])) > > + { > > + csts[i] = ops[i]; > > + vars[i] = CONST0_RTX (SFmode); > > + } > > + else > > + { > > + csts[i] = CONST0_RTX (SFmode); > > + vars[i] = ops[i]; > > + } > > > > nonzero_int_const_count check CONST_INT_P, but in the float cases, it > > should be CONST_DOUBLE_P? it's always 0 the float helpers(v4sf/v8f)? > > > > > > + case E_V4DImode: > > + if (TARGET_AVX2 && (TARGET_64BIT || MEM_P (var))) > > + { > > + if (!REG_P (var) || !MEM_P (var)) > > + var = force_reg (DImode, var); > > > > !REG_P (var) && !MEM_P (var)? > > > > + case E_V4DFmode: > > + if (TARGET_AVX2) > > + { > > + if (!REG_P (var) || !MEM_P (var)) > > + var = force_reg (DFmode, var); > > Ditto > > > > + return true; > > + case E_V2DFmode: > > + if (!REG_P (var) || !MEM_P (var)) > > + var = force_reg (DFmode, var); > > + x = gen_rtx_VEC_CONCAT (V2DFmode, var, CONST0_RTX (DFmode)); > > Ditto. > > > > + if (TARGET_64BIT || MEM_P (var)) > > + { > > + if (!REG_P (var) || !MEM_P (var)) > > + var = force_reg (DImode, var); > > + x = gen_rtx_VEC_CONCAT (V2DImode, var, CONST0_RTX (DImode)); > > Ditto. > > > > +/* Helper function. Determine if the given OPS array of size N > > + contains only zeros and one other value (possible repeated). > > + If TRUE, *VAR returns the value, PERM[i] contains 0 for for > > > > Double *for* in the comments. > > > > +/* Helper function. Determine if the given OPS array of size N > > + contains only zeros and two other values (possible repeated). > > + If TRUE, VARS returns the values, PERM[i] contains 0 for for > > > > Ditto. > > > > Could you also add some testcases to cover your changes, it can be in > > a separate commit. > > > > With > > commit f0bd50e831792692ffcedf288b312167a9339260 > Author: Roger Sayle <[email protected]> > Date: Sat Aug 1 17:51:02 2026 +0100 > > x86 SSE: Improved vector initialization/construction. > > I got > > FAIL: gcc.target/i386/sse-init-v2df-1.c scan-assembler-times movq 10 I don't see how movq can be generated with only SSE. > I also got > > FAIL: gcc.target/i386/sse2-init-v2df-1.c scan-assembler-times movsd 2 > FAIL: gcc.target/i386/sse2-init-v2df-1.c scan-assembler-times unpcklpd 3 > FAIL: gcc.target/i386/sse2-init-v2df-2.c scan-assembler-times movsd 3 > FAIL: gcc.target/i386/sse2-init-v2df-2.c scan-assembler-times unpcklpd 2 > FAIL: gcc.target/i386/sse2-init-v2di-3.c scan-assembler-times movq 9 > FAIL: gcc.target/i386/sse2-init-v2di-3.c scan-assembler-times punpcklqdq 3 > FAIL: gcc.target/i386/sse2-init-v2di-4.c scan-assembler-times movd 4 > FAIL: gcc.target/i386/sse2-init-v2di-4.c scan-assembler-times movq 6 > FAIL: gcc.target/i386/sse2-init-v2di-4.c scan-assembler-times punpcklqdq 2 Here is the patch to fix these failures. > with > > $ make check-gcc RUNTESTFLAGS="--target_board='unix{-m32\ > -march=x86-64-v2,-march=x86-64-v2}' i386.exp=sse2-init-*.c" > > > -- > H.J. -- H.J. --- commit f0bd50e831792692ffcedf288b312167a9339260 Author: Roger Sayle <[email protected]> Date: Sat Aug 1 17:51:02 2026 +0100 x86 SSE: Improved vector initialization/construction. improved vector initialization/construction. But some tests failed with SSE3. For expample, with SSE3, we generate better codes: fmm: movddup m(%rip), %xmm0 ret than with SSE2: fmm: movsd m(%rip), %xmm0 unpcklpd %xmm0, %xmm0 ret for fmm in gcc.target/i386/sse2-init-v2df-1.c. Replace -mno-sse4.1 with -mno-sse3 to disable SSE3 in these tests. * gcc.target/i386/sse2-init-v2df-1.c: Replace -mno-sse4.1 with -mno-sse3. * gcc.target/i386/sse2-init-v2df-2.c: Likewise. * gcc.target/i386/sse2-init-v2di-1.c: Likewise. * gcc.target/i386/sse2-init-v2di-2.c: Likewise.
0001-x86-Replace-mno-sse4.1-with-mno-sse3-in-commit-f0bd5.patch
(application/x-patch, 3.2 KB)
From 390049f52db616393244f2aa893276b0e54428c3 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Sun, 2 Aug 2026 11:42:24 +0800 Subject: [PATCH] x86: Replace -mno-sse4.1 with -mno-sse3 in commit f0bd50e8317 tests commit f0bd50e831792692ffcedf288b312167a9339260 Author: Roger Sayle <[email protected]> Date: Sat Aug 1 17:51:02 2026 +0100 x86 SSE: Improved vector initialization/construction. improved vector initialization/construction. But some tests failed with SSE3. For expample, with SSE3, we generate better codes: fmm: movddup m(%rip), %xmm0 ret than with SSE2: fmm: movsd m(%rip), %xmm0 unpcklpd %xmm0, %xmm0 ret for fmm in gcc.target/i386/sse2-init-v2df-1.c. Replace -mno-sse4.1 with -mno-sse3 to disable SSE3 in these tests. * gcc.target/i386/sse2-init-v2df-1.c: Replace -mno-sse4.1 with -mno-sse3. * gcc.target/i386/sse2-init-v2df-2.c: Likewise. * gcc.target/i386/sse2-init-v2di-1.c: Likewise. * gcc.target/i386/sse2-init-v2di-2.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> --- gcc/testsuite/gcc.target/i386/sse2-init-v2df-1.c | 2 +- gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c | 2 +- gcc/testsuite/gcc.target/i386/sse2-init-v2di-3.c | 2 +- gcc/testsuite/gcc.target/i386/sse2-init-v2di-4.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-1.c b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-1.c index d73a32e9e88..293d7db2d09 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-1.c +++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -msse2 -mno-sse4.1" } */ +/* { dg-options "-O2 -msse2 -mno-sse3" } */ typedef double v2df __attribute__ ((__vector_size__ (16))); diff --git a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c index 2e091eeabf6..3f58098af8d 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c +++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2df-2.c @@ -1,5 +1,5 @@ /* { dg-do compile { target ia32 } } */ -/* { dg-options "-O2 -msse2 -mno-sse4.1" } */ +/* { dg-options "-O2 -msse2 -mno-sse3" } */ typedef double v2df __attribute__ ((__vector_size__ (16))); diff --git a/gcc/testsuite/gcc.target/i386/sse2-init-v2di-3.c b/gcc/testsuite/gcc.target/i386/sse2-init-v2di-3.c index b054daad119..15c6b9c4d63 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-init-v2di-3.c +++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2di-3.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -msse2 -mno-sse4.1" } */ +/* { dg-options "-O2 -msse2 -mno-sse3" } */ typedef long long v2di __attribute__ ((__vector_size__ (16))); diff --git a/gcc/testsuite/gcc.target/i386/sse2-init-v2di-4.c b/gcc/testsuite/gcc.target/i386/sse2-init-v2di-4.c index 272b6b23039..133115ab4f8 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-init-v2di-4.c +++ b/gcc/testsuite/gcc.target/i386/sse2-init-v2di-4.c @@ -1,5 +1,5 @@ /* { dg-do compile { target ia32 } } */ -/* { dg-options "-O2 -msse2 -mno-sse4.1" } */ +/* { dg-options "-O2 -msse2 -mno-sse3" } */ typedef long long v2di __attribute__ ((__vector_size__ (16))); -- 2.55.0