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.
---
gcc/config/i386/sse.md | 2 +-
.../gcc.target/i386/vec-concatv2df.c | 22 +++++++++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/i386/vec-concatv2df.c
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index e4bc746dacc..fe25d3cdce4 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 00000000000..1ae58b94602
--- /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 } } */
--
2.25.1