+2017-08-04 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vectorizer.h (vec_info): Add a constructor and destructor.
+ Add an explicit name for the enum. Use auto_vec for slp_instances
+ and grouped_stores.
+ (_loop_vec_info): Add a constructor and destructor. Use auto_vec
+ for all vectors.
+ (_bb_vec_info): Add a constructor and destructor.
+ (vinfo_for_stmt): Return NULL for uids of -1 as well.
+ (destroy_loop_vec_info): Delete.
+ (vect_destroy_datarefs): Likewise.
+ * tree-vectorizer.c (vect_destroy_datarefs): Delete.
+ (vec_info::vec_info): New function.
+ (vec_info::~vec_info): Likewise.
+ (vectorize_loops): Use delete instead of destroy_loop_vec_info.
+ * tree-parloops.c (gather_scalar_reductions): Use delete instead of
+ destroy_loop_vec_info.
+ * tree-vect-loop.c (new_loop_vec_info): Replace with...
+ (_loop_vec_info::_loop_vec_info): ...this.
+ (destroy_loop_vec_info): Replace with...
+ (_loop_vec_info::~_loop_vec_info): ...this. Unconditionally delete
+ the stmt_vec_infos. Leave handling of vec_info information to its
+ destructor. Remove explicit vector releases.
+ (vect_analyze_loop_form): Use new instead of new_loop_vec_info.
+ (vect_analyze_loop): Use delete instead of destroy_loop_vec_info.
+ * tree-vect-slp.c (new_bb_vec_info): Replace with...
+ (_bb_vec_info::_bb_vec_info): ...this. Don't reserve space in
+ BB_VINFO_GROUPED_STORES or BB_VINFO_SLP_INSTANCES.
+ (destroy_bb_vec_info): Replace with...
+ (_bb_vec_info::~_bb_vec_info): ...this. Leave handling of vec_info
+ information to its destructor.
+ (vect_slp_analyze_bb_1): Use new and delete instead of
+ new_bb_vec_info and destroy_bb_vec_info.
+ (vect_slp_bb): Replace 2 calls to destroy_bb_vec_info with a
+ single delete.
+
2017-08-04 Richard Sandiford <richard.sandiford@linaro.org>
* tree-data-ref.h (subscript): Add access_fn field.
build_new_reduction (reduction_list, reduc_stmt, phi);
}
- destroy_loop_vec_info (simple_loop_info, true);
+ delete simple_loop_info;
if (!double_reduc_phis.is_empty ())
{
build_new_reduction (reduction_list, double_reduc_stmts[i], phi);
}
- destroy_loop_vec_info (simple_loop_info, true);
+ delete simple_loop_info;
}
}
}
-/* Function new_loop_vec_info.
-
- Create and initialize a new loop_vec_info struct for LOOP, as well as
- stmt_vec_info structs for all the stmts in LOOP. */
-
-static loop_vec_info
-new_loop_vec_info (struct loop *loop)
+/* Create and initialize a new loop_vec_info struct for LOOP_IN, as well as
+ stmt_vec_info structs for all the stmts in LOOP_IN. */
+
+_loop_vec_info::_loop_vec_info (struct loop *loop_in)
+ : vec_info (vec_info::loop, init_cost (loop_in)),
+ loop (loop_in),
+ bbs (XCNEWVEC (basic_block, loop->num_nodes)),
+ num_itersm1 (NULL_TREE),
+ num_iters (NULL_TREE),
+ num_iters_unchanged (NULL_TREE),
+ num_iters_assumptions (NULL_TREE),
+ th (0),
+ vectorization_factor (0),
+ unaligned_dr (NULL),
+ peeling_for_alignment (0),
+ ptr_mask (0),
+ slp_unrolling_factor (1),
+ single_scalar_iteration_cost (0),
+ vectorizable (false),
+ peeling_for_gaps (false),
+ peeling_for_niter (false),
+ operands_swapped (false),
+ no_data_dependencies (false),
+ has_mask_store (false),
+ scalar_loop (NULL),
+ orig_loop_info (NULL)
{
- loop_vec_info res;
- basic_block *bbs;
- gimple_stmt_iterator si;
- unsigned int i, nbbs;
-
- res = (loop_vec_info) xcalloc (1, sizeof (struct _loop_vec_info));
- res->kind = vec_info::loop;
- LOOP_VINFO_LOOP (res) = loop;
-
- bbs = get_loop_body (loop);
-
/* Create/Update stmt_info for all stmts in the loop. */
- for (i = 0; i < loop->num_nodes; i++)
+ basic_block *body = get_loop_body (loop);
+ for (unsigned int i = 0; i < loop->num_nodes; i++)
{
- basic_block bb = bbs[i];
+ basic_block bb = body[i];
+ gimple_stmt_iterator si;
for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple *phi = gsi_stmt (si);
gimple_set_uid (phi, 0);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res));
+ set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, this));
}
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res));
+ set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, this));
}
}
+ free (body);
/* CHECKME: We want to visit all BBs before their successors (except for
latch blocks, for which this assertion wouldn't hold). In the simple
case of the loop forms we allow, a dfs order of the BBs would the same
as reversed postorder traversal, so we are safe. */
- free (bbs);
- bbs = XCNEWVEC (basic_block, loop->num_nodes);
- nbbs = dfs_enumerate_from (loop->header, 0, bb_in_loop_p,
- bbs, loop->num_nodes, loop);
- gcc_assert (nbbs == loop->num_nodes);
-
- LOOP_VINFO_BBS (res) = bbs;
- LOOP_VINFO_NITERSM1 (res) = NULL;
- LOOP_VINFO_NITERS (res) = NULL;
- LOOP_VINFO_NITERS_UNCHANGED (res) = NULL;
- LOOP_VINFO_NITERS_ASSUMPTIONS (res) = NULL;
- LOOP_VINFO_COST_MODEL_THRESHOLD (res) = 0;
- LOOP_VINFO_VECTORIZABLE_P (res) = 0;
- LOOP_VINFO_PEELING_FOR_ALIGNMENT (res) = 0;
- LOOP_VINFO_VECT_FACTOR (res) = 0;
- LOOP_VINFO_LOOP_NEST (res) = vNULL;
- LOOP_VINFO_DATAREFS (res) = vNULL;
- LOOP_VINFO_DDRS (res) = vNULL;
- LOOP_VINFO_UNALIGNED_DR (res) = NULL;
- LOOP_VINFO_MAY_MISALIGN_STMTS (res) = vNULL;
- LOOP_VINFO_MAY_ALIAS_DDRS (res) = vNULL;
- LOOP_VINFO_GROUPED_STORES (res) = vNULL;
- LOOP_VINFO_REDUCTIONS (res) = vNULL;
- LOOP_VINFO_REDUCTION_CHAINS (res) = vNULL;
- LOOP_VINFO_SLP_INSTANCES (res) = vNULL;
- LOOP_VINFO_SLP_UNROLLING_FACTOR (res) = 1;
- LOOP_VINFO_TARGET_COST_DATA (res) = init_cost (loop);
- LOOP_VINFO_PEELING_FOR_GAPS (res) = false;
- LOOP_VINFO_PEELING_FOR_NITER (res) = false;
- LOOP_VINFO_OPERANDS_SWAPPED (res) = false;
- LOOP_VINFO_ORIG_LOOP_INFO (res) = NULL;
-
- return res;
+ unsigned int nbbs = dfs_enumerate_from (loop->header, 0, bb_in_loop_p,
+ bbs, loop->num_nodes, loop);
+ gcc_assert (nbbs == loop->num_nodes);
}
-/* Function destroy_loop_vec_info.
-
- Free LOOP_VINFO struct, as well as all the stmt_vec_info structs of all the
- stmts in the loop. */
+/* Free all memory used by the _loop_vec_info, as well as all the
+ stmt_vec_info structs of all the stmts in the loop. */
-void
-destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
+_loop_vec_info::~_loop_vec_info ()
{
- struct loop *loop;
- basic_block *bbs;
int nbbs;
gimple_stmt_iterator si;
int j;
- vec<slp_instance> slp_instances;
- slp_instance instance;
- bool swapped;
-
- if (!loop_vinfo)
- return;
-
- loop = LOOP_VINFO_LOOP (loop_vinfo);
-
- bbs = LOOP_VINFO_BBS (loop_vinfo);
- nbbs = clean_stmts ? loop->num_nodes : 0;
- swapped = LOOP_VINFO_OPERANDS_SWAPPED (loop_vinfo);
+ nbbs = loop->num_nodes;
for (j = 0; j < nbbs; j++)
{
basic_block bb = bbs[j];
/* We may have broken canonical form by moving a constant
into RHS1 of a commutative op. Fix such occurrences. */
- if (swapped && is_gimple_assign (stmt))
+ if (operands_swapped && is_gimple_assign (stmt))
{
enum tree_code code = gimple_assign_rhs_code (stmt);
}
}
- free (LOOP_VINFO_BBS (loop_vinfo));
- vect_destroy_datarefs (loop_vinfo);
- free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo));
- LOOP_VINFO_LOOP_NEST (loop_vinfo).release ();
- LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).release ();
- LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo).release ();
- LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo).release ();
- slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
- FOR_EACH_VEC_ELT (slp_instances, j, instance)
- vect_free_slp_instance (instance);
-
- LOOP_VINFO_SLP_INSTANCES (loop_vinfo).release ();
- LOOP_VINFO_GROUPED_STORES (loop_vinfo).release ();
- LOOP_VINFO_REDUCTIONS (loop_vinfo).release ();
- LOOP_VINFO_REDUCTION_CHAINS (loop_vinfo).release ();
-
- destroy_cost_data (LOOP_VINFO_TARGET_COST_DATA (loop_vinfo));
- loop_vinfo->scalar_cost_vec.release ();
-
- LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo).release ();
+ free (bbs);
- free (loop_vinfo);
loop->aux = NULL;
}
&number_of_iterations, &inner_loop_cond))
return NULL;
- loop_vec_info loop_vinfo = new_loop_vec_info (loop);
+ loop_vec_info loop_vinfo = new _loop_vec_info (loop);
LOOP_VINFO_NITERSM1 (loop_vinfo) = number_of_iterationsm1;
LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
LOOP_VINFO_NITERS_UNCHANGED (loop_vinfo) = number_of_iterations;
return loop_vinfo;
}
- destroy_loop_vec_info (loop_vinfo, true);
+ delete loop_vinfo;
vector_sizes &= ~current_vector_size;
if (fatal
}
-/* Create and initialize a new bb_vec_info struct for BB, as well as
- stmt_vec_info structs for all the stmts in it. */
-
-static bb_vec_info
-new_bb_vec_info (gimple_stmt_iterator region_begin,
- gimple_stmt_iterator region_end)
+/* Initialize a bb_vec_info struct for the statements between
+ REGION_BEGIN_IN (inclusive) and REGION_END_IN (exclusive). */
+
+_bb_vec_info::_bb_vec_info (gimple_stmt_iterator region_begin_in,
+ gimple_stmt_iterator region_end_in)
+ : vec_info (vec_info::bb, init_cost (NULL)),
+ bb (gsi_bb (region_begin_in)),
+ region_begin (region_begin_in),
+ region_end (region_end_in)
{
- basic_block bb = gsi_bb (region_begin);
- bb_vec_info res = NULL;
gimple_stmt_iterator gsi;
- res = (bb_vec_info) xcalloc (1, sizeof (struct _bb_vec_info));
- res->kind = vec_info::bb;
- BB_VINFO_BB (res) = bb;
- res->region_begin = region_begin;
- res->region_end = region_end;
-
for (gsi = region_begin; gsi_stmt (gsi) != gsi_stmt (region_end);
gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res));
+ set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, this));
}
- BB_VINFO_GROUPED_STORES (res).create (10);
- BB_VINFO_SLP_INSTANCES (res).create (2);
- BB_VINFO_TARGET_COST_DATA (res) = init_cost (NULL);
-
- bb->aux = res;
- return res;
+ bb->aux = this;
}
/* Free BB_VINFO struct, as well as all the stmt_vec_info structs of all the
stmts in the basic block. */
-static void
-destroy_bb_vec_info (bb_vec_info bb_vinfo)
+_bb_vec_info::~_bb_vec_info ()
{
- slp_instance instance;
- unsigned i;
-
- if (!bb_vinfo)
- return;
-
- vect_destroy_datarefs (bb_vinfo);
- free_dependence_relations (BB_VINFO_DDRS (bb_vinfo));
- BB_VINFO_GROUPED_STORES (bb_vinfo).release ();
- FOR_EACH_VEC_ELT (BB_VINFO_SLP_INSTANCES (bb_vinfo), i, instance)
- vect_free_slp_instance (instance);
- BB_VINFO_SLP_INSTANCES (bb_vinfo).release ();
- destroy_cost_data (BB_VINFO_TARGET_COST_DATA (bb_vinfo));
-
- for (gimple_stmt_iterator si = bb_vinfo->region_begin;
- gsi_stmt (si) != gsi_stmt (bb_vinfo->region_end); gsi_next (&si))
+ for (gimple_stmt_iterator si = region_begin;
+ gsi_stmt (si) != gsi_stmt (region_end); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
gimple_set_uid (stmt, -1);
}
- BB_VINFO_BB (bb_vinfo)->aux = NULL;
- free (bb_vinfo);
+ bb->aux = NULL;
}
return NULL;
}
- bb_vinfo = new_bb_vec_info (region_begin, region_end);
+ bb_vinfo = new _bb_vec_info (region_begin, region_end);
if (!bb_vinfo)
return NULL;
"not vectorized: unhandled data-ref in basic "
"block.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
"not vectorized: not enough data-refs in "
"basic block.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
"not vectorized: unhandled data access in "
"basic block.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
"not vectorized: no grouped stores in "
"basic block.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
"in basic block.\n");
}
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
}
if (! BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
{
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: bad operation in basic block.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
"not vectorized: vectorization is not "
"profitable.\n");
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
return NULL;
}
dump_printf_loc (MSG_NOTE, vect_location,
"basic block part vectorized\n");
- destroy_bb_vec_info (bb_vinfo);
-
vectorized = true;
}
- else
- destroy_bb_vec_info (bb_vinfo);
+ delete bb_vinfo;
any_vectorized |= vectorized;
delete simd_array_to_simduid_htab;
}
\f
-/* A helper function to free data refs. */
+/* Initialize the vec_info with kind KIND_IN and target cost data
+ TARGET_COST_DATA_IN. */
+
+vec_info::vec_info (vec_info::vec_kind kind_in, void *target_cost_data_in)
+ : kind (kind_in),
+ datarefs (vNULL),
+ ddrs (vNULL),
+ target_cost_data (target_cost_data_in)
+{
+}
-void
-vect_destroy_datarefs (vec_info *vinfo)
+vec_info::~vec_info ()
{
+ slp_instance instance;
struct data_reference *dr;
unsigned int i;
- FOR_EACH_VEC_ELT (vinfo->datarefs, i, dr)
+ FOR_EACH_VEC_ELT (datarefs, i, dr)
if (dr->aux)
{
free (dr->aux);
dr->aux = NULL;
}
- free_data_refs (vinfo->datarefs);
+ FOR_EACH_VEC_ELT (slp_instances, i, instance)
+ vect_free_slp_instance (instance);
+
+ free_data_refs (datarefs);
+ free_dependence_relations (ddrs);
+ destroy_cost_data (target_cost_data);
}
/* A helper function to free scev and LOOP niter information, as well as
has_mask_store = false;
if (loop_vinfo)
has_mask_store = LOOP_VINFO_HAS_MASK_STORE (loop_vinfo);
- destroy_loop_vec_info (loop_vinfo, true);
+ delete loop_vinfo;
if (has_mask_store)
optimize_mask_stores (loop);
loop->aux = NULL;
/* Vectorizer state common between loop and basic-block vectorization. */
struct vec_info {
- enum { bb, loop } kind;
+ enum vec_kind { bb, loop };
+
+ vec_info (vec_kind, void *);
+ ~vec_info ();
+
+ /* The type of vectorization. */
+ vec_kind kind;
/* All SLP instances. */
- vec<slp_instance> slp_instances;
+ auto_vec<slp_instance> slp_instances;
- /* All data references. */
+ /* All data references. Freed by free_data_refs, so not an auto_vec. */
vec<data_reference_p> datarefs;
- /* All data dependences. */
+ /* All data dependences. Freed by free_dependence_relations, so not
+ an auto_vec. */
vec<ddr_p> ddrs;
/* All interleaving chains of stores, represented by the first
stmt in the chain. */
- vec<gimple *> grouped_stores;
+ auto_vec<gimple *> grouped_stores;
/* Cost data used by the target cost model. */
void *target_cost_data;
/* Info on vectorized loops. */
/*-----------------------------------------------------------------*/
typedef struct _loop_vec_info : public vec_info {
+ _loop_vec_info (struct loop *);
+ ~_loop_vec_info ();
/* The loop to which this info struct refers to. */
struct loop *loop;
int ptr_mask;
/* The loop nest in which the data dependences are computed. */
- vec<loop_p> loop_nest;
+ auto_vec<loop_p> loop_nest;
/* Data Dependence Relations defining address ranges that are candidates
for a run-time aliasing check. */
- vec<ddr_p> may_alias_ddrs;
+ auto_vec<ddr_p> may_alias_ddrs;
/* Data Dependence Relations defining address ranges together with segment
lengths from which the run-time aliasing check is built. */
- vec<dr_with_seg_len_pair_t> comp_alias_ddrs;
+ auto_vec<dr_with_seg_len_pair_t> comp_alias_ddrs;
/* Check that the addresses of each pair of objects is unequal. */
- vec<vec_object_pair> check_unequal_addrs;
+ auto_vec<vec_object_pair> check_unequal_addrs;
/* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */
- vec<gimple *> may_misalign_stmts;
+ auto_vec<gimple *> may_misalign_stmts;
/* Reduction cycles detected in the loop. Used in loop-aware SLP. */
- vec<gimple *> reductions;
+ auto_vec<gimple *> reductions;
/* All reduction chains in the loop, represented by the first
stmt in the chain. */
- vec<gimple *> reduction_chains;
+ auto_vec<gimple *> reduction_chains;
/* Cost vector for a single scalar iteration. */
- vec<stmt_info_for_cost> scalar_cost_vec;
+ auto_vec<stmt_info_for_cost> scalar_cost_vec;
/* The unrolling factor needed to SLP the loop. In case of that pure SLP is
applied to the loop, i.e., no unrolling is needed, this is 1. */
typedef struct _bb_vec_info : public vec_info
{
+ _bb_vec_info (gimple_stmt_iterator, gimple_stmt_iterator);
+ ~_bb_vec_info ();
+
basic_block bb;
gimple_stmt_iterator region_begin;
gimple_stmt_iterator region_end;
static inline stmt_vec_info
vinfo_for_stmt (gimple *stmt)
{
- unsigned int uid = gimple_uid (stmt);
- if (uid == 0)
+ int uid = gimple_uid (stmt);
+ if (uid <= 0)
return NULL;
return stmt_vec_info_vec[uid - 1];
/* In tree-vect-loop.c. */
/* FORNOW: Used in tree-parloops.c. */
-extern void destroy_loop_vec_info (loop_vec_info, bool);
extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *,
bool *, bool);
/* Drive for loop analysis stage. */
/* In tree-vectorizer.c. */
unsigned vectorize_loops (void);
-void vect_destroy_datarefs (vec_info *);
bool vect_stmt_in_region_p (vec_info *, gimple *);
void vect_free_loop_info_assumptions (struct loop *);