aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vectorizer.h
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2021-11-04 12:31:17 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2021-11-04 12:31:17 +0000
commit6239dd05127f1dc05f13f504805d36e8ebe1c2c5 (patch)
tree27c1a57b8c23d47801a5c3d62e95e17c15ddbfa4 /gcc/tree-vectorizer.h
parentaf976d90fa15b379b766647fea34e6b2c37d5c16 (diff)
downloadgcc-6239dd05127f1dc05f13f504805d36e8ebe1c2c5.zip
gcc-6239dd05127f1dc05f13f504805d36e8ebe1c2c5.tar.gz
gcc-6239dd05127f1dc05f13f504805d36e8ebe1c2c5.tar.bz2
vect: Convert cost hooks to classes
The current vector cost interface has a quite a bit of redundancy built in. Each target that defines its own hooks has to replicate the basic unsigned[3] management. Currently each target also duplicates the cost adjustment for inner loops. This patch instead defines a vector_costs class for holding the scalar or vector cost and allows targets to subclass it. There is then only one costing hook: to create a new costs structure of the appropriate type. Everything else can be virtual functions, with common concepts implemented in the base class rather than in each target's derivation. This might seem like excess C++-ification, but it shaves ~100 LOC. I've also got some follow-on changes that become significantly easier with this patch. Maybe it could help with things like weighting blocks based on frequency too. This will clash with Andre's unrolling patches. His patches have priority so this patch should queue behind them. The x86 and rs6000 parts fully convert to a self-contained class. The equivalent aarch64 changes are more complex, so this patch just does the bare minimum. A later patch will rework the aarch64 bits. gcc/ * target.def (targetm.vectorize.init_cost): Replace with... (targetm.vectorize.create_costs): ...this. (targetm.vectorize.add_stmt_cost): Delete. (targetm.vectorize.finish_cost): Likewise. (targetm.vectorize.destroy_cost_data): Likewise. * doc/tm.texi.in (TARGET_VECTORIZE_INIT_COST): Replace with... (TARGET_VECTORIZE_CREATE_COSTS): ...this. (TARGET_VECTORIZE_ADD_STMT_COST): Delete. (TARGET_VECTORIZE_FINISH_COST): Likewise. (TARGET_VECTORIZE_DESTROY_COST_DATA): Likewise. * doc/tm.texi: Regenerate. * tree-vectorizer.h (vec_info::vec_info): Remove target_cost_data parameter. (vec_info::target_cost_data): Change from a void * to a vector_costs *. (vector_costs): New class. (init_cost): Take a vec_info and return a vector_costs. (dump_stmt_cost): Remove data parameter. (add_stmt_cost): Replace vinfo and data parameters with a vector_costs. (add_stmt_costs): Likewise. (finish_cost): Replace data parameter with a vector_costs. (destroy_cost_data): Delete. * tree-vectorizer.c (dump_stmt_cost): Remove data argument and don't print it. (vec_info::vec_info): Remove the target_cost_data parameter and initialize the member variable to null instead. (vec_info::~vec_info): Delete target_cost_data instead of calling destroy_cost_data. (vector_costs::add_stmt_cost): New function. (vector_costs::finish_cost): Likewise. (vector_costs::record_stmt_cost): Likewise. (vector_costs::adjust_cost_for_freq): Likewise. * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Update call to vec_info::vec_info. (vect_compute_single_scalar_iteration_cost): Update after above changes to costing interface. (vect_analyze_loop_operations): Likewise. (vect_estimate_min_profitable_iters): Likewise. (vect_analyze_loop_2): Initialize LOOP_VINFO_TARGET_COST_DATA at the start_over point, where it needs to be recreated after trying without slp. Update retry code accordingly. * tree-vect-slp.c (_bb_vec_info::_bb_vec_info): Update call to vec_info::vec_info. (vect_slp_analyze_operation): Update after above changes to costing interface. (vect_bb_vectorization_profitable_p): Likewise. * targhooks.h (default_init_cost): Replace with... (default_vectorize_create_costs): ...this. (default_add_stmt_cost): Delete. (default_finish_cost, default_destroy_cost_data): Likewise. * targhooks.c (default_init_cost): Replace with... (default_vectorize_create_costs): ...this. (default_add_stmt_cost): Delete, moving logic to vector_costs instead. (default_finish_cost, default_destroy_cost_data): Delete. * config/aarch64/aarch64.c (aarch64_vector_costs): Inherit from vector_costs. Add a constructor. (aarch64_init_cost): Replace with... (aarch64_vectorize_create_costs): ...this. (aarch64_add_stmt_cost): Replace with... (aarch64_vector_costs::add_stmt_cost): ...this. Use record_stmt_cost to adjust the cost for inner loops. (aarch64_finish_cost): Replace with... (aarch64_vector_costs::finish_cost): ...this. (aarch64_destroy_cost_data): Delete. (TARGET_VECTORIZE_INIT_COST): Replace with... (TARGET_VECTORIZE_CREATE_COSTS): ...this. (TARGET_VECTORIZE_ADD_STMT_COST): Delete. (TARGET_VECTORIZE_FINISH_COST): Likewise. (TARGET_VECTORIZE_DESTROY_COST_DATA): Likewise. * config/i386/i386.c (ix86_vector_costs): New structure. (ix86_init_cost): Replace with... (ix86_vectorize_create_costs): ...this. (ix86_add_stmt_cost): Replace with... (ix86_vector_costs::add_stmt_cost): ...this. Use adjust_cost_for_freq to adjust the cost for inner loops. (ix86_finish_cost, ix86_destroy_cost_data): Delete. (TARGET_VECTORIZE_INIT_COST): Replace with... (TARGET_VECTORIZE_CREATE_COSTS): ...this. (TARGET_VECTORIZE_ADD_STMT_COST): Delete. (TARGET_VECTORIZE_FINISH_COST): Likewise. (TARGET_VECTORIZE_DESTROY_COST_DATA): Likewise. * config/rs6000/rs6000.c (TARGET_VECTORIZE_INIT_COST): Replace with... (TARGET_VECTORIZE_CREATE_COSTS): ...this. (TARGET_VECTORIZE_ADD_STMT_COST): Delete. (TARGET_VECTORIZE_FINISH_COST): Likewise. (TARGET_VECTORIZE_DESTROY_COST_DATA): Likewise. (rs6000_cost_data): Inherit from vector_costs. Add a constructor. Drop loop_info, cost and costing_for_scalar in favor of the corresponding vector_costs member variables. Add "m_" to the names of the remaining member variables and initialize them. (rs6000_density_test): Replace with... (rs6000_cost_data::density_test): ...this. (rs6000_init_cost): Replace with... (rs6000_vectorize_create_costs): ...this. (rs6000_update_target_cost_per_stmt): Replace with... (rs6000_cost_data::update_target_cost_per_stmt): ...this. (rs6000_add_stmt_cost): Replace with... (rs6000_cost_data::add_stmt_cost): ...this. Use adjust_cost_for_freq to adjust the cost for inner loops. (rs6000_adjust_vect_cost_per_loop): Replace with... (rs6000_cost_data::adjust_vect_cost_per_loop): ...this. (rs6000_finish_cost): Replace with... (rs6000_cost_data::finish_cost): ...this. Group loop code into a single if statement and pass the loop_vinfo down to subroutines. (rs6000_destroy_cost_data): Delete.
Diffstat (limited to 'gcc/tree-vectorizer.h')
-rw-r--r--gcc/tree-vectorizer.h141
1 files changed, 116 insertions, 25 deletions
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 73347ce..76e22ee 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -368,7 +368,7 @@ public:
typedef hash_set<int_hash<machine_mode, E_VOIDmode, E_BLKmode> > mode_set;
enum vec_kind { bb, loop };
- vec_info (vec_kind, void *, vec_info_shared *);
+ vec_info (vec_kind, vec_info_shared *);
~vec_info ();
stmt_vec_info add_stmt (gimple *);
@@ -406,7 +406,7 @@ public:
auto_vec<stmt_vec_info> grouped_stores;
/* Cost data used by the target cost model. */
- void *target_cost_data;
+ class vector_costs *target_cost_data;
/* The set of vector modes used in the vectorized region. */
mode_set used_vector_modes;
@@ -1395,6 +1395,103 @@ struct gather_scatter_info {
#define PURE_SLP_STMT(S) ((S)->slp_type == pure_slp)
#define STMT_SLP_TYPE(S) (S)->slp_type
+/* Contains the scalar or vector costs for a vec_info. */
+class vector_costs
+{
+public:
+ vector_costs (vec_info *, bool);
+ virtual ~vector_costs () {}
+
+ /* Update the costs in response to adding COUNT copies of a statement.
+
+ - WHERE specifies whether the cost occurs in the loop prologue,
+ the loop body, or the loop epilogue.
+ - KIND is the kind of statement, which is always meaningful.
+ - STMT_INFO, if nonnull, describes the statement that will be
+ vectorized.
+ - VECTYPE, if nonnull, is the vector type that the vectorized
+ statement will operate on. Note that this should be used in
+ preference to STMT_VINFO_VECTYPE (STMT_INFO) since the latter
+ is not correct for SLP.
+ - for unaligned_load and unaligned_store statements, MISALIGN is
+ the byte misalignment of the load or store relative to the target's
+ preferred alignment for VECTYPE, or DR_MISALIGNMENT_UNKNOWN
+ if the misalignment is not known.
+
+ Return the calculated cost as well as recording it. The return
+ value is used for dumping purposes. */
+ virtual unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind,
+ stmt_vec_info stmt_info, tree vectype,
+ int misalign,
+ vect_cost_model_location where);
+
+ /* Finish calculating the cost of the code. The results can be
+ read back using the functions below. */
+ virtual void finish_cost ();
+
+ unsigned int prologue_cost () const;
+ unsigned int body_cost () const;
+ unsigned int epilogue_cost () const;
+
+protected:
+ unsigned int record_stmt_cost (stmt_vec_info, vect_cost_model_location,
+ unsigned int);
+ unsigned int adjust_cost_for_freq (stmt_vec_info, vect_cost_model_location,
+ unsigned int);
+
+ /* The region of code that we're considering vectorizing. */
+ vec_info *m_vinfo;
+
+ /* True if we're costing the scalar code, false if we're costing
+ the vector code. */
+ bool m_costing_for_scalar;
+
+ /* The costs of the three regions, indexed by vect_cost_model_location. */
+ unsigned int m_costs[3];
+
+ /* True if finish_cost has been called. */
+ bool m_finished;
+};
+
+/* Create costs for VINFO. COSTING_FOR_SCALAR is true if the costs
+ are for scalar code, false if they are for vector code. */
+
+inline
+vector_costs::vector_costs (vec_info *vinfo, bool costing_for_scalar)
+ : m_vinfo (vinfo),
+ m_costing_for_scalar (costing_for_scalar),
+ m_costs (),
+ m_finished (false)
+{
+}
+
+/* Return the cost of the prologue code (in abstract units). */
+
+inline unsigned int
+vector_costs::prologue_cost () const
+{
+ gcc_checking_assert (m_finished);
+ return m_costs[vect_prologue];
+}
+
+/* Return the cost of the body code (in abstract units). */
+
+inline unsigned int
+vector_costs::body_cost () const
+{
+ gcc_checking_assert (m_finished);
+ return m_costs[vect_body];
+}
+
+/* Return the cost of the epilogue code (in abstract units). */
+
+inline unsigned int
+vector_costs::epilogue_cost () const
+{
+ gcc_checking_assert (m_finished);
+ return m_costs[vect_epilogue];
+}
+
#define VECT_MAX_COST 1000
/* The maximum number of intermediate steps required in multi-step type
@@ -1531,29 +1628,28 @@ int vect_get_stmt_cost (enum vect_cost_for_stmt type_of_cost)
/* Alias targetm.vectorize.init_cost. */
-static inline void *
-init_cost (class loop *loop_info, bool costing_for_scalar)
+static inline vector_costs *
+init_cost (vec_info *vinfo, bool costing_for_scalar)
{
- return targetm.vectorize.init_cost (loop_info, costing_for_scalar);
+ return targetm.vectorize.create_costs (vinfo, costing_for_scalar);
}
-extern void dump_stmt_cost (FILE *, void *, int, enum vect_cost_for_stmt,
+extern void dump_stmt_cost (FILE *, int, enum vect_cost_for_stmt,
stmt_vec_info, tree, int, unsigned,
enum vect_cost_model_location);
/* Alias targetm.vectorize.add_stmt_cost. */
static inline unsigned
-add_stmt_cost (vec_info *vinfo, void *data, int count,
+add_stmt_cost (vector_costs *costs, int count,
enum vect_cost_for_stmt kind,
stmt_vec_info stmt_info, tree vectype, int misalign,
enum vect_cost_model_location where)
{
- unsigned cost = targetm.vectorize.add_stmt_cost (vinfo, data, count, kind,
- stmt_info, vectype,
- misalign, where);
+ unsigned cost = costs->add_stmt_cost (count, kind, stmt_info, vectype,
+ misalign, where);
if (dump_file && (dump_flags & TDF_DETAILS))
- dump_stmt_cost (dump_file, data, count, kind, stmt_info, vectype, misalign,
+ dump_stmt_cost (dump_file, count, kind, stmt_info, vectype, misalign,
cost, where);
return cost;
}
@@ -1561,36 +1657,31 @@ add_stmt_cost (vec_info *vinfo, void *data, int count,
/* Alias targetm.vectorize.add_stmt_cost. */
static inline unsigned
-add_stmt_cost (vec_info *vinfo, void *data, stmt_info_for_cost *i)
+add_stmt_cost (vector_costs *costs, stmt_info_for_cost *i)
{
- return add_stmt_cost (vinfo, data, i->count, i->kind, i->stmt_info,
+ return add_stmt_cost (costs, i->count, i->kind, i->stmt_info,
i->vectype, i->misalign, i->where);
}
/* Alias targetm.vectorize.finish_cost. */
static inline void
-finish_cost (void *data, unsigned *prologue_cost,
+finish_cost (vector_costs *costs, unsigned *prologue_cost,
unsigned *body_cost, unsigned *epilogue_cost)
{
- targetm.vectorize.finish_cost (data, prologue_cost, body_cost, epilogue_cost);
-}
-
-/* Alias targetm.vectorize.destroy_cost_data. */
-
-static inline void
-destroy_cost_data (void *data)
-{
- targetm.vectorize.destroy_cost_data (data);
+ costs->finish_cost ();
+ *prologue_cost = costs->prologue_cost ();
+ *body_cost = costs->body_cost ();
+ *epilogue_cost = costs->epilogue_cost ();
}
inline void
-add_stmt_costs (vec_info *vinfo, void *data, stmt_vector_for_cost *cost_vec)
+add_stmt_costs (vector_costs *costs, stmt_vector_for_cost *cost_vec)
{
stmt_info_for_cost *cost;
unsigned i;
FOR_EACH_VEC_ELT (*cost_vec, i, cost)
- add_stmt_cost (vinfo, data, cost->count, cost->kind, cost->stmt_info,
+ add_stmt_cost (costs, cost->count, cost->kind, cost->stmt_info,
cost->vectype, cost->misalign, cost->where);
}