On Wed, Sep 9, 2026 at 10:16 AM Uros Bizjak <[email protected]> wrote:
>
> On Wed, Sep 9, 2026 at 8:38 AM Uros Bizjak <[email protected]> wrote:
> >
> > On Wed, Sep 9, 2026 at 7:27 AM Sun, Qin <[email protected]> wrote:
> > >
> > > This patch fixes a miss-optimization issue.
> > >
> > > Pattern `vec_concatv2df` has no alternative accepting a memory operand 1
> > > and a non-zero operand 2, but the old condition accepted it with an 
> > > unclear
> > > condition `!(MEM_P (operands[1]) && MEM_P (operands[2]))`.
> > > Therefore, after combine resulted its folding with a MEM operand 1 and a
> > > REG operand 2, the old condition would wrongly advertise the unencodable
> > > form. A reload would be needed by LRA, which might result in one more
> > > instruction.
> > > To avoid such situations, we should reject MEM as operand 1 in the 
> > > condition
> > > unless operand 2 is a CONST 0.
> > >
> > > Take this case as an example:
> > >
> > > v2df foo3 (double* a, double *b) { return __extension__(v2df) {*b, *a}; }
> > >
> > > Before with -O3 -march=znver5, we generated:
> > > foo3:
> > >         vmovsd  (%rdi), %xmm0
> > >         vmovsd  (%rsi), %xmm1
> > >         vunpcklpd       %xmm0, %xmm1, %xmm0
> > >         ret
> > >
> > > By narrowing the condition, now we generate:
> > > foo3:
> > >         vmovsd  (%rdi), %xmm0
> > >         vmovhpd (%rdi), %xmm0, %xmm0
> > >         ret
> > >
> > > gcc/ChangeLog:
> > >
> > >         * config/i386/sse.md (vec_concatv2df): Restrict the condition
> > >         to accept only CONST0_RTX as operand 2 when operand 1 is MEM.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >         * gcc.target/i386/vec-concatv2df-1.c: New test.
> >
> > OK.
> >
> > GCC 16 got it right by chance, because it expanded to:
> >
> >     8: r106:DF=[r108:DI]
> >       REG_DEAD r108:DI
> >     9: r104:V2DF=vec_concat(r106:DF,[r107:DI])
> >       REG_DEAD r107:DI
> >       REG_DEAD r106:DF
> >
> > while mainline expands to:
> >
> >     8: r106:DF=[r107:DI]
> >       REG_DEAD r107:DI
> >     9: r104:V2DF=vec_concat([r108:DI],r106:DF)
> >       REG_DEAD r108:DI
> >       REG_DEAD r106:DF
>
> A follow-up question: there are two similar patterns:
>
> "*vec_concatv2sf_sse4_1"
> "*vec_concatv2si_sse4_1"
>
> should this fix be applied to these two as well?

Like the attached patch that robustifies vec_concatv2{si,sf}_* patterns.

Uros.
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index fe25d3cdce4..eb3b8eb2fe0 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -12480,7 +12480,8 @@ (define_insn "*vec_concatv2sf_sse4_1"
          "  0, 0,Yv, 0,0, v,m, 0 , m")
          (match_operand:SF 2 "nonimm_or_0_operand"
          " Yr,*x,Yv, jm,jm, m,C,*ym, C")))]
-  "TARGET_SSE4_1 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+  "TARGET_SSE4_1
+   && (operands[2] == CONST0_RTX (SFmode) || !MEM_P (operands[1]))"
   "@
    unpcklps\t{%2, %0|%0, %2}
    unpcklps\t{%2, %0|%0, %2}
@@ -12544,7 +12545,7 @@ (define_insn "*vec_concatv2sf_sse"
        (vec_concat:V2SF
          (match_operand:SF 1 "nonimmediate_operand" " 0,m, 0, m")
          (match_operand:SF 2 "reg_or_0_operand"     " x,C,*y, C")))]
-  "TARGET_SSE"
+  "TARGET_SSE && !TARGET_SSE4_1"
   "@
    unpcklps\t{%2, %0|%0, %2}
    movss\t{%1, %0|%0, %1}
@@ -22464,7 +22465,8 @@ (define_insn "*vec_concatv2si_sse4_1"
          "  0, 0, x,Yv, 0, 0,Yv,rm,  0,rm")
          (match_operand:SI 2 "nonimm_or_0_operand"
          "jrjm,jrjm,rm,rm,Yr,*x,Yv, C,*ym, C")))]
-  "TARGET_SSE4_1 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+  "TARGET_SSE4_1
+   && (operands[2] == CONST0_RTX (SImode) || !MEM_P (operands[1]))"
   "@
    pinsrd\t{$1, %2, %0|%0, %2, 1}
    pinsrd\t{$1, %2, %0|%0, %2, 1}
@@ -22512,7 +22514,7 @@ (define_insn "*vec_concatv2si_sse4_1"
 ;; ??? In theory we can match memory for the MMX alternative, but allowing
 ;; nonimmediate_operand for operand 2 and *not* allowing memory for the SSE
 ;; alternatives pretty much forces the MMX alternative to be chosen.
-(define_insn "*vec_concatv2si"
+(define_insn "*vec_concatv2si_sse"
   [(set (match_operand:V2SI 0 "register_operand"     "=x,x ,x,x,*y,*y")
        (vec_concat:V2SI
          (match_operand:SI 1 "nonimmediate_operand" " 0,rm,0,m, 0,rm")

Reply via email to