Merged
[Backport] i386: Add avx512_avoid_vec_perm tune for c86-4g-m7 #394
haibaooAdd on Aug 17
[Backport] i386: Add avx512_avoid_vec_perm tune for c86-4g-m7 #394
Merged
Total: 7 files changed+189-3
| @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see | |||
| 27 | #include "tree.h" | 27 | #include "tree.h" |
| 28 | #include "memmodel.h" | 28 | #include "memmodel.h" |
| 29 | #include "gimple.h" | 29 | #include "gimple.h" |
| 30 | +#include "gimple-pretty-print.h" | ||
| 30 | #include "cfghooks.h" | 31 | #include "cfghooks.h" |
| 31 | #include "cfgloop.h" | 32 | #include "cfgloop.h" |
| 32 | #include "df.h" | 33 | #include "df.h" |
| @@ -23145,14 +23146,26 @@ ix86_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) | |||
| 23145 | /* x86-specific vector costs. */ | 23146 | /* x86-specific vector costs. */ |
| 23146 | class ix86_vector_costs : public vector_costs | 23147 | class ix86_vector_costs : public vector_costs |
| 23147 | { | 23148 | { |
| 23148 | - using vector_costs::vector_costs; | 23149 | +public: |
| 23150 | + ix86_vector_costs (vec_info *, bool); | ||
| 23149 | 23151 | ||
| 23150 | unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind, | 23152 | unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind, |
| 23151 | stmt_vec_info stmt_info, slp_tree node, | 23153 | stmt_vec_info stmt_info, slp_tree node, |
| 23152 | tree vectype, int misalign, | 23154 | tree vectype, int misalign, |
| 23153 | vect_cost_model_location where) override; | 23155 | vect_cost_model_location where) override; |
| 23156 | + void finish_cost (const vector_costs *scalar_costs) override; | ||
| 23157 | + | ||
| 23158 | +private: | ||
| 23159 | + /* Number of 512-bit vector permutations. */ | ||
| 23160 | + unsigned m_num_avx512_vec_perm[3]; | ||
| 23154 | }; | 23161 | }; |
| 23155 | 23162 | ||
| 23163 | +ix86_vector_costs::ix86_vector_costs (vec_info *vinfo, | ||
| 23164 | + bool costing_for_scalar) | ||
| 23165 | + : vector_costs (vinfo, costing_for_scalar), | ||
| 23166 | + m_num_avx512_vec_perm () | ||
| 23167 | +{} | ||
| 23168 | + | ||
| 23156 | /* Implement targetm.vectorize.create_costs. */ | 23169 | /* Implement targetm.vectorize.create_costs. */ |
| 23157 | 23170 | ||
| 23158 | static vector_costs * | 23171 | static vector_costs * |
| @@ -23161,6 +23174,47 @@ ix86_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) | |||
| 23161 | return new ix86_vector_costs (vinfo, costing_for_scalar); | 23174 | return new ix86_vector_costs (vinfo, costing_for_scalar); |
| 23162 | } | 23175 | } |
| 23163 | 23176 | ||
| 23177 | +/* Return true if a vec_perm should be counted as a cross-lane vector | ||
| 23178 | + permutation for a vector with NUNITS elements. */ | ||
| 23179 | +static bool | ||
| 23180 | +ix86_count_cross_lane_perm_p (vec_info *vinfo, slp_tree node, unsigned nunits) | ||
| 23181 | +{ | ||
| 23182 | + /* TODO: For loop vectorization with no SLP load-permutation | ||
| 23183 | + information, conservatively treat these perms as cross-lane. | ||
| 23184 | + Repeated-index cases such as {0, 0, 0, 0} are emitted as | ||
| 23185 | + separate vec_perm_exprs for each index, so we cannot reliably | ||
| 23186 | + separate false positives from real cross-lane shuffles yet. */ | ||
| 23187 | + if (!node | ||
| 23188 | + || !SLP_TREE_LOAD_PERMUTATION (node).exists () | ||
| 23189 | + || !is_a<bb_vec_info> (vinfo)) | ||
| 23190 | + return true; | ||
| 23191 | + | ||
| 23192 | + unsigned half = nunits / 2; | ||
| 23193 | + bool allsame = true; | ||
| 23194 | + unsigned first = SLP_TREE_LOAD_PERMUTATION (node)[0]; | ||
| 23195 | + bool cross_lane_p = false; | ||
| 23196 | + | ||
| 23197 | + for (unsigned i = 0; i != SLP_TREE_LANES (node); i++) | ||
| 23198 | + { | ||
| 23199 | + unsigned tmp = SLP_TREE_LOAD_PERMUTATION (node)[i]; | ||
| 23200 | + /* allsame is just a broadcast. */ | ||
| 23201 | + if (tmp != first) | ||
| 23202 | + allsame = false; | ||
| 23203 | + | ||
| 23204 | + /* The load permutation can cover multiple vectors, so compare | ||
| 23205 | + source and destination lanes modulo NUNITS. */ | ||
| 23206 | + tmp = tmp & (nunits - 1); | ||
| 23207 | + unsigned index = i & (nunits - 1); | ||
| 23208 | + if ((index < half && tmp >= half) || (index >= half && tmp < half)) | ||
| 23209 | + cross_lane_p = true; | ||
| 23210 | + | ||
| 23211 | + if (!allsame && cross_lane_p) | ||
| 23212 | + return true; | ||
| 23213 | + } | ||
| 23214 | + | ||
| 23215 | + return false; | ||
| 23216 | +} | ||
| 23217 | + | ||
| 23164 | unsigned | 23218 | unsigned |
| 23165 | ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, | 23219 | ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, |
| 23166 | stmt_vec_info stmt_info, slp_tree node, | 23220 | stmt_vec_info stmt_info, slp_tree node, |
| @@ -23394,11 +23448,42 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, | |||
| 23394 | retval = (retval * 17) / 10; | 23448 | retval = (retval * 17) / 10; |
| 23395 | } | 23449 | } |
| 23396 | 23450 | ||
| 23451 | + /* BIT_FIELD_REF <vect_**, 64, 0> with count 0 costs 0 in body. */ | ||
| 23452 | + if (kind == vec_perm && vectype | ||
| 23453 | + && GET_MODE_SIZE (TYPE_MODE (vectype)) == 64 | ||
| 23454 | + && count != 0) | ||
| 23455 | + { | ||
| 23456 | + unsigned nunits = TYPE_VECTOR_SUBPARTS (vectype).to_constant (); | ||
| 23457 | + | ||
| 23458 | + if (ix86_count_cross_lane_perm_p (m_vinfo, node, nunits)) | ||
| 23459 | + { | ||
| 23460 | + m_num_avx512_vec_perm[where] += count; | ||
| 23461 | + if (dump_file && (dump_flags & TDF_DETAILS)) | ||
| 23462 | + { | ||
| 23463 | + fprintf (dump_file, | ||
| 23464 | + "Detected avx512 cross-lane permutation: "); | ||
| 23465 | + if (stmt_info) | ||
| 23466 | + print_gimple_expr (dump_file, stmt_info->stmt, 0, TDF_SLIM); | ||
| 23467 | + fprintf (dump_file, " \n"); | ||
| 23468 | + } | ||
| 23469 | + } | ||
| 23470 | + } | ||
| 23471 | + | ||
| 23397 | m_costs[where] += retval; | 23472 | m_costs[where] += retval; |
| 23398 | 23473 | ||
| 23399 | return retval; | 23474 | return retval; |
| 23400 | } | 23475 | } |
| 23401 | 23476 | ||
| 23477 | +void | ||
| 23478 | +ix86_vector_costs::finish_cost (const vector_costs *scalar_costs) | ||
| 23479 | +{ | ||
| 23480 | + for (int i = 0; i != 3; i++) | ||
| 23481 | + if (m_num_avx512_vec_perm[i] && TARGET_AVX512_AVOID_VEC_PERM) | ||
| 23482 | + m_costs[i] = INT_MAX; | ||
| 23483 | + | ||
| 23484 | + vector_costs::finish_cost (scalar_costs); | ||
| 23485 | +} | ||
| 23486 | + | ||
| 23402 | /* Validate target specific memory model bits in VAL. */ | 23487 | /* Validate target specific memory model bits in VAL. */ |
| 23403 | 23488 | ||
| 23404 | static unsigned HOST_WIDE_INT | 23489 | static unsigned HOST_WIDE_INT |
| @@ -427,6 +427,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; | |||
| 427 | ix86_tune_features[X86_TUNE_AVX256_SPLIT_REGS] | 427 | ix86_tune_features[X86_TUNE_AVX256_SPLIT_REGS] |
| 428 | #define TARGET_AVX512_SPLIT_REGS \ | 428 | #define TARGET_AVX512_SPLIT_REGS \ |
| 429 | ix86_tune_features[X86_TUNE_AVX512_SPLIT_REGS] | 429 | ix86_tune_features[X86_TUNE_AVX512_SPLIT_REGS] |
| 430 | +#define TARGET_AVX512_AVOID_VEC_PERM \ | ||
| 431 | + ix86_tune_features[X86_TUNE_AVX512_AVOID_VEC_PERM] | ||
| 430 | #define TARGET_GENERAL_REGS_SSE_SPILL \ | 432 | #define TARGET_GENERAL_REGS_SSE_SPILL \ |
| 431 | ix86_tune_features[X86_TUNE_GENERAL_REGS_SSE_SPILL] | 433 | ix86_tune_features[X86_TUNE_GENERAL_REGS_SSE_SPILL] |
| 432 | #define TARGET_AVOID_MEM_OPND_FOR_CMOVE \ | 434 | #define TARGET_AVOID_MEM_OPND_FOR_CMOVE \ |
| @@ -556,6 +556,10 @@ DEF_TUNE (X86_TUNE_AVX256_OPTIMAL, "avx256_optimal", m_CORE_AVX512) | |||
| 556 | DEF_TUNE (X86_TUNE_AVX512_SPLIT_REGS, "avx512_split_regs", m_ZNVER4 | 556 | DEF_TUNE (X86_TUNE_AVX512_SPLIT_REGS, "avx512_split_regs", m_ZNVER4 |
| 557 | | m_C86_4G_M7 | m_C86_4G_M8) | 557 | | m_C86_4G_M7 | m_C86_4G_M8) |
| 558 | 558 | ||
| 559 | +/* X86_TUNE_AVX512_AVOID_VEC_PERM: Avoid using 512-bit cross-lane | ||
| 560 | + vector permutation instructions in the auto-vectorizer. */ | ||
| 561 | +DEF_TUNE (X86_TUNE_AVX512_AVOID_VEC_PERM, "avx512_avoid_vec_perm", m_C86_4G_M7) | ||
| 562 | + | ||
| 559 | /* X86_TUNE_AVX256_MOVE_BY_PIECES: Optimize move_by_pieces with 256-bit | 563 | /* X86_TUNE_AVX256_MOVE_BY_PIECES: Optimize move_by_pieces with 256-bit |
| 560 | AVX instructions. */ | 564 | AVX instructions. */ |
| 561 | DEF_TUNE (X86_TUNE_AVX256_MOVE_BY_PIECES, "avx256_move_by_pieces", | 565 | DEF_TUNE (X86_TUNE_AVX256_MOVE_BY_PIECES, "avx256_move_by_pieces", |
| @@ -0,0 +1,30 @@ | |||
| 1 | +/* { dg-do compile } */ | ||
| 2 | +/* { dg-options "-O2 -march=c86-4g-m7 -fdump-tree-vect-details" } */ | ||
| 3 | +/* { dg-final { scan-tree-dump "loop vectorized using 32 byte vectors" "vect" } } */ | ||
| 4 | + | ||
| 5 | +int a[512], b[512]; | ||
| 6 | + | ||
| 7 | +void | ||
| 8 | +foo (void) | ||
| 9 | +{ | ||
| 10 | + int i; | ||
| 11 | + for (i = 0; i < 32; ++i) | ||
| 12 | + { | ||
| 13 | + b[i * 16 + 0] = a[i * 16 + 0]; | ||
| 14 | + b[i * 16 + 1] = a[i * 16 + 0]; | ||
| 15 | + b[i * 16 + 2] = a[i * 16 + 3]; | ||
| 16 | + b[i * 16 + 3] = a[i * 16 + 5]; | ||
| 17 | + b[i * 16 + 4] = a[i * 16 + 4]; | ||
| 18 | + b[i * 16 + 5] = a[i * 16 + 6]; | ||
| 19 | + b[i * 16 + 6] = a[i * 16 + 4]; | ||
| 20 | + b[i * 16 + 7] = a[i * 16 + 9]; | ||
| 21 | + b[i * 16 + 8] = a[i * 16 + 8]; | ||
| 22 | + b[i * 16 + 9] = a[i * 16 + 8]; | ||
| 23 | + b[i * 16 + 10] = a[i * 16 + 11]; | ||
| 24 | + b[i * 16 + 11] = a[i * 16 + 13]; | ||
| 25 | + b[i * 16 + 12] = a[i * 16 + 12]; | ||
| 26 | + b[i * 16 + 13] = a[i * 16 + 14]; | ||
| 27 | + b[i * 16 + 14] = a[i * 16 + 12]; | ||
| 28 | + b[i * 16 + 15] = a[i * 16 + 14]; | ||
| 29 | + } | ||
| 30 | +} | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +/* { dg-do compile } */ | ||
| 2 | +/* { dg-options "-march=c86-4g-m7 -O2 -fdump-tree-slp-details" } */ | ||
| 3 | +/* { dg-final { scan-tree-dump-times {(?n)Detected avx512 cross-lane permutation} 1 "slp2" } } */ | ||
| 4 | + | ||
| 5 | +void | ||
| 6 | +foo (double *a, double *__restrict b, int c, int n) | ||
| 7 | +{ | ||
| 8 | + a[0] = b[100] * b[4]; | ||
| 9 | + a[1] = b[100] * b[5]; | ||
| 10 | + a[2] = b[100] * b[6]; | ||
| 11 | + a[3] = b[100] * b[7]; | ||
| 12 | + a[4] = b[100] * b[0]; | ||
| 13 | + a[5] = b[100] * b[1]; | ||
| 14 | + a[6] = b[100] * b[2]; | ||
| 15 | + a[7] = b[100] * b[3]; | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +void | ||
| 19 | +foo1 (double *a, double *__restrict b, int c, int n) | ||
| 20 | +{ | ||
| 21 | + a[0] = b[100] * b[0]; | ||
| 22 | + a[1] = b[100] * b[1]; | ||
| 23 | + a[2] = b[100] * b[3]; | ||
| 24 | + a[3] = b[100] * b[2]; | ||
| 25 | + a[4] = b[100] * b[4]; | ||
| 26 | + a[5] = b[100] * b[5]; | ||
| 27 | + a[6] = b[100] * b[7]; | ||
| 28 | + a[7] = b[100] * b[6]; | ||
| 29 | +} | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +/* { dg-do compile } */ | ||
| 2 | +/* { dg-options "-O2 -march=c86-4g-m7 -fdump-tree-vect-details" } */ | ||
| 3 | +/* { dg-final { scan-tree-dump "loop vectorized using 64 byte vectors" "vect" { xfail *-*-* } } } */ | ||
| 4 | + | ||
| 5 | +/* This case only has false cross-lane permutations, which should ideally be | ||
| 6 | + excluded from the loop vectorizer cost downgrade. The current loop-vect | ||
| 7 | + handling does not distinguish false cross-lane permutations from real ones, | ||
| 8 | + so the expected full-width vectorization is marked as xfail. */ | ||
| 9 | + | ||
| 10 | +int a[512], b[512]; | ||
| 11 | + | ||
| 12 | +void | ||
| 13 | +foo (void) | ||
| 14 | +{ | ||
| 15 | + int i; | ||
| 16 | + for (i = 0; i < 32; ++i) | ||
| 17 | + { | ||
| 18 | + b[i * 16 + 0] = a[i * 16 + 0]; | ||
| 19 | + b[i * 16 + 1] = a[i * 16 + 0]; | ||
| 20 | + b[i * 16 + 2] = a[i * 16 + 3]; | ||
| 21 | + b[i * 16 + 3] = a[i * 16 + 3]; | ||
| 22 | + b[i * 16 + 4] = a[i * 16 + 4]; | ||
| 23 | + b[i * 16 + 5] = a[i * 16 + 6]; | ||
| 24 | + b[i * 16 + 6] = a[i * 16 + 4]; | ||
| 25 | + b[i * 16 + 7] = a[i * 16 + 6]; | ||
| 26 | + b[i * 16 + 8] = a[i * 16 + 8]; | ||
| 27 | + b[i * 16 + 9] = a[i * 16 + 8]; | ||
| 28 | + b[i * 16 + 10] = a[i * 16 + 11]; | ||
| 29 | + b[i * 16 + 11] = a[i * 16 + 11]; | ||
| 30 | + b[i * 16 + 12] = a[i * 16 + 12]; | ||
| 31 | + b[i * 16 + 13] = a[i * 16 + 14]; | ||
| 32 | + b[i * 16 + 14] = a[i * 16 + 12]; | ||
| 33 | + b[i * 16 + 15] = a[i * 16 + 14]; | ||
| 34 | + } | ||
| 35 | +} | ||
| @@ -1142,7 +1142,9 @@ vect_model_load_cost (vec_info *vinfo, | |||
| 1142 | vect_transform_slp_perm_load (vinfo, slp_node, vNULL, NULL, | 1142 | vect_transform_slp_perm_load (vinfo, slp_node, vNULL, NULL, |
| 1143 | vf, true, &n_perms, &n_loads); | 1143 | vf, true, &n_perms, &n_loads); |
| 1144 | inside_cost += record_stmt_cost (cost_vec, n_perms, vec_perm, | 1144 | inside_cost += record_stmt_cost (cost_vec, n_perms, vec_perm, |
| 1145 | - first_stmt_info, 0, vect_body); | 1145 | + first_stmt_info, slp_node, |
| 1146 | + STMT_VINFO_VECTYPE (first_stmt_info), | ||
| 1147 | + 0, vect_body); | ||
| 1146 | 1148 | ||
| 1147 | /* And adjust the number of loads performed. This handles | 1149 | /* And adjust the number of loads performed. This handles |
| 1148 | redundancies as well as loads that are later dead. */ | 1150 | redundancies as well as loads that are later dead. */ |
| @@ -13577,4 +13579,3 @@ vect_gen_len (tree len, tree start_index, tree end_index, tree len_limit) | |||
| 13577 | 13579 | ||
| 13578 | return stmts; | 13580 | return stmts; |
| 13579 | } | 13581 | } |
| 13580 | - | ||