https://gcc.gnu.org/g:8747b25bcd9606418296906091674d97fd4b65a7
commit r17-4049-g8747b25bcd9606418296906091674d97fd4b65a7 Author: Uros Bizjak <[email protected]> Date: Thu Sep 10 08:11:56 2026 +0200 i386: Improve insn conditions of vec_concatv2{sf,si} patterns for SSE4.1 Improve an incorrect insn condition and avoid selecting the SSE vec_concatv2sf pattern when SSE4.1 is available. The SSE4.1 pattern has alternatives that accept a memory operand 1 only when operand 2 is zero. However, its old condition only rejected the case where both operands were memory operands. As a result, a memory operand 1 combined with a non-zero register operand 2 could be advertised even though that form is not encodable. Restrict the condition in the same way as the available alternatives: when operand 1 is a MEM, operand 2 must be CONST0_RTX. The generic SSE pattern is also disabled when SSE4.1 is enabled, so that the more appropriate SSE4.1 pattern is selected. gcc/ChangeLog: * config/i386/sse.md (*vec_concatv2sf_sse4_1): Restrict the condition to accept only CONST0_RTX as operand 2 when operand 1 is MEM. (*vec_concatv2si_sse4_1): Ditto. (*vec_concatv2sf_sse): Disable the pattern when SSE4.1 is enabled. (*vec_concatv2si_sse): Rename from *vec_concatv2si. gcc/testsuite/ChangeLog: * gcc.target/i386/vec-concatv2sf.c: New test. Diff: --- gcc/config/i386/sse.md | 10 ++++++---- gcc/testsuite/gcc.target/i386/vec-concatv2sf.c | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index fe25d3cdce49..eb3b8eb2fe05 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -12480,7 +12480,8 @@ " 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 @@ (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 @@ " 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 @@ ;; ??? 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") diff --git a/gcc/testsuite/gcc.target/i386/vec-concatv2sf.c b/gcc/testsuite/gcc.target/i386/vec-concatv2sf.c new file mode 100644 index 000000000000..925f18a54b6f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vec-concatv2sf.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mavx -masm=att" } */ + +typedef float v2sf __attribute__((vector_size (8))); + +v2sf +f1 (float *a, float *b) +{ + return (v2sf) { *b, *a }; +} + +/* { dg-final { scan-assembler-times "vinsertps\[ \t]" 1 } } */ +/* { dg-final { scan-assembler-not "vunpcklps" } } */ + +v2sf +f2 (float *a) +{ + return (v2sf) { *a, 0.0 }; +} + +/* { dg-final { scan-assembler-times "vmovss\[ \t]" 2 } } */
