diff mbox

C++-ify vec_info structures

Message ID 87r2x2rr3a.fsf@linaro.org
State New
Headers show

Commit Message

Richard Sandiford July 27, 2017, 12:39 p.m. UTC
[ Needed to unblock https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00198.html ]

This patch uses new, delete, constructors and desctructors to manage
vec_info.  This includes making ~vec_info free all the data shared
by bb_vec_info and loop_vec_info, whereas previously the code was
duplicated in destroy_bb_vec_info and destroy_loop_vec_info.  This
in turn meant changing the order of:

  FOR_EACH_VEC_ELT (slp_instances, i, instance)
    vect_free_slp_instance (instance);

and:

  gimple_set_uid (stmt, -1);

in destroy_bb_vec_info/~_bb_vec_info, so that now vect_free_slp_instance
could see a uid of -1 as well as 0.  The patch updates vinfo_for_stmt
so that it returns NULL for a uid of -1.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


2017-07-27  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* 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.

Comments

Richard Biener July 28, 2017, 7:16 a.m. UTC | #1
On Thu, Jul 27, 2017 at 2:39 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> [ Needed to unblock https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00198.html ]
>
> This patch uses new, delete, constructors and desctructors to manage
> vec_info.  This includes making ~vec_info free all the data shared
> by bb_vec_info and loop_vec_info, whereas previously the code was
> duplicated in destroy_bb_vec_info and destroy_loop_vec_info.  This
> in turn meant changing the order of:
>
>   FOR_EACH_VEC_ELT (slp_instances, i, instance)
>     vect_free_slp_instance (instance);
>
> and:
>
>   gimple_set_uid (stmt, -1);
>
> in destroy_bb_vec_info/~_bb_vec_info, so that now vect_free_slp_instance
> could see a uid of -1 as well as 0.  The patch updates vinfo_for_stmt
> so that it returns NULL for a uid of -1.

Yeah... details.  For the future I hope to move stmt_vec_info_vec into
vec_info somehow so we can have multiple vec_info in "analysis phase"
in flight to be able to compare cost of different vectorization choices
(rather than only vectorization vs. no vectorization).

So if you feel lucky... ;)  [if it gets too ugly wrt those instances sharing
gimple_uid changing stmt_vec_info_vec to a hash-map would be my
prefered fix, caching the last lookup as we're quite lazy with
repeating vinfo_for_stmt (...)]

> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Ok.  Thanks for doing all this.

Richard.

