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.
[ 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. | #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;

>

Patch hide | download patch | download mbox

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;