Merged
[Backport] i386: Add avx512_avoid_vec_perm tune for c86-4g-m7 #394
[Backport] i386: Add avx512_avoid_vec_perm tune for c86-4g-m7 #394
Merged
haibaooAdd on Aug 17
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. */
23146class ix86_vector_costs : public vector_costs23147class 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 
23158static vector_costs *23171static 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+ 
23164unsigned23218unsigned
23165ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,23219ix86_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 
23404static unsigned HOST_WIDE_INT23489static 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)
556DEF_TUNE (X86_TUNE_AVX512_SPLIT_REGS, "avx512_split_regs", m_ZNVER4556DEF_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-bit563/* X86_TUNE_AVX256_MOVE_BY_PIECES: Optimize move_by_pieces with 256-bit
560 AVX instructions. */564 AVX instructions. */
561DEF_TUNE (X86_TUNE_AVX256_MOVE_BY_PIECES, "avx256_move_by_pieces",565DEF_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 handles1149 /* 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-