Hi,
This is authored-by: Zhongjie Guo <[email protected]>.
c86-4g-m7 is a split-regs AVX512 target. A 512-bit memory
operation is implemented as two 256-bit halves, so the vectorizer cost
model should not make 512-bit loads and stores almost as cheap as
256-bit ones.
The old c86_4g_m7_cost values made 512-bit loads/stores cost 12/12,
close to or equal to the 256-bit 10/12 costs. This can make 64-byte
vectorization win in the loop body cost comparison even when 32-byte
vectors avoid extra reduction epilogue work.
Set the 512-bit load/store and unaligned load/store costs to twice the
256-bit costs. This removes the artificial 64-byte body-cost advantage;
for dot-product style reduction loops, the reduction epilogue cost can
then make 32-byte vectorization preferable.
Compared with gcc-trunk without this tuning, local SPEC2006/SPEC2017
testing shows improvements in several vector-width sensitive workloads.
SPEC2006 1-copy fp_speed improved by 2.32%, including 436.cactusADM
+12.39%, 433.milc +7.33%, and 459.GemsFDTD +4.76%. SPEC2017 32-copy
fprate improved by 0.40%, with 526.blender_r improving by 2.80%.
Bootstrapped and regtested on a hygon c86-4g-m7 machine.
Is it ok for trunk? Also ok to backport to gcc-16 after burn-in
time? (considering gcc-16 supports ix86-vect-compare-costs)
BR,
Kewen
-----
gcc/ChangeLog:
* config/i386/x86-tune-costs.h (c86_4g_m7_cost): Increase
512-bit load/store and unaligned load/store costs.
gcc/testsuite/ChangeLog:
* gcc.target/i386/c86-4g-m7-vect-load-cost-reduc.c: New test.
Signed-off-by: Zhongjie Guo <[email protected]>
---
gcc/config/i386/x86-tune-costs.h | 12 +++++------
.../i386/c86-4g-m7-vect-load-cost-reduc.c | 21 +++++++++++++++++++
2 files changed, 27 insertions(+), 6 deletions(-)
create mode 100644
gcc/testsuite/gcc.target/i386/c86-4g-m7-vect-load-cost-reduc.c
diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h
index deb752889ac..8cbc2125973 100644
--- a/gcc/config/i386/x86-tune-costs.h
+++ b/gcc/config/i386/x86-tune-costs.h
@@ -4612,9 +4612,9 @@ struct processor_costs c86_4g_m7_cost = {
in SImode and DImode. */
2, 2, 3, /* cost of moving XMM,YMM,ZMM
register. */
- {6, 6, 10, 10, 12}, /* cost of loading SSE registers
+ {6, 6, 10, 10, 20}, /* cost of loading SSE registers
in 32,64,128,256 and 512-bit. */
- {8, 8, 8, 12, 12}, /* cost of storing SSE registers
+ {8, 8, 8, 12, 24}, /* cost of storing SSE registers
in 32,64,128,256 and 512-bit. */
6, 8, /* SSE->integer and integer->SSE
moves. */
@@ -4654,12 +4654,12 @@ struct processor_costs c86_4g_m7_cost = {
Relative to reg-reg move (2). */
{8, 8, 8}, /* cost of storing integer
registers. */
- {6, 6, 10, 10, 12}, /* cost of loading SSE registers
+ {6, 6, 10, 10, 20}, /* cost of loading SSE registers
in 32bit, 64bit, 128bit, 256bit and
512bit */
- {8, 8, 8, 12, 12}, /* cost of storing SSE register
+ {8, 8, 8, 12, 24}, /* cost of storing SSE register
in 32bit, 64bit, 128bit, 256bit and
512bit */
- {6, 6, 10, 10, 12}, /* cost of unaligned loads. */
- {8, 8, 8, 12, 12}, /* cost of unaligned stores. */
+ {6, 6, 10, 10, 20}, /* cost of unaligned loads. */
+ {8, 8, 8, 12, 24}, /* cost of unaligned stores. */
2, 2, 3, /* cost of moving XMM,YMM,ZMM
register. */
6, /* cost of moving SSE register to
integer. */
diff --git a/gcc/testsuite/gcc.target/i386/c86-4g-m7-vect-load-cost-reduc.c
b/gcc/testsuite/gcc.target/i386/c86-4g-m7-vect-load-cost-reduc.c
new file mode 100644
index 00000000000..2be556cefb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/c86-4g-m7-vect-load-cost-reduc.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=c86-4g-m7 -mprefer-vector-width=512 -ffast-math
-fdump-tree-vect-details" } */
+
+#define N 1024
+
+void foo (double *__restrict a, double *__restrict b, double *out)
+{
+ double sum = 1.0;
+
+ for (int i = 0; i < N; ++i)
+ sum += a[i] * b[i];
+
+ out[0] = sum;
+}
+
+/* On c86-4g-m7, 512-bit memory costs should model two 256-bit operations on
+ split-regs targets. This loop exercises the load side of that model: once
+ the normalized body cost no longer favors 64-byte vectors, the reduction
+ epilogue cost makes 32-byte vectorization preferable. */
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized using 32 byte
vectors" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-not "optimized: loop vectorized using 64 byte
vectors" "vect" } } */
--
2.34.1