On Thu, Oct 10, 2013 at 8:07 PM, <tsaund...@mozilla.com> wrote: > From: Trevor Saunders <tsaund...@mozilla.com> > > Hi, > > This makes the implementation of stack vectors simpler and easier to use. > This > > works by making the size of the on stack storage a template argument, so the > size is embedded in the type. This allows you to implicitly convert a > stack_vec<T, N> to a vec<T, va_heap> *, and it will just work.
Any particular reason to not go with a vec<T, va_stack, N> partial specialization? Btw, one reason against N being a template parameter is code bloat (so hopefully the implementation dispatches to a single vec<T, va_stack> set of template instantiations - I didn't look too closely at the patch yet). Richard. > Because there's > no need to support stack vectors in unions we can make them be a more normal > c++ class with a constructor and destructor that are nontrivial. > > Trev > > 2013-10-08 Trevor Saunders <tsaund...@mozilla.com> > > ada/ > * gcc-interface/decl.c (components_to_record): Adjust. > > gcc/ > * df-scan.c (df_collection_rec): Adjust. > (copy_defs): New constant. > (copy_uses): Likewise. > (copy_eq_uses): Likewise. > (copy_mw): Likewise. > (copy_all): Likewise. > (df_insn_rescan): Adjust. > (df_notes_rescan): Likewise. > (df_swap_refs): Likewise. > (df_sort_and_compress_refs): Likewise. > (df_sort_and_compress_mws): Likewise. > (df_install_refs): Likewise. > (df_install_mws): Likewise. > (df_refs_add_to_chains): Add flags parameter controlling which vectors > are coppied. > (df_bb_refs_record): Adjust. > (df_record_entry_block_defs): Likewise. > (df_record_exit_block_defs): Likewise. > (df_refs_verify): Likewise. > (df_mws_verify): Likewise. > (df_insn_refs_verify): Likewise. > (df_bb_verify): Likewise. > * ipa-pure-const.c (finish_state): Remove. > (propagate): Adjust. > * tree-data-ref.c tree-ssa-alias.c tree-ssa-loop-ivcanon.c > tree-ssa-threadedge.c tree-vect-loop-manip.c tree-vect-slp.c > var-tracking.c > Adjust. > * vec.c (stack_vecs): Remove. > (register_stack_vec): Likewise. > (stack_vec_register_index): Likewise. > (unregister_stack_vec): Likewise. > * vec.h (struct va_stack): Remove. > (struct vec<T, A, vl_ptr>): Specialize as > struct vec<T, va_heap, vl_ptr> instead since va_heap is the only > allocation strategy compatable with the vl_ptr layout. > (struct vec<T, va_gc, vl_ptr>): Remove because it now gets an empty > specialization anyway. > (class stack_vec): New class. > (vec_stack_alloc): Remove. > (vec<T, va_heap, vl_ptr>::using_auto_storage): New method. > > diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c > index 456d7ab..0debdae 100644 > --- a/gcc/ada/gcc-interface/decl.c > +++ b/gcc/ada/gcc-interface/decl.c > @@ -6994,13 +6994,11 @@ components_to_record (tree gnu_record_type, Node_Id > gnat_component_list, > tree gnu_union_type, gnu_union_name; > tree this_first_free_pos, gnu_variant_list = NULL_TREE; > bool union_field_needs_strict_alignment = false; > - vec <vinfo_t, va_stack> variant_types; > + stack_vec <vinfo_t, 16> variant_types; > vinfo_t *gnu_variant; > unsigned int variants_align = 0; > unsigned int i; > > - vec_stack_alloc (vinfo_t, variant_types, 16); > - > if (TREE_CODE (gnu_name) == TYPE_DECL) > gnu_name = DECL_NAME (gnu_name); > > @@ -7196,9 +7194,6 @@ components_to_record (tree gnu_record_type, Node_Id > gnat_component_list, > gnu_variant_list = gnu_field; > } > > - /* We are done with the variants. */ > - variant_types.release (); > - > /* Only make the QUAL_UNION_TYPE if there are non-empty variants. */ > if (gnu_variant_list) > { > diff --git a/gcc/df-scan.c b/gcc/df-scan.c > index f2e8ab2..aace96d 100644 > --- a/gcc/df-scan.c > +++ b/gcc/df-scan.c > @@ -86,10 +86,10 @@ static HARD_REG_SET elim_reg_set; > > struct df_collection_rec > { > - vec<df_ref, va_stack> def_vec; > - vec<df_ref, va_stack> use_vec; > - vec<df_ref, va_stack> eq_use_vec; > - vec<df_mw_hardreg_ptr, va_stack> mw_vec; > + stack_vec<df_ref, 128> def_vec; > + stack_vec<df_ref, 32> use_vec; > + stack_vec<df_ref, 32> eq_use_vec; > + stack_vec<df_mw_hardreg_ptr, 32> mw_vec; > }; > > static df_ref df_null_ref_rec[1]; > @@ -131,7 +131,7 @@ static void df_ref_chain_delete_du_chain (df_ref *); > static void df_ref_chain_delete (df_ref *); > > static void df_refs_add_to_chains (struct df_collection_rec *, > - basic_block, rtx); > + basic_block, rtx, unsigned int); > > static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, > rtx, bool); > static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap); > @@ -153,6 +153,14 @@ static void df_insn_info_delete (unsigned int); > and epilogue to save and restore registers as needed. */ > > static bool regs_ever_live[FIRST_PSEUDO_REGISTER]; > + > +/* Flags used to tell df_refs_add_to_chains() which vectors it should copy. > */ > +static const unsigned int copy_defs = 0x1; > +static const unsigned int copy_uses = 0x2; > +static const unsigned int copy_eq_uses = 0x4; > +static const unsigned int copy_mw = 0x8; > +static const unsigned int copy_all = copy_defs | copy_uses | copy_eq_uses > +| copy_mw; > > > /*---------------------------------------------------------------------------- > SCANNING DATAFLOW PROBLEM > @@ -1268,11 +1276,6 @@ df_insn_rescan (rtx insn) > return false; > } > > - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); > - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); > - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); > - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); > - > bitmap_clear_bit (&df->insns_to_delete, uid); > bitmap_clear_bit (&df->insns_to_rescan, uid); > bitmap_clear_bit (&df->insns_to_notes_rescan, uid); > @@ -1306,15 +1309,10 @@ df_insn_rescan (rtx insn) > fprintf (dump_file, "scanning new insn with uid = %d.\n", uid); > } > > - df_refs_add_to_chains (&collection_rec, bb, insn); > + df_refs_add_to_chains (&collection_rec, bb, insn, copy_all); > if (!DEBUG_INSN_P (insn)) > df_set_bb_dirty (bb); > > - collection_rec.def_vec.release (); > - collection_rec.use_vec.release (); > - collection_rec.eq_use_vec.release (); > - collection_rec.mw_vec.release (); > - > return true; > } > > @@ -2221,10 +2219,6 @@ df_notes_rescan (rtx insn) > unsigned int num_deleted; > unsigned int mw_len; > > - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); > - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); > - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); > - > num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info); > df_ref_chain_delete (insn_info->eq_uses); > insn_info->eq_uses = NULL; > @@ -2287,11 +2281,7 @@ df_notes_rescan (rtx insn) > insn_info->mw_hardregs[mw_len] = NULL; > } > } > - /* Get rid of the mw_rec so that df_refs_add_to_chains will > - ignore it. */ > - collection_rec.mw_vec.release (); > - df_refs_add_to_chains (&collection_rec, bb, insn); > - collection_rec.eq_use_vec.release (); > + df_refs_add_to_chains (&collection_rec, bb, insn, copy_eq_uses); > } > else > df_insn_rescan (insn); > @@ -2391,7 +2381,7 @@ df_ref_compare (const void *r1, const void *r2) > } > > static void > -df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, int j) > +df_swap_refs (vec<df_ref, va_heap> *ref_vec, int i, int j) > { > df_ref tmp = (*ref_vec)[i]; > (*ref_vec)[i] = (*ref_vec)[j]; > @@ -2401,7 +2391,7 @@ df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, > int j) > /* Sort and compress a set of refs. */ > > static void > -df_sort_and_compress_refs (vec<df_ref, va_stack> *ref_vec) > +df_sort_and_compress_refs (vec<df_ref, va_heap> *ref_vec) > { > unsigned int count; > unsigned int i; > @@ -2510,7 +2500,7 @@ df_mw_compare (const void *m1, const void *m2) > /* Sort and compress a set of refs. */ > > static void > -df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_stack> *mw_vec) > +df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_heap> *mw_vec) > { > unsigned int count; > struct df_scan_problem_data *problem_data > @@ -2621,14 +2611,12 @@ df_install_ref (df_ref this_ref, > > static df_ref * > df_install_refs (basic_block bb, > - vec<df_ref, va_stack> old_vec, > + const vec<df_ref, va_heap> *old_vec, > struct df_reg_info **reg_info, > struct df_ref_info *ref_info, > bool is_notes) > { > - unsigned int count; > - > - count = old_vec.length (); > + unsigned int count = old_vec->length (); > if (count) > { > df_ref *new_vec = XNEWVEC (df_ref, count + 1); > @@ -2659,7 +2647,7 @@ df_install_refs (basic_block bb, > if (add_to_table && df->analyze_subset) > add_to_table = bitmap_bit_p (df->blocks_to_analyze, bb->index); > > - FOR_EACH_VEC_ELT (old_vec, ix, this_ref) > + FOR_EACH_VEC_ELT (*old_vec, ix, this_ref) > { > new_vec[ix] = this_ref; > df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)], > @@ -2678,16 +2666,14 @@ df_install_refs (basic_block bb, > insn. */ > > static struct df_mw_hardreg ** > -df_install_mws (vec<df_mw_hardreg_ptr, va_stack> old_vec) > +df_install_mws (const vec<df_mw_hardreg_ptr, va_heap> *old_vec) > { > - unsigned int count; > - > - count = old_vec.length (); > + unsigned int count = old_vec->length (); > if (count) > { > struct df_mw_hardreg **new_vec > = XNEWVEC (struct df_mw_hardreg*, count + 1); > - memcpy (new_vec, old_vec.address (), > + memcpy (new_vec, old_vec->address (), > sizeof (struct df_mw_hardreg*) * count); > new_vec[count] = NULL; > return new_vec; > @@ -2702,7 +2688,7 @@ df_install_mws (vec<df_mw_hardreg_ptr, va_stack> > old_vec) > > static void > df_refs_add_to_chains (struct df_collection_rec *collection_rec, > - basic_block bb, rtx insn) > + basic_block bb, rtx insn, unsigned int flags) > { > if (insn) > { > @@ -2710,35 +2696,35 @@ df_refs_add_to_chains (struct df_collection_rec > *collection_rec, > /* If there is a vector in the collection rec, add it to the > insn. A null rec is a signal that the caller will handle the > chain specially. */ > - if (collection_rec->def_vec.exists ()) > + if (flags & copy_defs) > { > df_scan_free_ref_vec (insn_rec->defs); > insn_rec->defs > - = df_install_refs (bb, collection_rec->def_vec, > + = df_install_refs (bb, &collection_rec->def_vec, > df->def_regs, > &df->def_info, false); > } > - if (collection_rec->use_vec.exists ()) > + if (flags & copy_uses) > { > df_scan_free_ref_vec (insn_rec->uses); > insn_rec->uses > - = df_install_refs (bb, collection_rec->use_vec, > + = df_install_refs (bb, &collection_rec->use_vec, > df->use_regs, > &df->use_info, false); > } > - if (collection_rec->eq_use_vec.exists ()) > + if (flags & copy_eq_uses) > { > df_scan_free_ref_vec (insn_rec->eq_uses); > insn_rec->eq_uses > - = df_install_refs (bb, collection_rec->eq_use_vec, > + = df_install_refs (bb, &collection_rec->eq_use_vec, > df->eq_use_regs, > &df->use_info, true); > } > - if (collection_rec->mw_vec.exists ()) > + if (flags & copy_mw) > { > df_scan_free_mws_vec (insn_rec->mw_hardregs); > insn_rec->mw_hardregs > - = df_install_mws (collection_rec->mw_vec); > + = df_install_mws (&collection_rec->mw_vec); > } > } > else > @@ -2747,12 +2733,12 @@ df_refs_add_to_chains (struct df_collection_rec > *collection_rec, > > df_scan_free_ref_vec (bb_info->artificial_defs); > bb_info->artificial_defs > - = df_install_refs (bb, collection_rec->def_vec, > + = df_install_refs (bb, &collection_rec->def_vec, > df->def_regs, > &df->def_info, false); > df_scan_free_ref_vec (bb_info->artificial_uses); > bb_info->artificial_uses > - = df_install_refs (bb, collection_rec->use_vec, > + = df_install_refs (bb, &collection_rec->use_vec, > df->use_regs, > &df->use_info, false); > } > @@ -3633,17 +3619,12 @@ df_bb_refs_record (int bb_index, bool scan_insns) > basic_block bb = BASIC_BLOCK (bb_index); > rtx insn; > int luid = 0; > - struct df_collection_rec collection_rec; > > if (!df) > return; > > + df_collection_rec collection_rec; > df_grow_bb_info (df_scan); > - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); > - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); > - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); > - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); > - > if (scan_insns) > /* Scan the block an insn at a time from beginning to end. */ > FOR_BB_INSNS (bb, insn) > @@ -3657,19 +3638,14 @@ df_bb_refs_record (int bb_index, bool scan_insns) > /* Record refs within INSN. */ > DF_INSN_INFO_LUID (insn_info) = luid++; > df_insn_refs_collect (&collection_rec, bb, DF_INSN_INFO_GET > (insn)); > - df_refs_add_to_chains (&collection_rec, bb, insn); > + df_refs_add_to_chains (&collection_rec, bb, insn, copy_all); > } > DF_INSN_INFO_LUID (insn_info) = luid; > } > > /* Other block level artificial refs */ > df_bb_refs_collect (&collection_rec, bb); > - df_refs_add_to_chains (&collection_rec, bb, NULL); > - > - collection_rec.def_vec.release (); > - collection_rec.use_vec.release (); > - collection_rec.eq_use_vec.release (); > - collection_rec.mw_vec.release (); > + df_refs_add_to_chains (&collection_rec, bb, NULL, copy_all); > > /* Now that the block has been processed, set the block as dirty so > LR and LIVE will get it processed. */ > @@ -3911,13 +3887,11 @@ static void > df_record_entry_block_defs (bitmap entry_block_defs) > { > struct df_collection_rec collection_rec; > - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); > - vec_stack_alloc (df_ref, collection_rec.def_vec, FIRST_PSEUDO_REGISTER); > df_entry_block_defs_collect (&collection_rec, entry_block_defs); > > /* Process bb_refs chain */ > - df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL); > - collection_rec.def_vec.release (); > + df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL, > + copy_defs); > } > > > @@ -4084,13 +4058,11 @@ static void > df_record_exit_block_uses (bitmap exit_block_uses) > { > struct df_collection_rec collection_rec; > - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); > - vec_stack_alloc (df_ref, collection_rec.use_vec, FIRST_PSEUDO_REGISTER); > df_exit_block_uses_collect (&collection_rec, exit_block_uses); > > /* Process bb_refs chain */ > - df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL); > - collection_rec.use_vec.release (); > + df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL, > + copy_uses); > } > > > @@ -4331,13 +4303,13 @@ df_reg_chain_verify_unmarked (df_ref refs) > /* Verify that NEW_REC and OLD_REC have exactly the same members. */ > > static bool > -df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref *old_rec, > +df_refs_verify (const vec<df_ref, va_heap> *new_rec, df_ref *old_rec, > bool abort_if_fail) > { > unsigned int ix; > df_ref new_ref; > > - FOR_EACH_VEC_ELT (new_rec, ix, new_ref) > + FOR_EACH_VEC_ELT (*new_rec, ix, new_ref) > { > if (*old_rec == NULL || !df_ref_equal_p (new_ref, *old_rec)) > { > @@ -4369,14 +4341,14 @@ df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref > *old_rec, > /* Verify that NEW_REC and OLD_REC have exactly the same members. */ > > static bool > -df_mws_verify (vec<df_mw_hardreg_ptr, va_stack> new_rec, > +df_mws_verify (const vec<df_mw_hardreg_ptr, va_heap> *new_rec, > struct df_mw_hardreg **old_rec, > bool abort_if_fail) > { > unsigned int ix; > struct df_mw_hardreg *new_reg; > > - FOR_EACH_VEC_ELT (new_rec, ix, new_reg) > + FOR_EACH_VEC_ELT (*new_rec, ix, new_reg) > { > if (*old_rec == NULL || !df_mw_equal_p (new_reg, *old_rec)) > { > @@ -4430,13 +4402,13 @@ df_insn_refs_verify (struct df_collection_rec > *collection_rec, > > /* Unfortunately we cannot opt out early if one of these is not > right because the marks will not get cleared. */ > - ret1 = df_refs_verify (collection_rec->def_vec, DF_INSN_UID_DEFS (uid), > + ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid), > abort_if_fail); > - ret2 = df_refs_verify (collection_rec->use_vec, DF_INSN_UID_USES (uid), > + ret2 = df_refs_verify (&collection_rec->use_vec, DF_INSN_UID_USES (uid), > abort_if_fail); > - ret3 = df_refs_verify (collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES > (uid), > + ret3 = df_refs_verify (&collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES > (uid), > abort_if_fail); > - ret4 = df_mws_verify (collection_rec->mw_vec, DF_INSN_UID_MWS (uid), > + ret4 = df_mws_verify (&collection_rec->mw_vec, DF_INSN_UID_MWS (uid), > abort_if_fail); > return (ret1 && ret2 && ret3 && ret4); > } > @@ -4453,12 +4425,6 @@ df_bb_verify (basic_block bb) > struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index); > struct df_collection_rec collection_rec; > > - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); > - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); > - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); > - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); > - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); > - > gcc_assert (bb_info); > > /* Scan the block, one insn at a time, from beginning to end. */ > @@ -4472,8 +4438,8 @@ df_bb_verify (basic_block bb) > > /* Do the artificial defs and uses. */ > df_bb_refs_collect (&collection_rec, bb); > - df_refs_verify (collection_rec.def_vec, df_get_artificial_defs > (bb->index), true); > - df_refs_verify (collection_rec.use_vec, df_get_artificial_uses > (bb->index), true); > + df_refs_verify (&collection_rec.def_vec, df_get_artificial_defs > (bb->index), true); > + df_refs_verify (&collection_rec.use_vec, df_get_artificial_uses > (bb->index), true); > df_free_collection_rec (&collection_rec); > > return true; > diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c > index 85e5736..7e37b49 100644 > --- a/gcc/ipa-pure-const.c > +++ b/gcc/ipa-pure-const.c > @@ -190,15 +190,6 @@ warn_function_noreturn (tree decl) > true, warned_about, "noreturn"); > } > > -/* Init the function state. */ > - > -static void > -finish_state (void) > -{ > - funct_state_vec.release (); > -} > - > - > /* Return true if we have a function state for NODE. */ > > static inline bool > @@ -1488,7 +1479,6 @@ propagate (void) > if (has_function_state (node)) > free (get_function_state (node)); > funct_state_vec.release (); > - finish_state (); > return 0; > } > > diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c > index 9133df4..acdb689 100644 > --- a/gcc/tree-data-ref.c > +++ b/gcc/tree-data-ref.c > @@ -4322,7 +4322,7 @@ typedef struct data_ref_loc_d > true if STMT clobbers memory, false otherwise. */ > > static bool > -get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_stack> *references) > +get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_heap> *references) > { > bool clobbers_memory = false; > data_ref_loc ref; > @@ -4414,17 +4414,13 @@ find_data_references_in_stmt (struct loop *nest, > gimple stmt, > vec<data_reference_p> *datarefs) > { > unsigned i; > - vec<data_ref_loc, va_stack> references; > + stack_vec<data_ref_loc, 2> references; > data_ref_loc *ref; > bool ret = true; > data_reference_p dr; > > - vec_stack_alloc (data_ref_loc, references, 2); > if (get_references_in_stmt (stmt, &references)) > - { > - references.release (); > - return false; > - } > + return false; > > FOR_EACH_VEC_ELT (references, i, ref) > { > @@ -4448,17 +4444,13 @@ graphite_find_data_references_in_stmt (loop_p nest, > loop_p loop, gimple stmt, > vec<data_reference_p> *datarefs) > { > unsigned i; > - vec<data_ref_loc, va_stack> references; > + stack_vec<data_ref_loc, 2> references; > data_ref_loc *ref; > bool ret = true; > data_reference_p dr; > > - vec_stack_alloc (data_ref_loc, references, 2); > if (get_references_in_stmt (stmt, &references)) > - { > - references.release (); > - return false; > - } > + return false; > > FOR_EACH_VEC_ELT (references, i, ref) > { > diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c > index 4aaa98b..04a0979 100644 > --- a/gcc/tree-ssa-alias.c > +++ b/gcc/tree-ssa-alias.c > @@ -726,11 +726,8 @@ aliasing_component_refs_p (tree ref1, > static bool > nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2) > { > - vec<tree, va_stack> component_refs1; > - vec<tree, va_stack> component_refs2; > - > - vec_stack_alloc (tree, component_refs1, 16); > - vec_stack_alloc (tree, component_refs2, 16); > + stack_vec<tree, 16> component_refs1; > + stack_vec<tree, 16> component_refs2; > > /* Create the stack of handled components for REF1. */ > while (handled_component_p (ref1)) > diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c > index 8db5b9e..fd3c892 100644 > --- a/gcc/tree-ssa-loop-ivcanon.c > +++ b/gcc/tree-ssa-loop-ivcanon.c > @@ -1089,7 +1089,7 @@ propagate_constants_for_unrolling (basic_block bb) > > static bool > tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, > - vec<loop_p, va_stack>& father_stack, > + vec<loop_p, va_heap>& father_stack, > struct loop *loop) > { > struct loop *loop_father; > @@ -1153,12 +1153,11 @@ tree_unroll_loops_completely_1 (bool > may_increase_size, bool unroll_outer, > unsigned int > tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) > { > - vec<loop_p, va_stack> father_stack; > + stack_vec<loop_p, 16> father_stack; > bool changed; > int iteration = 0; > bool irred_invalidated = false; > > - vec_stack_alloc (loop_p, father_stack, 16); > do > { > changed = false; > diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c > index c2dd015..4b32bb4 100644 > --- a/gcc/tree-ssa-threadedge.c > +++ b/gcc/tree-ssa-threadedge.c > @@ -638,7 +638,7 @@ propagate_threaded_block_debug_into (basic_block dest, > basic_block src) > i++; > } > > - vec<tree, va_stack> fewvars = vNULL; > + stack_vec<tree, alloc_count> fewvars; > pointer_set_t *vars = NULL; > > /* If we're already starting with 3/4 of alloc_count, go for a > @@ -646,8 +646,6 @@ propagate_threaded_block_debug_into (basic_block dest, > basic_block src) > VEC. */ > if (i * 4 > alloc_count * 3) > vars = pointer_set_create (); > - else if (alloc_count) > - vec_stack_alloc (tree, fewvars, alloc_count); > > /* Now go through the initial debug stmts in DEST again, this time > actually inserting in VARS or FEWVARS. Don't bother checking for > diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c > index 574446a..4a14607 100644 > --- a/gcc/tree-vect-loop-manip.c > +++ b/gcc/tree-vect-loop-manip.c > @@ -107,7 +107,7 @@ typedef struct > with a PHI DEF that would soon become non-dominant, and when we got > to the suitable one, it wouldn't have anything to substitute any > more. */ > -static vec<adjust_info, va_stack> adjust_vec; > +static vec<adjust_info, va_heap> adjust_vec; > > /* Adjust any debug stmts that referenced AI->from values to use the > loop-closed AI->to, if the references are dominated by AI->bb and > @@ -1125,7 +1125,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, > if (MAY_HAVE_DEBUG_STMTS) > { > gcc_assert (!adjust_vec.exists ()); > - vec_stack_alloc (adjust_info, adjust_vec, 32); > + adjust_vec.create (32); > } > > if (e == exit_e) > diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c > index b3b3abe..f6a99eb 100644 > --- a/gcc/tree-vect-slp.c > +++ b/gcc/tree-vect-slp.c > @@ -1930,7 +1930,7 @@ vect_slp_analyze_operations (bb_vec_info bb_vinfo) > > static unsigned > vect_bb_slp_scalar_cost (basic_block bb, > - slp_tree node, vec<bool, va_stack> life) > + slp_tree node, vec<bool, va_heap> *life) > { > unsigned scalar_cost = 0; > unsigned i; > @@ -1944,7 +1944,7 @@ vect_bb_slp_scalar_cost (basic_block bb, > def_operand_p def_p; > stmt_vec_info stmt_info; > > - if (life[i]) > + if ((*life)[i]) > continue; > > /* If there is a non-vectorized use of the defs then the scalar > @@ -1961,11 +1961,11 @@ vect_bb_slp_scalar_cost (basic_block bb, > || gimple_bb (use_stmt) != bb > || !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (use_stmt))) > { > - life[i] = true; > + (*life)[i] = true; > BREAK_FROM_IMM_USE_STMT (use_iter); > } > } > - if (life[i]) > + if ((*life)[i]) > continue; > > stmt_info = vinfo_for_stmt (stmt); > @@ -2019,13 +2019,11 @@ vect_bb_vectorization_profitable_p (bb_vec_info > bb_vinfo) > /* Calculate scalar cost. */ > FOR_EACH_VEC_ELT (slp_instances, i, instance) > { > - vec<bool, va_stack> life; > - vec_stack_alloc (bool, life, SLP_INSTANCE_GROUP_SIZE (instance)); > - life.quick_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance)); > + stack_vec<bool, 20> life; > + life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance)); > scalar_cost += vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo), > SLP_INSTANCE_TREE (instance), > - life); > - life.release (); > + &life); > } > > /* Complete the target-specific cost calculation. */ > diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c > index 24c61cc..e908de1 100644 > --- a/gcc/var-tracking.c > +++ b/gcc/var-tracking.c > @@ -7905,7 +7905,7 @@ struct expand_loc_callback_data > > /* Stack of values and debug_exprs under expansion, and their > children. */ > - vec<rtx, va_stack> expanding; > + stack_vec<rtx, 4> expanding; > > /* Stack of values and debug_exprs whose expansion hit recursion > cycles. They will have VALUE_RECURSED_INTO marked when added to > @@ -7913,7 +7913,7 @@ struct expand_loc_callback_data > resolves to a valid location. So, if the flag remains set at the > end of the search, we know no valid location for this one can > possibly exist. */ > - vec<rtx, va_stack> pending; > + stack_vec<rtx, 4> pending; > > /* The maximum depth among the sub-expressions under expansion. > Zero indicates no expansion so far. */ > @@ -8415,11 +8415,11 @@ vt_expand_loc_callback (rtx x, bitmap regs, > This function performs this finalization of NULL locations. */ > > static void > -resolve_expansions_pending_recursion (vec<rtx, va_stack> pending) > +resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending) > { > - while (!pending.is_empty ()) > + while (!pending->is_empty ()) > { > - rtx x = pending.pop (); > + rtx x = pending->pop (); > decl_or_value dv; > > if (!VALUE_RECURSED_INTO (x)) > @@ -8439,8 +8439,6 @@ resolve_expansions_pending_recursion (vec<rtx, > va_stack> pending) > do \ > { \ > (d).vars = (v); \ > - vec_stack_alloc (rtx, (d).expanding, 4); \ > - vec_stack_alloc (rtx, (d).pending, 4); \ > (d).depth.complexity = (d).depth.entryvals = 0; \ > } \ > while (0) > @@ -8448,7 +8446,7 @@ resolve_expansions_pending_recursion (vec<rtx, > va_stack> pending) > #define FINI_ELCD(d, l) \ > do \ > { \ > - resolve_expansions_pending_recursion ((d).pending); \ > + resolve_expansions_pending_recursion (&(d).pending); \ > (d).pending.release (); \ > (d).expanding.release (); \ > \ > @@ -8742,7 +8740,7 @@ emit_note_insn_var_location (variable_def **varp, > emit_note_data *data) > > int > var_track_values_to_stack (variable_def **slot, > - vec<rtx, va_stack> *changed_values_stack) > + vec<rtx, va_heap> *changed_values_stack) > { > variable var = *slot; > > @@ -8777,7 +8775,7 @@ remove_value_from_changed_variables (rtx val) > > static void > notify_dependents_of_changed_value (rtx val, variable_table_type htab, > - vec<rtx, va_stack> *changed_values_stack) > + vec<rtx, va_heap> *changed_values_stack) > { > variable_def **slot; > variable var; > @@ -8862,13 +8860,11 @@ process_changed_values (variable_table_type htab) > { > int i, n; > rtx val; > - vec<rtx, va_stack> changed_values_stack; > - > - vec_stack_alloc (rtx, changed_values_stack, 20); > + stack_vec<rtx, 20> changed_values_stack; > > /* Move values from changed_variables to changed_values_stack. */ > changed_variables > - .traverse <vec<rtx, va_stack>*, var_track_values_to_stack> > + .traverse <vec<rtx, va_heap>*, var_track_values_to_stack> > (&changed_values_stack); > > /* Back-propagate change notifications in values while popping > @@ -8889,8 +8885,6 @@ process_changed_values (variable_table_type htab) > n--; > } > } > - > - changed_values_stack.release (); > } > > /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain > diff --git a/gcc/vec.c b/gcc/vec.c > index 1303d53..f3c3315 100644 > --- a/gcc/vec.c > +++ b/gcc/vec.c > @@ -217,49 +217,6 @@ vec_prefix::calculate_allocation (vec_prefix *pfx, > unsigned reserve, > } > > > -/* Stack vectors are a little different. VEC_alloc turns into a call > - to vec<T, A>::stack_reserve and passes in space allocated via a > - call to alloca. We record that pointer so that we know that we > - shouldn't free it. If the vector is resized, we resize it on the > - heap. We record the pointers in a vector and search it in LIFO > - order--i.e., we look for the newest stack vectors first. We don't > - expect too many stack vectors at any one level, and searching from > - the end should normally be efficient even if they are used in a > - recursive function. */ > - > -static vec<void *> stack_vecs; > - > -/* Add a stack vector to STACK_VECS. */ > - > -void > -register_stack_vec (void *vec) > -{ > - stack_vecs.safe_push (vec); > -} > - > - > -/* If VEC is registered in STACK_VECS, return its index. > - Otherwise, return -1. */ > - > -int > -stack_vec_register_index (void *vec) > -{ > - for (unsigned ix = stack_vecs.length (); ix > 0; --ix) > - if (stack_vecs[ix - 1] == vec) > - return static_cast<int> (ix - 1); > - return -1; > -} > - > - > -/* Remove vector at slot IX from the list of registered stack vectors. */ > - > -void > -unregister_stack_vec (unsigned ix) > -{ > - stack_vecs.unordered_remove (ix); > -} > - > - > /* Helper for qsort; sort descriptors by amount of memory consumed. */ > > static int > diff --git a/gcc/vec.h b/gcc/vec.h > index 60b77ec..f97e022 100644 > --- a/gcc/vec.h > +++ b/gcc/vec.h > @@ -101,8 +101,6 @@ along with GCC; see the file COPYING3. If not see > - Heap: allocation is done using malloc/free. This is the > default allocation strategy. > > - - Stack: allocation is done using alloca. > - > - GC: allocation is done using ggc_alloc/ggc_free. > > - GC atomic: same as GC with the exception that the elements > @@ -233,9 +231,9 @@ struct vec_prefix > friend struct va_gc; > friend struct va_gc_atomic; > friend struct va_heap; > - friend struct va_stack; > > - unsigned m_alloc; > + unsigned m_alloc : 31; > + unsigned m_has_auto_buf : 1; > unsigned m_num; > }; > > @@ -255,8 +253,7 @@ struct vl_ptr { }; > va_heap - Allocation uses malloc/free. > va_gc - Allocation uses ggc_alloc. > va_gc_atomic - Same as GC, but individual elements of the array > - do not need to be marked during collection. > - va_stack - Allocation uses alloca. */ > + do not need to be marked during collection. */ > > /* Allocator type for heap vectors. */ > struct va_heap > @@ -401,107 +398,6 @@ struct va_gc_atomic : va_gc > }; > > > -/* Allocator type for stack vectors. */ > -struct va_stack > -{ > - /* Use vl_ptr as the default layout for stack vectors. */ > - typedef vl_ptr default_layout; > - > - template<typename T> > - static void alloc (vec<T, va_stack, vl_ptr>&, unsigned, > - vec<T, va_stack, vl_embed> *); > - > - template <typename T> > - static void reserve (vec<T, va_stack, vl_embed> *&, unsigned, bool > - CXX_MEM_STAT_INFO); > - > - template <typename T> > - static void release (vec<T, va_stack, vl_embed> *&); > -}; > - > -/* Helper functions to keep track of vectors allocated on the stack. */ > -void register_stack_vec (void *); > -int stack_vec_register_index (void *); > -void unregister_stack_vec (unsigned); > - > -/* Allocate a vector V which uses alloca for the initial allocation. > - SPACE is space allocated using alloca. NELEMS is the number of > - entries allocated. */ > - > -template<typename T> > -void > -va_stack::alloc (vec<T, va_stack, vl_ptr> &v, unsigned nelems, > - vec<T, va_stack, vl_embed> *space) > -{ > - v.m_vec = space; > - register_stack_vec (static_cast<void *> (v.m_vec)); > - v.m_vec->embedded_init (nelems, 0); > -} > - > - > -/* Reserve NELEMS slots for a vector initially allocated on the stack. > - When this happens, we switch back to heap allocation. We remove > - the vector from stack_vecs, if it is there, since we no longer need > - to avoid freeing it. If EXACT is true, grow exactly, otherwise > - grow exponentially. */ > - > -template<typename T> > -void > -va_stack::reserve (vec<T, va_stack, vl_embed> *&v, unsigned nelems, bool > exact > - MEM_STAT_DECL) > -{ > - int ix = stack_vec_register_index (static_cast<void *> (v)); > - if (ix >= 0) > - unregister_stack_vec (ix); > - else > - { > - /* V is already on the heap. */ > - va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v), > - nelems, exact PASS_MEM_STAT); > - return; > - } > - > - /* Move VEC_ to the heap. */ > - nelems += v->m_vecpfx.m_num; > - vec<T, va_stack, vl_embed> *oldvec = v; > - v = NULL; > - va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&>(v), > nelems, > - exact PASS_MEM_STAT); > - if (v && oldvec) > - { > - v->m_vecpfx.m_num = oldvec->length (); > - memcpy (v->m_vecdata, > - oldvec->m_vecdata, > - oldvec->length () * sizeof (T)); > - } > -} > - > - > -/* Free a vector allocated on the stack. Don't actually free it if we > - find it in the hash table. */ > - > -template<typename T> > -void > -va_stack::release (vec<T, va_stack, vl_embed> *&v) > -{ > - if (v == NULL) > - return; > - > - int ix = stack_vec_register_index (static_cast<void *> (v)); > - if (ix >= 0) > - { > - unregister_stack_vec (ix); > - v = NULL; > - } > - else > - { > - /* The vector was not on the list of vectors allocated on the stack, > so it > - must be allocated on the heap. */ > - va_heap::release (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v)); > - } > -} > - > - > /* Generic vector template. Default values for A and L indicate the > most commonly used strategies. > > @@ -597,7 +493,6 @@ public: > friend struct va_gc; > friend struct va_gc_atomic; > friend struct va_heap; > - friend struct va_stack; > > /* FIXME - These fields should be private, but we need to cater to > compilers that have stricter notions of PODness for types. */ > @@ -1112,6 +1007,7 @@ inline void > vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num) > { > m_vecpfx.m_alloc = alloc; > + m_vecpfx.m_has_auto_buf = 0; > m_vecpfx.m_num = num; > } > > @@ -1218,8 +1114,8 @@ gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator > op, void *cookie) > As long as we use C++03, we cannot have constructors nor > destructors in classes that are stored in unions. */ > > -template<typename T, typename A> > -struct vec<T, A, vl_ptr> > +template<typename T> > +struct vec<T, va_heap, vl_ptr> > { > public: > /* Memory allocation and deallocation for the embedded vector. > @@ -1284,23 +1180,39 @@ public: > void qsort (int (*) (const void *, const void *)); > unsigned lower_bound (T, bool (*)(const T &, const T &)) const; > > - template<typename T1> > - friend void va_stack::alloc (vec<T1, va_stack, vl_ptr>&, unsigned, > - vec<T1, va_stack, vl_embed> *); > + bool using_auto_storage () const; > > /* FIXME - This field should be private, but we need to cater to > compilers that have stricter notions of PODness for types. */ > - vec<T, A, vl_embed> *m_vec; > + vec<T, va_heap, vl_embed> *m_vec; > }; > > > -/* Empty specialization for GC allocation. This will prevent GC > - vectors from using the vl_ptr layout. FIXME: This is needed to > - circumvent limitations in the GTY machinery. */ > - > -template<typename T> > -struct vec<T, va_gc, vl_ptr> > +/* stack_vec is a subclass of vec containing N elements of internal storage. > + You probably only want to allocate this on the stack because if the array > + ends up being larger or much smaller than N it will be wasting space. */ > +template<typename T, size_t N> > +class stack_vec : public vec<T, va_heap> > { > +public: > + stack_vec () > + { > + m_header.m_alloc = N; > + m_header.m_has_auto_buf = 1; > + m_header.m_num = 0; > + this->m_vec = reinterpret_cast<vec<T, va_heap, vl_embed> *> (&m_header); > + } > + > + ~stack_vec () > + { > + this->release (); > + } > + > +private: > + friend class vec<T, va_heap, vl_ptr>; > + > + vec_prefix m_header; > + T m_data[N]; > }; > > > @@ -1343,45 +1255,6 @@ vec_free (vec<T> *&v) > } > > > -/* Allocate a new stack vector with space for exactly NELEMS objects. > - If NELEMS is zero, NO vector is created. > - > - For the stack allocator, no memory is really allocated. The vector > - is initialized to be at address SPACE and contain NELEMS slots. > - Memory allocation actually occurs in the expansion of VEC_alloc. > - > - Usage notes: > - > - * This does not allocate an instance of vec<T, A>. It allocates the > - actual vector of elements (i.e., vec<T, A, vl_embed>) inside a > - vec<T, A> instance. > - > - * This allocator must always be a macro: > - > - We support a vector which starts out with space on the stack and > - switches to heap space when forced to reallocate. This works a > - little differently. In the case of stack vectors, vec_alloc will > - expand to a call to vec_alloc_1 that calls XALLOCAVAR to request > - the initial allocation. This uses alloca to get the initial > - space. Since alloca can not be usefully called in an inline > - function, vec_alloc must always be a macro. > - > - Important limitations of stack vectors: > - > - - Only the initial allocation will be made using alloca, so pass > - a reasonable estimate that doesn't use too much stack space; > - don't pass zero. > - > - - Don't return a stack-allocated vector from the function which > - allocated it. */ > - > -#define vec_stack_alloc(T,V,N) \ > - do { \ > - typedef vec<T, va_stack, vl_embed> stackv; \ > - va_stack::alloc (V, N, XALLOCAVAR (stackv, stackv::embedded_size (N)));\ > - } while (0) > - > - > /* Return iteration condition and update PTR to point to the IX'th > element of this vector. Use this to iterate over the elements of a > vector as follows, > @@ -1389,9 +1262,9 @@ vec_free (vec<T> *&v) > for (ix = 0; v.iterate (ix, &ptr); ix++) > continue; */ > > -template<typename T, typename A> > +template<typename T> > inline bool > -vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const > +vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const > { > if (m_vec) > return m_vec->iterate (ix, ptr); > @@ -1412,9 +1285,9 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const > > This variant is for vectors of objects. */ > > -template<typename T, typename A> > +template<typename T> > inline bool > -vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) const > +vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const > { > if (m_vec) > return m_vec->iterate (ix, ptr); > @@ -1451,11 +1324,11 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) > const > > /* Return a copy of this vector. */ > > -template<typename T, typename A> > -inline vec<T, A, vl_ptr> > -vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const > +template<typename T> > +inline vec<T, va_heap, vl_ptr> > +vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const > { > - vec<T, A, vl_ptr> new_vec = vNULL; > + vec<T, va_heap, vl_ptr> new_vec = vNULL; > if (length ()) > new_vec.m_vec = m_vec->copy (); > return new_vec; > @@ -1471,14 +1344,34 @@ vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const > Note that this can cause the embedded vector to be reallocated. > Returns true iff reallocation actually occurred. */ > > -template<typename T, typename A> > +template<typename T> > inline bool > -vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) > -{ > - bool extend = nelems ? !space (nelems) : false; > - if (extend) > - A::reserve (m_vec, nelems, exact PASS_MEM_STAT); > - return extend; > +vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) > +{ > + if (!nelems || space (nelems)) > + return false; > + > + /* For now play a game with va_heap::reserve to hide our auto storage if > any, > + this is necessary because it doesn't have enough information to know the > + embedded vector is in auto storage, and so should not be freed. */ > + vec<T, va_heap, vl_embed> *oldvec = m_vec; > + unsigned int oldsize = 0; > + bool handle_auto_vec = m_vec && using_auto_storage (); > + if (handle_auto_vec) > + { > + m_vec = NULL; > + oldsize = oldvec->length (); > + nelems += oldsize; > + } > + > + va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT); > + if (handle_auto_vec) > + { > + memcpy (m_vec->address (), oldvec->address (), sizeof (T) * oldsize); > + m_vec->m_vecpfx.m_num = oldsize; > + } > + > + return true; > } > > > @@ -1487,9 +1380,9 @@ vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact > MEM_STAT_DECL) > embedded vector to be reallocated. Returns true iff reallocation > actually occurred. */ > > -template<typename T, typename A> > +template<typename T> > inline bool > -vec<T, A, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) > { > return reserve (nelems, true PASS_MEM_STAT); > } > @@ -1500,9 +1393,9 @@ vec<T, A, vl_ptr>::reserve_exact (unsigned nelems > MEM_STAT_DECL) > unconditionally allocated from scratch. The old one, if it > existed, is lost. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) > { > m_vec = NULL; > if (nelems > 0) > @@ -1512,23 +1405,30 @@ vec<T, A, vl_ptr>::create (unsigned nelems > MEM_STAT_DECL) > > /* Free the memory occupied by the embedded vector. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::release (void) > +vec<T, va_heap, vl_ptr>::release (void) > { > - if (m_vec) > - A::release (m_vec); > -} > + if (!m_vec) > + return; > > + if (using_auto_storage ()) > + { > + static_cast<stack_vec<T, 1> *> (this)->m_header.m_num = 0; > + return; > + } > + > + va_heap::release (m_vec); > +} > > /* Copy the elements from SRC to the end of this vector as if by memcpy. > SRC and this vector must be allocated with the same memory > allocation mechanism. This vector is assumed to have sufficient > headroom available. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src) > +vec<T, va_heap, vl_ptr>::splice (vec<T, va_heap, vl_ptr> &src) > { > if (src.m_vec) > m_vec->splice (*(src.m_vec)); > @@ -1540,9 +1440,10 @@ vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src) > If there is not enough headroom in this vector, it will be reallocated > as needed. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::safe_splice (vec<T, va_heap, vl_ptr> &src > + MEM_STAT_DECL) > { > if (src.length ()) > { > @@ -1556,9 +1457,9 @@ vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src > MEM_STAT_DECL) > sufficient space in the vector. Return a pointer to the slot > where OBJ was inserted. */ > > -template<typename T, typename A> > +template<typename T> > inline T * > -vec<T, A, vl_ptr>::quick_push (const T &obj) > +vec<T, va_heap, vl_ptr>::quick_push (const T &obj) > { > return m_vec->quick_push (obj); > } > @@ -1568,9 +1469,9 @@ vec<T, A, vl_ptr>::quick_push (const T &obj) > the embedded vector, if needed. Return a pointer to the slot where > OBJ was inserted. */ > > -template<typename T, typename A> > +template<typename T> > inline T * > -vec<T, A, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) > { > reserve (1, false PASS_MEM_STAT); > return quick_push (obj); > @@ -1579,9 +1480,9 @@ vec<T, A, vl_ptr>::safe_push (const T &obj > MEM_STAT_DECL) > > /* Pop and return the last element off the end of the vector. */ > > -template<typename T, typename A> > +template<typename T> > inline T & > -vec<T, A, vl_ptr>::pop (void) > +vec<T, va_heap, vl_ptr>::pop (void) > { > return m_vec->pop (); > } > @@ -1590,9 +1491,9 @@ vec<T, A, vl_ptr>::pop (void) > /* Set the length of the vector to LEN. The new length must be less > than or equal to the current length. This is an O(1) operation. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::truncate (unsigned size) > +vec<T, va_heap, vl_ptr>::truncate (unsigned size) > { > if (m_vec) > m_vec->truncate (size); > @@ -1605,9 +1506,9 @@ vec<T, A, vl_ptr>::truncate (unsigned size) > longer than the current length. The new elements are > uninitialized. Reallocate the internal vector, if needed. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL) > { > unsigned oldlen = length (); > gcc_checking_assert (oldlen <= len); > @@ -1620,9 +1521,9 @@ vec<T, A, vl_ptr>::safe_grow (unsigned len > MEM_STAT_DECL) > long or longer than the current length. The new elements are > initialized to zero. Reallocate the internal vector, if needed. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL) > { > unsigned oldlen = length (); > safe_grow (len PASS_MEM_STAT); > @@ -1633,9 +1534,9 @@ vec<T, A, vl_ptr>::safe_grow_cleared (unsigned len > MEM_STAT_DECL) > /* Same as vec::safe_grow but without reallocation of the internal vector. > If the vector cannot be extended, a runtime assertion will be triggered. > */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::quick_grow (unsigned len) > +vec<T, va_heap, vl_ptr>::quick_grow (unsigned len) > { > gcc_checking_assert (m_vec); > m_vec->quick_grow (len); > @@ -1646,9 +1547,9 @@ vec<T, A, vl_ptr>::quick_grow (unsigned len) > internal vector. If the vector cannot be extended, a runtime > assertion will be triggered. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::quick_grow_cleared (unsigned len) > +vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len) > { > gcc_checking_assert (m_vec); > m_vec->quick_grow_cleared (len); > @@ -1658,9 +1559,9 @@ vec<T, A, vl_ptr>::quick_grow_cleared (unsigned len) > /* Insert an element, OBJ, at the IXth position of this vector. There > must be sufficient space. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::quick_insert (unsigned ix, const T &obj) > +vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj) > { > m_vec->quick_insert (ix, obj); > } > @@ -1669,9 +1570,9 @@ vec<T, A, vl_ptr>::quick_insert (unsigned ix, const T > &obj) > /* Insert an element, OBJ, at the IXth position of the vector. > Reallocate the embedded vector, if necessary. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) > +vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj > MEM_STAT_DECL) > { > reserve (1, false PASS_MEM_STAT); > quick_insert (ix, obj); > @@ -1682,9 +1583,9 @@ vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T > &obj MEM_STAT_DECL) > remaining elements is preserved. This is an O(N) operation due to > a memmove. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::ordered_remove (unsigned ix) > +vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix) > { > m_vec->ordered_remove (ix); > } > @@ -1693,9 +1594,9 @@ vec<T, A, vl_ptr>::ordered_remove (unsigned ix) > /* Remove an element from the IXth position of this vector. Ordering > of remaining elements is destroyed. This is an O(1) operation. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::unordered_remove (unsigned ix) > +vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix) > { > m_vec->unordered_remove (ix); > } > @@ -1704,9 +1605,9 @@ vec<T, A, vl_ptr>::unordered_remove (unsigned ix) > /* Remove LEN elements starting at the IXth. Ordering is retained. > This is an O(N) operation due to memmove. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::block_remove (unsigned ix, unsigned len) > +vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len) > { > m_vec->block_remove (ix, len); > } > @@ -1715,9 +1616,9 @@ vec<T, A, vl_ptr>::block_remove (unsigned ix, unsigned > len) > /* Sort the contents of this vector with qsort. CMP is the comparison > function to pass to qsort. */ > > -template<typename T, typename A> > +template<typename T> > inline void > -vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, const void *)) > +vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *)) > { > if (m_vec) > m_vec->qsort (cmp); > @@ -1729,14 +1630,27 @@ vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, > const void *)) > function that returns true if the first argument is strictly less > than the second. */ > > -template<typename T, typename A> > +template<typename T> > inline unsigned > -vec<T, A, vl_ptr>::lower_bound (T obj, bool (*lessthan)(const T &, const T > &)) > +vec<T, va_heap, vl_ptr>::lower_bound (T obj, > + bool (*lessthan)(const T &, const T &)) > const > { > return m_vec ? m_vec->lower_bound (obj, lessthan) : 0; > } > > +template<typename T> > +inline bool > +vec<T, va_heap, vl_ptr>::using_auto_storage () const > +{ > + if (!m_vec->m_vecpfx.m_has_auto_buf) > + return false; > + > + const vec_prefix *auto_header > + = &static_cast<const stack_vec<T, 1> *> (this)->m_header; > + return reinterpret_cast<vec_prefix *> (m_vec) == auto_header; > +} > + > #if (GCC_VERSION >= 3000) > # pragma GCC poison m_vec m_vecpfx m_vecdata > #endif > -- > 1.8.4.rc3 >