> Richard
>
>
> 2017-07-27  Richard Sandiford  <richard.sandiford@linaro.org>
>
> gcc/
>         * 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.
>
> Index: gcc/tree-vectorizer.h
> ===================================================================
> --- gcc/tree-vectorizer.h       2017-07-27 13:25:33.934530189 +0100
> +++ gcc/tree-vectorizer.h       2017-07-27 13:25:42.989783339 +0100
> @@ -155,20 +155,27 @@ typedef std::pair<tree, tree> vec_object
>
>  /* 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;
> @@ -198,6 +205,8 @@ is_a_helper <_bb_vec_info *>::test (vec_
>  /* 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;
> @@ -239,32 +248,32 @@ typedef struct _loop_vec_info : public v
>    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.  */
> @@ -399,6 +408,9 @@ nested_in_vect_loop_p (struct loop *loop
>
>  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;
> @@ -802,8 +814,8 @@ void free_stmt_vec_info_vec (void);
>  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];
> @@ -1177,7 +1189,6 @@ extern tree vect_create_addr_base_for_ve
>
>  /* 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.  */
> @@ -1226,7 +1237,6 @@ void vect_pattern_recog (vec_info *);
>
>  /* 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 *);
>
> Index: gcc/tree-vectorizer.c
> ===================================================================
> --- gcc/tree-vectorizer.c       2017-07-27 13:23:27.073925971 +0100
> +++ gcc/tree-vectorizer.c       2017-07-27 13:25:42.988783310 +0100
> @@ -354,22 +354,36 @@ note_simd_array_uses (hash_table<simd_ar
>    delete simd_array_to_simduid_htab;
>  }
>
> -/* A helper function to free data refs.  */
> +/* Initialize the vec_info with kind KIND_IN and target cost data
> +   TARGET_COST_DATA_IN.  */
>
> -void
> -vect_destroy_datarefs (vec_info *vinfo)
> +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)
>  {
> +}
> +
> +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
> @@ -830,7 +844,7 @@ vectorize_loops (void)
>        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;
> Index: gcc/tree-parloops.c
> ===================================================================
> --- gcc/tree-parloops.c 2017-07-27 13:23:27.073925971 +0100
> +++ gcc/tree-parloops.c 2017-07-27 13:25:42.987783282 +0100
> @@ -2561,7 +2561,7 @@ gather_scalar_reductions (loop_p loop, r
>
>        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 ())
>      {
> @@ -2597,7 +2597,7 @@ gather_scalar_reductions (loop_p loop, r
>
>               build_new_reduction (reduction_list, double_reduc_stmts[i], phi);
>             }
> -         destroy_loop_vec_info (simple_loop_info, true);
> +         delete simple_loop_info;
>         }
>      }
>
> Index: gcc/tree-vect-loop.c
> ===================================================================
> --- gcc/tree-vect-loop.c        2017-07-27 13:25:33.934530189 +0100
> +++ gcc/tree-vect-loop.c        2017-07-27 13:25:42.988783310 +0100
> @@ -1098,112 +1098,77 @@ bb_in_loop_p (const_basic_block bb, cons
>  }
>
>
> -/* Function new_loop_vec_info.
> +/* 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.  */
>
> -   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)
> +_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];
> @@ -1216,7 +1181,7 @@ destroy_loop_vec_info (loop_vec_info loo
>
>           /* 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);
>
> @@ -1256,28 +1221,8 @@ destroy_loop_vec_info (loop_vec_info loo
>          }
>      }
>
> -  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;
>  }
>
> @@ -1564,7 +1509,7 @@ vect_analyze_loop_form (struct loop *loo
>                                   &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;
> @@ -2412,7 +2357,7 @@ vect_analyze_loop (struct loop *loop, lo
>           return loop_vinfo;
>         }
>
> -      destroy_loop_vec_info (loop_vinfo, true);
> +      delete loop_vinfo;
>
>        vector_sizes &= ~current_vector_size;
>        if (fatal
> Index: gcc/tree-vect-slp.c
> ===================================================================
> --- gcc/tree-vect-slp.c 2017-07-27 13:23:27.073925971 +0100
> +++ gcc/tree-vect-slp.c 2017-07-27 13:25:42.988783310 +0100
> @@ -2362,62 +2362,37 @@ vect_detect_hybrid_slp (loop_vec_info lo
>  }
>
>
> -/* Create and initialize a new bb_vec_info struct for BB, as well as
> -   stmt_vec_info structs for all the stmts in it.  */
> +/* Initialize a bb_vec_info struct for the statements between
> +   REGION_BEGIN_IN (inclusive) and REGION_END_IN (exclusive).  */
>
> -static bb_vec_info
> -new_bb_vec_info (gimple_stmt_iterator region_begin,
> -                gimple_stmt_iterator region_end)
> +_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);
> @@ -2430,8 +2405,7 @@ destroy_bb_vec_info (bb_vec_info bb_vinf
>        gimple_set_uid (stmt, -1);
>      }
>
> -  BB_VINFO_BB (bb_vinfo)->aux = NULL;
> -  free (bb_vinfo);
> +  bb->aux = NULL;
>  }
>
>
> @@ -2713,7 +2687,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>        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;
>
> @@ -2728,7 +2702,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                          "not vectorized: unhandled data-ref in basic "
>                          "block.\n");
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2739,7 +2713,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                          "not vectorized: not enough data-refs in "
>                          "basic block.\n");
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2750,7 +2724,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                         "not vectorized: unhandled data access in "
>                         "basic block.\n");
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2764,7 +2738,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                          "not vectorized: no grouped stores in "
>                          "basic block.\n");
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2786,7 +2760,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                            "in basic block.\n");
>         }
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2816,7 +2790,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>      }
>    if (! BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
>      {
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2827,7 +2801,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>          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;
>      }
>
> @@ -2840,7 +2814,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
>                          "not vectorized: vectorization is not "
>                          "profitable.\n");
>
> -      destroy_bb_vec_info (bb_vinfo);
> +      delete bb_vinfo;
>        return NULL;
>      }
>
> @@ -2920,12 +2894,9 @@ vect_slp_bb (basic_block bb)
>             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;
>
diff mbox

Patch

Index: gcc/tree-vectorizer.h
===================================================================
--- gcc/tree-vectorizer.h	2017-07-27 13:25:33.934530189 +0100
+++ gcc/tree-vectorizer.h	2017-07-27 13:25:42.989783339 +0100
@@ -155,20 +155,27 @@  typedef std::pair<tree, tree> vec_object
 
 /* 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;
@@ -198,6 +205,8 @@  is_a_helper <_bb_vec_info *>::test (vec_
 /* 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;
@@ -239,32 +248,32 @@  typedef struct _loop_vec_info : public v
   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.  */
@@ -399,6 +408,9 @@  nested_in_vect_loop_p (struct loop *loop
 
 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;
@@ -802,8 +814,8 @@  void free_stmt_vec_info_vec (void);
 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];
@@ -1177,7 +1189,6 @@  extern tree vect_create_addr_base_for_ve
 
 /* 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.  */
