https://gcc.gnu.org/g:1df63c7f3a3f9c52669c11d289abc0238e909813
commit r17-4021-g1df63c7f3a3f9c52669c11d289abc0238e909813 Author: Sun, Qin <[email protected]> Date: Wed Aug 26 13:07:47 2026 +0800 i386: make vec_concatv2df's condition match its constraints 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.c: New test. Diff: --- gcc/config/i386/sse.md | 2 +- gcc/testsuite/gcc.target/i386/vec-concatv2df.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index e4bc746dacc5..fe25d3cdce49 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -15739,7 +15739,7 @@ (vec_concat:V2DF (match_operand:DF 1 "nonimmediate_operand" " 0,x,v,0,x,vm,0,0") (match_operand:DF 2 "nonimm_or_0_operand" " x,x,v,m,m, C,x,m")))] - "TARGET_SSE && !(MEM_P (operands[1]) && MEM_P (operands[2]))" + "TARGET_SSE && (operands[2] == CONST0_RTX (DFmode) || !MEM_P (operands[1]))" "@ unpcklpd\t{%2, %0|%0, %2} vunpcklpd\t{%2, %1, %0|%0, %1, %2} diff --git a/gcc/testsuite/gcc.target/i386/vec-concatv2df.c b/gcc/testsuite/gcc.target/i386/vec-concatv2df.c new file mode 100644 index 000000000000..1ae58b946023 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vec-concatv2df.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx -masm=att" } */ + +typedef double v2df __attribute__((vector_size (16))); + +v2df +f1 (double *a, double *b) +{ + return (v2df) { *b, *a }; +} + +/* { dg-final { scan-assembler-times "vmovhpd\[ \t]" 1 } } */ +/* { dg-final { scan-assembler-not "vunpcklpd" } } */ + +v2df +f2 (double *a) +{ + return (v2df) { *a, 0.0 }; +} + +/* { dg-final { scan-assembler-times "vmovq\[ \t]" 1 } } */ +/* { dg-final { scan-assembler-times "vmovsd\[ \t]" 1 } } */
