[PATCH] sse-init-v2df-1.c: Compile with -mfpmath=sse
"H.J. Lu" <[email protected]> Sun, 2 Aug 2026 15:48:17 +0800
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAMe9rOqJM0vVytCQOLxWhk6LSn1z1DVLHp4ap=Ro1AANGx7xEg@mail.gmail.com> |
On Sun, Aug 2, 2026 at 3:14 PM Roger Sayle <[email protected]> wrote: > > > Hi H.J., > Sorry for the inconvenience. The recently added 128-bit testcases > covered sse, sse2, sse4.1, avx, avx2 and avx512vl. I'd not considered > I that I'd also need tests for (or defend against) sse3. Thanks for your > -mno-sse3 fixes. I will check it. > See response to movq below: > > > -----Original Message----- > > From: H.J. Lu <[email protected]> > > Sent: 02 August 2026 05:33 > > To: Hongtao Liu <[email protected]> > > Cc: Roger Sayle <[email protected]>; Patches GCC <gcc- > > [email protected]>; Uros Bizjak <[email protected]>; Liu, Hongtao > > <[email protected]> > > Subject: [PATCH] x86: Replace -mno-sse4.1 with -mno-sse3 in commit > > f0bd50e8317 tests > > > > 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. > > We currently generate some poor code for some older combinations. > But movq is generated in these cases: > > fxx: > movlps %xmm0, -64(%rsp) > movq -64(%rsp), %rax > movq %rax, -56(%rsp) > movq %rax, -48(%rsp) > movaps -56(%rsp), %xmm0 > ret > > and the not quite so inefficient: > > fx0: > movq $0x000000000, -48(%rsp) > movlps %xmm0, -56(%rsp) > movaps -56(%rsp), %xmm0 > ret > > f0x: > movq $0x000000000, -56(%rsp) > movlps %xmm0, -48(%rsp) > movaps -56(%rsp), %xmm0 > ret These don't work when GCC is configured with --with-fpmath=sse which disables SSE math with -mno-sse2. I am checking this patch to fix it. -- H.J. --- When GCC is configured with --with-fpmath=sse, i386/ssemath.h is used, which has #undef TARGET_FPMATH_DEFAULT_P #define TARGET_FPMATH_DEFAULT_P(x) \ (TARGET_SSE2_P(x) ? FPMATH_SSE : FPMATH_387) SSE math is disabled with -mno-sse2. Since sse-init-v2df-1.c requires SSE math, compile sse-init-v2df-1.c with -mfpmath=sse so that SSE math is enabled with "-mno-sse2" * gcc.target/i386/sse-init-v2df-1.c: Compile with -mfpmath=sse.
0001-sse-init-v2df-1.c-Compile-with-mfpmath-sse.patch
(application/x-patch, 1.3 KB)
From f22241ccacd82ea3f43b1dd19188688c4b546ce9 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <[email protected]> Date: Sun, 2 Aug 2026 15:33:35 +0800 Subject: [PATCH] sse-init-v2df-1.c: Compile with -mfpmath=sse When GCC is configured with --with-fpmath=sse, i386/ssemath.h is used, which has #undef TARGET_FPMATH_DEFAULT_P #define TARGET_FPMATH_DEFAULT_P(x) \ (TARGET_SSE2_P(x) ? FPMATH_SSE : FPMATH_387) SSE math is disabled with -mno-sse2. Since sse-init-v2df-1.c requires SSE math, compile sse-init-v2df-1.c with -mfpmath=sse so that SSE math is enabled with "-mno-sse2" * gcc.target/i386/sse-init-v2df-1.c: Compile with -mfpmath=sse. Signed-off-by: H.J. Lu <[email protected]> --- gcc/testsuite/gcc.target/i386/sse-init-v2df-1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.target/i386/sse-init-v2df-1.c b/gcc/testsuite/gcc.target/i386/sse-init-v2df-1.c index f686d4ed5e8..7315bd2f2e1 100644 --- a/gcc/testsuite/gcc.target/i386/sse-init-v2df-1.c +++ b/gcc/testsuite/gcc.target/i386/sse-init-v2df-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -msse -mno-sse2" } */ +/* { dg-options "-O2 -msse -mno-sse2 -mfpmath=sse" } */ typedef double v2df __attribute__ ((__vector_size__ (16))); -- 2.55.0