@@ -1226,7 +1237,6 @@  void vect_pattern_recog (vec_info *);
 
 /* 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 *);
 
Index: gcc/tree-vectorizer.c
===================================================================
--- gcc/tree-vectorizer.c	2017-07-27 13:23:27.073925971 +0100
+++ gcc/tree-vectorizer.c	2017-07-27 13:25:42.988783310 +0100
@@ -354,22 +354,36 @@  note_simd_array_uses (hash_table<simd_ar
   delete simd_array_to_simduid_htab;
 }
 
-/* A helper function to free data refs.  */
+/* Initialize the vec_info with kind KIND_IN and target cost data
+   TARGET_COST_DATA_IN.  */
 
-void
-vect_destroy_datarefs (vec_info *vinfo)
+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)
 {
+}
+
+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
@@ -830,7 +844,7 @@  vectorize_loops (void)
       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;
Index: gcc/tree-parloops.c
===================================================================
--- gcc/tree-parloops.c	2017-07-27 13:23:27.073925971 +0100
+++ gcc/tree-parloops.c	2017-07-27 13:25:42.987783282 +0100
@@ -2561,7 +2561,7 @@  gather_scalar_reductions (loop_p loop, r
 
       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 ())
     {
@@ -2597,7 +2597,7 @@  gather_scalar_reductions (loop_p loop, r
 
 	      build_new_reduction (reduction_list, double_reduc_stmts[i], phi);
 	    }
-	  destroy_loop_vec_info (simple_loop_info, true);
+	  delete simple_loop_info;
 	}
     }
 
Index: gcc/tree-vect-loop.c
===================================================================
--- gcc/tree-vect-loop.c	2017-07-27 13:25:33.934530189 +0100
+++ gcc/tree-vect-loop.c	2017-07-27 13:25:42.988783310 +0100
@@ -1098,112 +1098,77 @@  bb_in_loop_p (const_basic_block bb, cons
 }
 
 
-/* Function new_loop_vec_info.
+/* 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.  */
 
-   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)
+_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];
@@ -1216,7 +1181,7 @@  destroy_loop_vec_info (loop_vec_info loo
 
 	  /* 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);
 
@@ -1256,28 +1221,8 @@  destroy_loop_vec_info (loop_vec_info loo
         }
     }
 
-  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;
 }
 
@@ -1564,7 +1509,7 @@  vect_analyze_loop_form (struct loop *loo
 				  &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;
@@ -2412,7 +2357,7 @@  vect_analyze_loop (struct loop *loop, lo
 	  return loop_vinfo;
 	}
 
-      destroy_loop_vec_info (loop_vinfo, true);
+      delete loop_vinfo;
 
       vector_sizes &= ~current_vector_size;
       if (fatal
Index: gcc/tree-vect-slp.c
===================================================================
--- gcc/tree-vect-slp.c	2017-07-27 13:23:27.073925971 +0100
+++ gcc/tree-vect-slp.c	2017-07-27 13:25:42.988783310 +0100
@@ -2362,62 +2362,37 @@  vect_detect_hybrid_slp (loop_vec_info lo
 }
 
 
-/* Create and initialize a new bb_vec_info struct for BB, as well as
-   stmt_vec_info structs for all the stmts in it.  */
+/* Initialize a bb_vec_info struct for the statements between
+   REGION_BEGIN_IN (inclusive) and REGION_END_IN (exclusive).  */
 
-static bb_vec_info
-new_bb_vec_info (gimple_stmt_iterator region_begin,
-		 gimple_stmt_iterator region_end)
+_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);
@@ -2430,8 +2405,7 @@  destroy_bb_vec_info (bb_vec_info bb_vinf
       gimple_set_uid (stmt, -1);
     }
 
-  BB_VINFO_BB (bb_vinfo)->aux = NULL;
-  free (bb_vinfo);
+  bb->aux = NULL;
 }
 
 
@@ -2713,7 +2687,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
       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;
 
@@ -2728,7 +2702,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			 "not vectorized: unhandled data-ref in basic "
 			 "block.\n");
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2739,7 +2713,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			 "not vectorized: not enough data-refs in "
 			 "basic block.\n");
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2750,7 +2724,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			"not vectorized: unhandled data access in "
 			"basic block.\n");
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2764,7 +2738,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			 "not vectorized: no grouped stores in "
 			 "basic block.\n");
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2786,7 +2760,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			   "in basic block.\n");
 	}
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2816,7 +2790,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
     }
   if (! BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
     {
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2827,7 +2801,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
         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;
     }
 
@@ -2840,7 +2814,7 @@  vect_slp_analyze_bb_1 (gimple_stmt_itera
 			 "not vectorized: vectorization is not "
 			 "profitable.\n");
 
-      destroy_bb_vec_info (bb_vinfo);
+      delete bb_vinfo;
       return NULL;
     }
 
@@ -2920,12 +2894,9 @@  vect_slp_bb (basic_block bb)
 	    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;