Message ID | 20170120215807.yh7acd36yq4qd4ur@virgil.suse.cz |
---|---|
State | New |
Headers | show |
On Fri, Jan 20, 2017 at 1:58 PM, Martin Jambor <mjambor@suse.cz> wrote: > Hi, > > when I fixed PR 78365 by streaming types of parameters that might not > have been anywhere else, I forgot that I was holding them in non-GC > memory and so I caused PR 79108. The following patch fixes it by > putting ipa_param_descriptor and ipa_node_params structures into GC > memory, together with summary holding class ipa_node_params_t which is > now a GC root. In the process, I have turned the destructor of the > latter into a remove and insert hooks of the summary holder. > > Bootstrapped and tested on x86_64-linux, also LTO-bootstrapped and > tested, although with only C,C++ and Fortran and with sanitizers and > multilib disabled. (It is now a part of an undergoing LTO bootstrap > with everything). OK for trunk? This fixes the ICE for all of the SPEC CPU 2006 benchmarks that I was getting them with. Thanks, Andrew > > Thanks, > > Martin > > > 2017-01-19 Martin Jambor <mjambor@suse.cz> > > PR ipa/79108 > * ipa-prop.h (ipa_param_descriptor): Anotate with with GTY(()). > (ipa_node_params): Annotate with GTY((for_user)). Make descriptors > field a pointer to garbage collected vector, mark lattices and > ipcp_orig_node with GTY((skip)). > (ipa_get_param_count): Adjust to descriptors being a pointer. > (ipa_get_param): Likewise. > (ipa_get_type): Likewise. > (ipa_get_param_move_cost): Likewise. > (ipa_set_param_used): Likewise. > (ipa_get_controlled_uses): Likewise. > (ipa_set_controlled_uses): Likewise. > (ipa_is_param_used): Likewise. > (ipa_node_params_t): Move into garbage collector. New methods insert > and remove. > (ipa_node_params_sum): Annotate wth GTY(()). > (ipa_check_create_node_params): Adjust to ipa_node_params_sum being > garbage collected. > (ipa_load_from_parm_agg): Adjust declaration. > * ipa-icf.c (param_used_p): Adjust to descriptors being a pointer. > * ipa-profile.c (ipa_profile): Likewise. > * ipa-prop.c (ipa_get_param_decl_index_1): Likewise. > (ipa_populate_param_decls): Make descriptors parameter garbage > collected. > (ipa_dump_param): Adjust to descriptors being a pointer. > (ipa_alloc_node_params): Likewise. > (ipa_initialize_node_params): Likewise. > (load_from_param_1): Make descriptors parameter garbage collected. > (load_from_unmodified_param): Likewise. > (load_from_param): Likewise. > (ipa_load_from_parm_agg): Likewise. > (ipa_node_params::~ipa_node_params): Removed. > (ipa_free_all_node_params): Remove call to delete operator. > (ipa_node_params_t::insert): New. > (ipa_node_params_t::remove): Likewise. > (ipa_node_params_t::duplicate): Adjust to descriptors being a pointer, > copy known_csts and known_contexts vectors. > (ipa_read_node_info): Adjust to descriptors being a pointer. > (ipcp_modif_dom_walker): Make m_descriptors field garbage > collected. > (ipcp_transform_function): Make descriptors variable garbage > collected. > > testsuite/ > * gfortran.dg/lto/pr79108_0.f90: New test. > --- > gcc/ipa-icf.c | 5 +- > gcc/ipa-profile.c | 3 +- > gcc/ipa-prop.c | 101 +++++++++++++++------------- > gcc/ipa-prop.h | 62 ++++++++++------- > gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 | 14 ++++ > 5 files changed, 111 insertions(+), 74 deletions(-) > create mode 100644 gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > > diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c > index c17a677b459..b9a5b4f2546 100644 > --- a/gcc/ipa-icf.c > +++ b/gcc/ipa-icf.c > @@ -539,9 +539,8 @@ sem_function::param_used_p (unsigned int i) > > struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); > > - if (parms_info->descriptors.is_empty () > - || parms_info->descriptors.length () <= i) > - return true; > + if (vec_safe_length (parms_info->descriptors) <= i) > + return true; > > return ipa_is_param_used (IPA_NODE_REF (get_node ()), i); > } > diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c > index 3e9b2a915fc..ae1ca2f3762 100644 > --- a/gcc/ipa-profile.c > +++ b/gcc/ipa-profile.c > @@ -621,7 +621,8 @@ ipa_profile (void) > "and can be discarded.\n"); > } > else if (ipa_node_params_sum && ipa_edge_args_vector > - && !IPA_NODE_REF (n2)->descriptors.is_empty () > + && (!vec_safe_is_empty > + (IPA_NODE_REF (n2)->descriptors)) > && ipa_get_param_count (IPA_NODE_REF (n2)) > != ipa_get_cs_argument_count (IPA_EDGE_REF (e)) > && (ipa_get_param_count (IPA_NODE_REF (n2)) > diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c > index 1f68f736e46..4d77c9b25ef 100644 > --- a/gcc/ipa-prop.c > +++ b/gcc/ipa-prop.c > @@ -99,13 +99,14 @@ ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) > to INFO. */ > > static int > -ipa_get_param_decl_index_1 (vec<ipa_param_descriptor> descriptors, tree ptree) > +ipa_get_param_decl_index_1 (vec<ipa_param_descriptor, va_gc> *descriptors, > + tree ptree) > { > int i, count; > > - count = descriptors.length (); > + count = vec_safe_length (descriptors); > for (i = 0; i < count; i++) > - if (descriptors[i].decl_or_type == ptree) > + if ((*descriptors)[i].decl_or_type == ptree) > return i; > > return -1; > @@ -125,7 +126,7 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) > > static void > ipa_populate_param_decls (struct cgraph_node *node, > - vec<ipa_param_descriptor> &descriptors) > + vec<ipa_param_descriptor, va_gc> &descriptors) > { > tree fndecl; > tree fnargs; > @@ -168,10 +169,10 @@ void > ipa_dump_param (FILE *file, struct ipa_node_params *info, int i) > { > fprintf (file, "param #%i", i); > - if (info->descriptors[i].decl_or_type) > + if ((*info->descriptors)[i].decl_or_type) > { > fprintf (file, " "); > - print_generic_expr (file, info->descriptors[i].decl_or_type, 0); > + print_generic_expr (file, (*info->descriptors)[i].decl_or_type, 0); > } > } > > @@ -183,8 +184,8 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count) > { > struct ipa_node_params *info = IPA_NODE_REF (node); > > - if (!info->descriptors.exists () && param_count) > - info->descriptors.safe_grow_cleared (param_count); > + if (!info->descriptors && param_count) > + vec_safe_grow_cleared (info->descriptors, param_count); > } > > /* Initialize the ipa_node_params structure associated with NODE by counting > @@ -196,10 +197,10 @@ ipa_initialize_node_params (struct cgraph_node *node) > { > struct ipa_node_params *info = IPA_NODE_REF (node); > > - if (!info->descriptors.exists ()) > + if (!info->descriptors) > { > ipa_alloc_node_params (node, count_formal_params (node->decl)); > - ipa_populate_param_decls (node, info->descriptors); > + ipa_populate_param_decls (node, *info->descriptors); > } > } > > @@ -867,7 +868,7 @@ parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index, > > static int > load_from_param_1 (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > int index; > @@ -892,7 +893,7 @@ load_from_param_1 (struct ipa_func_body_info *fbi, > > static int > load_from_unmodified_param (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > if (!gimple_assign_single_p (stmt)) > @@ -906,7 +907,7 @@ load_from_unmodified_param (struct ipa_func_body_info *fbi, > > static int > load_from_param (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > if (!is_gimple_assign (stmt)) > @@ -1010,7 +1011,7 @@ parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index, > > bool > ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt, tree op, int *index_p, > HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, > bool *by_ref_p, bool *guaranteed_unmodified) > @@ -3604,33 +3605,11 @@ ipa_free_all_edge_args (void) > vec_free (ipa_edge_args_vector); > } > > -/* Frees all dynamically allocated structures that the param info points > - to. */ > - > -ipa_node_params::~ipa_node_params () > -{ > - descriptors.release (); > - free (lattices); > - /* Lattice values and their sources are deallocated with their alocation > - pool. */ > - known_csts.release (); > - known_contexts.release (); > - > - lattices = NULL; > - ipcp_orig_node = NULL; > - analysis_done = 0; > - node_enqueued = 0; > - do_clone_for_all_contexts = 0; > - is_all_contexts_clone = 0; > - node_dead = 0; > -} > - > /* Free all ipa_node_params structures. */ > > void > ipa_free_all_node_params (void) > { > - delete ipa_node_params_sum; > ipa_node_params_sum = NULL; > } > > @@ -3792,6 +3771,36 @@ ipa_add_new_function (cgraph_node *node, void *data ATTRIBUTE_UNUSED) > ipa_analyze_node (node); > } > > +/* Initialize a newly created param info. */ > + > +void > +ipa_node_params_t::insert (cgraph_node *, ipa_node_params *info) > +{ > + info->lattices = NULL; > + info->ipcp_orig_node = NULL; > + info->analysis_done = 0; > + info->node_enqueued = 0; > + info->do_clone_for_all_contexts = 0; > + info->is_all_contexts_clone = 0; > + info->node_dead = 0; > + info->node_within_scc = 0; > + info->node_calling_single_call = 0; > + info->versionable = 0; > +} > + > +/* Frees all dynamically allocated structures that the param info points > + to. */ > + > +void > +ipa_node_params_t::remove (cgraph_node *, ipa_node_params *info) > +{ > + free (info->lattices); > + /* Lattice values and their sources are deallocated with their alocation > + pool. */ > + info->known_csts.release (); > + info->known_contexts.release (); > +} > + > /* Hook that is called by summary when a node is duplicated. */ > > void > @@ -3801,9 +3810,11 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst, > { > ipa_agg_replacement_value *old_av, *new_av; > > - new_info->descriptors = old_info->descriptors.copy (); > + new_info->descriptors = vec_safe_copy (old_info->descriptors); > new_info->lattices = NULL; > new_info->ipcp_orig_node = old_info->ipcp_orig_node; > + new_info->known_csts = old_info->known_csts.copy (); > + new_info->known_contexts = old_info->known_contexts.copy (); > > new_info->analysis_done = old_info->analysis_done; > new_info->node_enqueued = old_info->node_enqueued; > @@ -5022,7 +5033,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, > ipa_alloc_node_params (node, streamer_read_uhwi (ib)); > > for (k = 0; k < ipa_get_param_count (info); k++) > - info->descriptors[k].move_cost = streamer_read_uhwi (ib); > + (*info->descriptors)[k].move_cost = streamer_read_uhwi (ib); > > bp = streamer_read_bitpack (ib); > if (ipa_get_param_count (info) != 0) > @@ -5033,7 +5044,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, > for (k = 0; k < ipa_get_param_count (info); k++) > { > ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); > - info->descriptors[k].decl_or_type = stream_read_tree (ib, data_in); > + (*info->descriptors)[k].decl_or_type = stream_read_tree (ib, data_in); > } > for (e = node->callees; e; e = e->next_callee) > { > @@ -5483,7 +5494,7 @@ class ipcp_modif_dom_walker : public dom_walker > { > public: > ipcp_modif_dom_walker (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descs, > + vec<ipa_param_descriptor, va_gc> *descs, > struct ipa_agg_replacement_value *av, > bool *sc, bool *cc) > : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs), > @@ -5493,7 +5504,7 @@ public: > > private: > struct ipa_func_body_info *m_fbi; > - vec<ipa_param_descriptor> m_descriptors; > + vec<ipa_param_descriptor, va_gc> *m_descriptors; > struct ipa_agg_replacement_value *m_aggval; > bool *m_something_changed, *m_cfg_changed; > }; > @@ -5751,7 +5762,7 @@ ipcp_update_vr (struct cgraph_node *node) > unsigned int > ipcp_transform_function (struct cgraph_node *node) > { > - vec<ipa_param_descriptor> descriptors = vNULL; > + vec<ipa_param_descriptor, va_gc> *descriptors = NULL; > struct ipa_func_body_info fbi; > struct ipa_agg_replacement_value *aggval; > int param_count; > @@ -5783,8 +5794,8 @@ ipcp_transform_function (struct cgraph_node *node) > fbi.param_count = param_count; > fbi.aa_walked = 0; > > - descriptors.safe_grow_cleared (param_count); > - ipa_populate_param_decls (node, descriptors); > + vec_safe_grow_cleared (descriptors, param_count); > + ipa_populate_param_decls (node, *descriptors); > calculate_dominance_info (CDI_DOMINATORS); > ipcp_modif_dom_walker (&fbi, descriptors, aggval, &something_changed, > &cfg_changed).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); > @@ -5799,7 +5810,7 @@ ipcp_transform_function (struct cgraph_node *node) > (*ipcp_transformations)[node->uid].bits = NULL; > (*ipcp_transformations)[node->uid].m_vr = NULL; > > - descriptors.release (); > + vec_free (descriptors); > > if (!something_changed) > return 0; > diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h > index c9a69ab1f53..93a2390c321 100644 > --- a/gcc/ipa-prop.h > +++ b/gcc/ipa-prop.h > @@ -298,7 +298,7 @@ ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc) > > /* Summary describing a single formal parameter. */ > > -struct ipa_param_descriptor > +struct GTY(()) ipa_param_descriptor > { > /* In analysis and modification phase, this is the PARAM_DECL of this > parameter, in IPA LTO phase, this is the type of the the described > @@ -318,25 +318,23 @@ struct ipa_param_descriptor > and some other information for interprocedural passes that operate on > parameters (such as ipa-cp). */ > > -struct ipa_node_params > +struct GTY((for_user)) ipa_node_params > { > - ~ipa_node_params (); > - > /* Information about individual formal parameters that are gathered when > summaries are generated. */ > - vec<ipa_param_descriptor> descriptors; > + vec<ipa_param_descriptor, va_gc> *descriptors; > /* Pointer to an array of structures describing individual formal > parameters. */ > - struct ipcp_param_lattices *lattices; > + struct ipcp_param_lattices * GTY((skip)) lattices; > /* Only for versioned nodes this field would not be NULL, > it points to the node that IPA cp cloned from. */ > - struct cgraph_node *ipcp_orig_node; > + struct cgraph_node * GTY((skip)) ipcp_orig_node; > /* If this node is an ipa-cp clone, these are the known constants that > describe what it has been specialized for. */ > - vec<tree> known_csts; > + vec<tree> GTY((skip)) known_csts; > /* If this node is an ipa-cp clone, these are the known polymorphic contexts > that describe what it has been specialized for. */ > - vec<ipa_polymorphic_call_context> known_contexts; > + vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts; > /* Whether the param uses analysis and jump function computation has already > been performed. */ > unsigned analysis_done : 1; > @@ -417,7 +415,7 @@ struct ipa_func_body_info > static inline int > ipa_get_param_count (struct ipa_node_params *info) > { > - return info->descriptors.length (); > + return vec_safe_length (info->descriptors); > } > > /* Return the declaration of Ith formal parameter of the function corresponding > @@ -428,8 +426,9 @@ ipa_get_param_count (struct ipa_node_params *info) > static inline tree > ipa_get_param (struct ipa_node_params *info, int i) > { > + gcc_checking_assert (info->descriptors); > gcc_checking_assert (!flag_wpa); > - tree t = info->descriptors[i].decl_or_type; > + tree t = (*info->descriptors)[i].decl_or_type; > gcc_checking_assert (TREE_CODE (t) == PARM_DECL); > return t; > } > @@ -440,7 +439,8 @@ ipa_get_param (struct ipa_node_params *info, int i) > static inline tree > ipa_get_type (struct ipa_node_params *info, int i) > { > - tree t = info->descriptors[i].decl_or_type; > + gcc_checking_assert (info->descriptors); > + tree t = (*info->descriptors)[i].decl_or_type; > if (!t) > return NULL; > if (TYPE_P (t)) > @@ -455,7 +455,8 @@ ipa_get_type (struct ipa_node_params *info, int i) > static inline int > ipa_get_param_move_cost (struct ipa_node_params *info, int i) > { > - return info->descriptors[i].move_cost; > + gcc_checking_assert (info->descriptors); > + return (*info->descriptors)[i].move_cost; > } > > /* Set the used flag corresponding to the Ith formal parameter of the function > @@ -464,7 +465,8 @@ ipa_get_param_move_cost (struct ipa_node_params *info, int i) > static inline void > ipa_set_param_used (struct ipa_node_params *info, int i, bool val) > { > - info->descriptors[i].used = val; > + gcc_checking_assert (info->descriptors); > + (*info->descriptors)[i].used = val; > } > > /* Return how many uses described by ipa-prop a parameter has or > @@ -473,9 +475,9 @@ ipa_set_param_used (struct ipa_node_params *info, int i, bool val) > static inline int > ipa_get_controlled_uses (struct ipa_node_params *info, int i) > { > - /* FIXME: introducing speuclation causes out of bounds access here. */ > - if (info->descriptors.length () > (unsigned)i) > - return info->descriptors[i].controlled_uses; > + /* FIXME: introducing speculation causes out of bounds access here. */ > + if (vec_safe_length (info->descriptors) > (unsigned)i) > + return (*info->descriptors)[i].controlled_uses; > return IPA_UNDESCRIBED_USE; > } > > @@ -484,7 +486,8 @@ ipa_get_controlled_uses (struct ipa_node_params *info, int i) > static inline void > ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) > { > - info->descriptors[i].controlled_uses = val; > + gcc_checking_assert (info->descriptors); > + (*info->descriptors)[i].controlled_uses = val; > } > > /* Return the used flag corresponding to the Ith formal parameter of the > @@ -493,7 +496,8 @@ ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) > static inline bool > ipa_is_param_used (struct ipa_node_params *info, int i) > { > - return info->descriptors[i].used; > + gcc_checking_assert (info->descriptors); > + return (*info->descriptors)[i].used; > } > > /* Information about replacements done in aggregates for a given node (each > @@ -569,12 +573,16 @@ ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i) > } > > /* Function summary for ipa_node_params. */ > -class ipa_node_params_t: public function_summary <ipa_node_params *> > +class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *> > { > public: > - ipa_node_params_t (symbol_table *table): > - function_summary<ipa_node_params *> (table) { } > + ipa_node_params_t (symbol_table *table, bool ggc): > + function_summary<ipa_node_params *> (table, ggc) { } > > + /* Hook that is called by summary when a node is deleted. */ > + virtual void insert (cgraph_node *, ipa_node_params *info); > + /* Hook that is called by summary when a node is deleted. */ > + virtual void remove (cgraph_node *, ipa_node_params *info); > /* Hook that is called by summary when a node is duplicated. */ > virtual void duplicate (cgraph_node *node, > cgraph_node *node2, > @@ -583,12 +591,14 @@ public: > }; > > /* Function summary where the parameter infos are actually stored. */ > -extern ipa_node_params_t *ipa_node_params_sum; > +extern GTY(()) ipa_node_params_t * ipa_node_params_sum; > + > /* Vector of IPA-CP transformation data for each clone. */ > extern GTY(()) vec<ipcp_transformation_summary, va_gc> *ipcp_transformations; > /* Vector where the parameter infos are actually stored. */ > extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector; > > + > /* Return the associated parameter/argument info corresponding to the given > node/edge. */ > #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE)) > @@ -616,7 +626,9 @@ static inline void > ipa_check_create_node_params (void) > { > if (!ipa_node_params_sum) > - ipa_node_params_sum = new ipa_node_params_t (symtab); > + ipa_node_params_sum > + = (new (ggc_cleared_alloc <ipa_node_params_t> ()) > + ipa_node_params_t (symtab, true)); > } > > /* This function ensures the array of edge arguments infos is big enough to > @@ -680,7 +692,7 @@ tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, tree scalar, > HOST_WIDE_INT offset, bool by_ref, > bool *from_global_constant = NULL); > bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt, tree op, int *index_p, > HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, > bool *by_ref, bool *guaranteed_unmodified = NULL); > diff --git a/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > new file mode 100644 > index 00000000000..58412afc3c8 > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > @@ -0,0 +1,14 @@ > +! { dg-lto-do link } > +! { dg-lto-options {{ -Ofast -flto --param ggc-min-expand=0 --param ggc-min-heapsize=0 }} } > +! { dg-extra-ld-options "-r -nostdlib" } > + > +MODULE Errorcheck_mod > +CONTAINS > +SUBROUTINE Check_open(ios, outputstr, errortype) > +character(len=*), intent(in) :: outputstr > +if (ios > 0 .AND. errortype == FATAL) then > + write(*,*) 'The value of ios was:', ios > +end if > +END SUBROUTINE Check_open > +END MODULE Errorcheck_mod > + > -- > 2.11.0 >
On Fri, Jan 20, 2017 at 10:58 PM, Martin Jambor <mjambor@suse.cz> wrote: > Hi, > > when I fixed PR 78365 by streaming types of parameters that might not > have been anywhere else, I forgot that I was holding them in non-GC > memory and so I caused PR 79108. The following patch fixes it by > putting ipa_param_descriptor and ipa_node_params structures into GC > memory, together with summary holding class ipa_node_params_t which is > now a GC root. In the process, I have turned the destructor of the > latter into a remove and insert hooks of the summary holder. > > Bootstrapped and tested on x86_64-linux, also LTO-bootstrapped and > tested, although with only C,C++ and Fortran and with sanitizers and > multilib disabled. (It is now a part of an undergoing LTO bootstrap > with everything). OK for trunk? Ok. Richard. > Thanks, > > Martin > > > 2017-01-19 Martin Jambor <mjambor@suse.cz> > > PR ipa/79108 > * ipa-prop.h (ipa_param_descriptor): Anotate with with GTY(()). > (ipa_node_params): Annotate with GTY((for_user)). Make descriptors > field a pointer to garbage collected vector, mark lattices and > ipcp_orig_node with GTY((skip)). > (ipa_get_param_count): Adjust to descriptors being a pointer. > (ipa_get_param): Likewise. > (ipa_get_type): Likewise. > (ipa_get_param_move_cost): Likewise. > (ipa_set_param_used): Likewise. > (ipa_get_controlled_uses): Likewise. > (ipa_set_controlled_uses): Likewise. > (ipa_is_param_used): Likewise. > (ipa_node_params_t): Move into garbage collector. New methods insert > and remove. > (ipa_node_params_sum): Annotate wth GTY(()). > (ipa_check_create_node_params): Adjust to ipa_node_params_sum being > garbage collected. > (ipa_load_from_parm_agg): Adjust declaration. > * ipa-icf.c (param_used_p): Adjust to descriptors being a pointer. > * ipa-profile.c (ipa_profile): Likewise. > * ipa-prop.c (ipa_get_param_decl_index_1): Likewise. > (ipa_populate_param_decls): Make descriptors parameter garbage > collected. > (ipa_dump_param): Adjust to descriptors being a pointer. > (ipa_alloc_node_params): Likewise. > (ipa_initialize_node_params): Likewise. > (load_from_param_1): Make descriptors parameter garbage collected. > (load_from_unmodified_param): Likewise. > (load_from_param): Likewise. > (ipa_load_from_parm_agg): Likewise. > (ipa_node_params::~ipa_node_params): Removed. > (ipa_free_all_node_params): Remove call to delete operator. > (ipa_node_params_t::insert): New. > (ipa_node_params_t::remove): Likewise. > (ipa_node_params_t::duplicate): Adjust to descriptors being a pointer, > copy known_csts and known_contexts vectors. > (ipa_read_node_info): Adjust to descriptors being a pointer. > (ipcp_modif_dom_walker): Make m_descriptors field garbage > collected. > (ipcp_transform_function): Make descriptors variable garbage > collected. > > testsuite/ > * gfortran.dg/lto/pr79108_0.f90: New test. > --- > gcc/ipa-icf.c | 5 +- > gcc/ipa-profile.c | 3 +- > gcc/ipa-prop.c | 101 +++++++++++++++------------- > gcc/ipa-prop.h | 62 ++++++++++------- > gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 | 14 ++++ > 5 files changed, 111 insertions(+), 74 deletions(-) > create mode 100644 gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > > diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c > index c17a677b459..b9a5b4f2546 100644 > --- a/gcc/ipa-icf.c > +++ b/gcc/ipa-icf.c > @@ -539,9 +539,8 @@ sem_function::param_used_p (unsigned int i) > > struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); > > - if (parms_info->descriptors.is_empty () > - || parms_info->descriptors.length () <= i) > - return true; > + if (vec_safe_length (parms_info->descriptors) <= i) > + return true; > > return ipa_is_param_used (IPA_NODE_REF (get_node ()), i); > } > diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c > index 3e9b2a915fc..ae1ca2f3762 100644 > --- a/gcc/ipa-profile.c > +++ b/gcc/ipa-profile.c > @@ -621,7 +621,8 @@ ipa_profile (void) > "and can be discarded.\n"); > } > else if (ipa_node_params_sum && ipa_edge_args_vector > - && !IPA_NODE_REF (n2)->descriptors.is_empty () > + && (!vec_safe_is_empty > + (IPA_NODE_REF (n2)->descriptors)) > && ipa_get_param_count (IPA_NODE_REF (n2)) > != ipa_get_cs_argument_count (IPA_EDGE_REF (e)) > && (ipa_get_param_count (IPA_NODE_REF (n2)) > diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c > index 1f68f736e46..4d77c9b25ef 100644 > --- a/gcc/ipa-prop.c > +++ b/gcc/ipa-prop.c > @@ -99,13 +99,14 @@ ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) > to INFO. */ > > static int > -ipa_get_param_decl_index_1 (vec<ipa_param_descriptor> descriptors, tree ptree) > +ipa_get_param_decl_index_1 (vec<ipa_param_descriptor, va_gc> *descriptors, > + tree ptree) > { > int i, count; > > - count = descriptors.length (); > + count = vec_safe_length (descriptors); > for (i = 0; i < count; i++) > - if (descriptors[i].decl_or_type == ptree) > + if ((*descriptors)[i].decl_or_type == ptree) > return i; > > return -1; > @@ -125,7 +126,7 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) > > static void > ipa_populate_param_decls (struct cgraph_node *node, > - vec<ipa_param_descriptor> &descriptors) > + vec<ipa_param_descriptor, va_gc> &descriptors) > { > tree fndecl; > tree fnargs; > @@ -168,10 +169,10 @@ void > ipa_dump_param (FILE *file, struct ipa_node_params *info, int i) > { > fprintf (file, "param #%i", i); > - if (info->descriptors[i].decl_or_type) > + if ((*info->descriptors)[i].decl_or_type) > { > fprintf (file, " "); > - print_generic_expr (file, info->descriptors[i].decl_or_type, 0); > + print_generic_expr (file, (*info->descriptors)[i].decl_or_type, 0); > } > } > > @@ -183,8 +184,8 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count) > { > struct ipa_node_params *info = IPA_NODE_REF (node); > > - if (!info->descriptors.exists () && param_count) > - info->descriptors.safe_grow_cleared (param_count); > + if (!info->descriptors && param_count) > + vec_safe_grow_cleared (info->descriptors, param_count); > } > > /* Initialize the ipa_node_params structure associated with NODE by counting > @@ -196,10 +197,10 @@ ipa_initialize_node_params (struct cgraph_node *node) > { > struct ipa_node_params *info = IPA_NODE_REF (node); > > - if (!info->descriptors.exists ()) > + if (!info->descriptors) > { > ipa_alloc_node_params (node, count_formal_params (node->decl)); > - ipa_populate_param_decls (node, info->descriptors); > + ipa_populate_param_decls (node, *info->descriptors); > } > } > > @@ -867,7 +868,7 @@ parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index, > > static int > load_from_param_1 (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > int index; > @@ -892,7 +893,7 @@ load_from_param_1 (struct ipa_func_body_info *fbi, > > static int > load_from_unmodified_param (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > if (!gimple_assign_single_p (stmt)) > @@ -906,7 +907,7 @@ load_from_unmodified_param (struct ipa_func_body_info *fbi, > > static int > load_from_param (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt) > { > if (!is_gimple_assign (stmt)) > @@ -1010,7 +1011,7 @@ parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index, > > bool > ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt, tree op, int *index_p, > HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, > bool *by_ref_p, bool *guaranteed_unmodified) > @@ -3604,33 +3605,11 @@ ipa_free_all_edge_args (void) > vec_free (ipa_edge_args_vector); > } > > -/* Frees all dynamically allocated structures that the param info points > - to. */ > - > -ipa_node_params::~ipa_node_params () > -{ > - descriptors.release (); > - free (lattices); > - /* Lattice values and their sources are deallocated with their alocation > - pool. */ > - known_csts.release (); > - known_contexts.release (); > - > - lattices = NULL; > - ipcp_orig_node = NULL; > - analysis_done = 0; > - node_enqueued = 0; > - do_clone_for_all_contexts = 0; > - is_all_contexts_clone = 0; > - node_dead = 0; > -} > - > /* Free all ipa_node_params structures. */ > > void > ipa_free_all_node_params (void) > { > - delete ipa_node_params_sum; > ipa_node_params_sum = NULL; > } > > @@ -3792,6 +3771,36 @@ ipa_add_new_function (cgraph_node *node, void *data ATTRIBUTE_UNUSED) > ipa_analyze_node (node); > } > > +/* Initialize a newly created param info. */ > + > +void > +ipa_node_params_t::insert (cgraph_node *, ipa_node_params *info) > +{ > + info->lattices = NULL; > + info->ipcp_orig_node = NULL; > + info->analysis_done = 0; > + info->node_enqueued = 0; > + info->do_clone_for_all_contexts = 0; > + info->is_all_contexts_clone = 0; > + info->node_dead = 0; > + info->node_within_scc = 0; > + info->node_calling_single_call = 0; > + info->versionable = 0; > +} > + > +/* Frees all dynamically allocated structures that the param info points > + to. */ > + > +void > +ipa_node_params_t::remove (cgraph_node *, ipa_node_params *info) > +{ > + free (info->lattices); > + /* Lattice values and their sources are deallocated with their alocation > + pool. */ > + info->known_csts.release (); > + info->known_contexts.release (); > +} > + > /* Hook that is called by summary when a node is duplicated. */ > > void > @@ -3801,9 +3810,11 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst, > { > ipa_agg_replacement_value *old_av, *new_av; > > - new_info->descriptors = old_info->descriptors.copy (); > + new_info->descriptors = vec_safe_copy (old_info->descriptors); > new_info->lattices = NULL; > new_info->ipcp_orig_node = old_info->ipcp_orig_node; > + new_info->known_csts = old_info->known_csts.copy (); > + new_info->known_contexts = old_info->known_contexts.copy (); > > new_info->analysis_done = old_info->analysis_done; > new_info->node_enqueued = old_info->node_enqueued; > @@ -5022,7 +5033,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, > ipa_alloc_node_params (node, streamer_read_uhwi (ib)); > > for (k = 0; k < ipa_get_param_count (info); k++) > - info->descriptors[k].move_cost = streamer_read_uhwi (ib); > + (*info->descriptors)[k].move_cost = streamer_read_uhwi (ib); > > bp = streamer_read_bitpack (ib); > if (ipa_get_param_count (info) != 0) > @@ -5033,7 +5044,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, > for (k = 0; k < ipa_get_param_count (info); k++) > { > ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); > - info->descriptors[k].decl_or_type = stream_read_tree (ib, data_in); > + (*info->descriptors)[k].decl_or_type = stream_read_tree (ib, data_in); > } > for (e = node->callees; e; e = e->next_callee) > { > @@ -5483,7 +5494,7 @@ class ipcp_modif_dom_walker : public dom_walker > { > public: > ipcp_modif_dom_walker (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descs, > + vec<ipa_param_descriptor, va_gc> *descs, > struct ipa_agg_replacement_value *av, > bool *sc, bool *cc) > : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs), > @@ -5493,7 +5504,7 @@ public: > > private: > struct ipa_func_body_info *m_fbi; > - vec<ipa_param_descriptor> m_descriptors; > + vec<ipa_param_descriptor, va_gc> *m_descriptors; > struct ipa_agg_replacement_value *m_aggval; > bool *m_something_changed, *m_cfg_changed; > }; > @@ -5751,7 +5762,7 @@ ipcp_update_vr (struct cgraph_node *node) > unsigned int > ipcp_transform_function (struct cgraph_node *node) > { > - vec<ipa_param_descriptor> descriptors = vNULL; > + vec<ipa_param_descriptor, va_gc> *descriptors = NULL; > struct ipa_func_body_info fbi; > struct ipa_agg_replacement_value *aggval; > int param_count; > @@ -5783,8 +5794,8 @@ ipcp_transform_function (struct cgraph_node *node) > fbi.param_count = param_count; > fbi.aa_walked = 0; > > - descriptors.safe_grow_cleared (param_count); > - ipa_populate_param_decls (node, descriptors); > + vec_safe_grow_cleared (descriptors, param_count); > + ipa_populate_param_decls (node, *descriptors); > calculate_dominance_info (CDI_DOMINATORS); > ipcp_modif_dom_walker (&fbi, descriptors, aggval, &something_changed, > &cfg_changed).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); > @@ -5799,7 +5810,7 @@ ipcp_transform_function (struct cgraph_node *node) > (*ipcp_transformations)[node->uid].bits = NULL; > (*ipcp_transformations)[node->uid].m_vr = NULL; > > - descriptors.release (); > + vec_free (descriptors); > > if (!something_changed) > return 0; > diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h > index c9a69ab1f53..93a2390c321 100644 > --- a/gcc/ipa-prop.h > +++ b/gcc/ipa-prop.h > @@ -298,7 +298,7 @@ ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc) > > /* Summary describing a single formal parameter. */ > > -struct ipa_param_descriptor > +struct GTY(()) ipa_param_descriptor > { > /* In analysis and modification phase, this is the PARAM_DECL of this > parameter, in IPA LTO phase, this is the type of the the described > @@ -318,25 +318,23 @@ struct ipa_param_descriptor > and some other information for interprocedural passes that operate on > parameters (such as ipa-cp). */ > > -struct ipa_node_params > +struct GTY((for_user)) ipa_node_params > { > - ~ipa_node_params (); > - > /* Information about individual formal parameters that are gathered when > summaries are generated. */ > - vec<ipa_param_descriptor> descriptors; > + vec<ipa_param_descriptor, va_gc> *descriptors; > /* Pointer to an array of structures describing individual formal > parameters. */ > - struct ipcp_param_lattices *lattices; > + struct ipcp_param_lattices * GTY((skip)) lattices; > /* Only for versioned nodes this field would not be NULL, > it points to the node that IPA cp cloned from. */ > - struct cgraph_node *ipcp_orig_node; > + struct cgraph_node * GTY((skip)) ipcp_orig_node; > /* If this node is an ipa-cp clone, these are the known constants that > describe what it has been specialized for. */ > - vec<tree> known_csts; > + vec<tree> GTY((skip)) known_csts; > /* If this node is an ipa-cp clone, these are the known polymorphic contexts > that describe what it has been specialized for. */ > - vec<ipa_polymorphic_call_context> known_contexts; > + vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts; > /* Whether the param uses analysis and jump function computation has already > been performed. */ > unsigned analysis_done : 1; > @@ -417,7 +415,7 @@ struct ipa_func_body_info > static inline int > ipa_get_param_count (struct ipa_node_params *info) > { > - return info->descriptors.length (); > + return vec_safe_length (info->descriptors); > } > > /* Return the declaration of Ith formal parameter of the function corresponding > @@ -428,8 +426,9 @@ ipa_get_param_count (struct ipa_node_params *info) > static inline tree > ipa_get_param (struct ipa_node_params *info, int i) > { > + gcc_checking_assert (info->descriptors); > gcc_checking_assert (!flag_wpa); > - tree t = info->descriptors[i].decl_or_type; > + tree t = (*info->descriptors)[i].decl_or_type; > gcc_checking_assert (TREE_CODE (t) == PARM_DECL); > return t; > } > @@ -440,7 +439,8 @@ ipa_get_param (struct ipa_node_params *info, int i) > static inline tree > ipa_get_type (struct ipa_node_params *info, int i) > { > - tree t = info->descriptors[i].decl_or_type; > + gcc_checking_assert (info->descriptors); > + tree t = (*info->descriptors)[i].decl_or_type; > if (!t) > return NULL; > if (TYPE_P (t)) > @@ -455,7 +455,8 @@ ipa_get_type (struct ipa_node_params *info, int i) > static inline int > ipa_get_param_move_cost (struct ipa_node_params *info, int i) > { > - return info->descriptors[i].move_cost; > + gcc_checking_assert (info->descriptors); > + return (*info->descriptors)[i].move_cost; > } > > /* Set the used flag corresponding to the Ith formal parameter of the function > @@ -464,7 +465,8 @@ ipa_get_param_move_cost (struct ipa_node_params *info, int i) > static inline void > ipa_set_param_used (struct ipa_node_params *info, int i, bool val) > { > - info->descriptors[i].used = val; > + gcc_checking_assert (info->descriptors); > + (*info->descriptors)[i].used = val; > } > > /* Return how many uses described by ipa-prop a parameter has or > @@ -473,9 +475,9 @@ ipa_set_param_used (struct ipa_node_params *info, int i, bool val) > static inline int > ipa_get_controlled_uses (struct ipa_node_params *info, int i) > { > - /* FIXME: introducing speuclation causes out of bounds access here. */ > - if (info->descriptors.length () > (unsigned)i) > - return info->descriptors[i].controlled_uses; > + /* FIXME: introducing speculation causes out of bounds access here. */ > + if (vec_safe_length (info->descriptors) > (unsigned)i) > + return (*info->descriptors)[i].controlled_uses; > return IPA_UNDESCRIBED_USE; > } > > @@ -484,7 +486,8 @@ ipa_get_controlled_uses (struct ipa_node_params *info, int i) > static inline void > ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) > { > - info->descriptors[i].controlled_uses = val; > + gcc_checking_assert (info->descriptors); > + (*info->descriptors)[i].controlled_uses = val; > } > > /* Return the used flag corresponding to the Ith formal parameter of the > @@ -493,7 +496,8 @@ ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) > static inline bool > ipa_is_param_used (struct ipa_node_params *info, int i) > { > - return info->descriptors[i].used; > + gcc_checking_assert (info->descriptors); > + return (*info->descriptors)[i].used; > } > > /* Information about replacements done in aggregates for a given node (each > @@ -569,12 +573,16 @@ ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i) > } > > /* Function summary for ipa_node_params. */ > -class ipa_node_params_t: public function_summary <ipa_node_params *> > +class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *> > { > public: > - ipa_node_params_t (symbol_table *table): > - function_summary<ipa_node_params *> (table) { } > + ipa_node_params_t (symbol_table *table, bool ggc): > + function_summary<ipa_node_params *> (table, ggc) { } > > + /* Hook that is called by summary when a node is deleted. */ > + virtual void insert (cgraph_node *, ipa_node_params *info); > + /* Hook that is called by summary when a node is deleted. */ > + virtual void remove (cgraph_node *, ipa_node_params *info); > /* Hook that is called by summary when a node is duplicated. */ > virtual void duplicate (cgraph_node *node, > cgraph_node *node2, > @@ -583,12 +591,14 @@ public: > }; > > /* Function summary where the parameter infos are actually stored. */ > -extern ipa_node_params_t *ipa_node_params_sum; > +extern GTY(()) ipa_node_params_t * ipa_node_params_sum; > + > /* Vector of IPA-CP transformation data for each clone. */ > extern GTY(()) vec<ipcp_transformation_summary, va_gc> *ipcp_transformations; > /* Vector where the parameter infos are actually stored. */ > extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector; > > + > /* Return the associated parameter/argument info corresponding to the given > node/edge. */ > #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE)) > @@ -616,7 +626,9 @@ static inline void > ipa_check_create_node_params (void) > { > if (!ipa_node_params_sum) > - ipa_node_params_sum = new ipa_node_params_t (symtab); > + ipa_node_params_sum > + = (new (ggc_cleared_alloc <ipa_node_params_t> ()) > + ipa_node_params_t (symtab, true)); > } > > /* This function ensures the array of edge arguments infos is big enough to > @@ -680,7 +692,7 @@ tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, tree scalar, > HOST_WIDE_INT offset, bool by_ref, > bool *from_global_constant = NULL); > bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, > - vec<ipa_param_descriptor> descriptors, > + vec<ipa_param_descriptor, va_gc> *descriptors, > gimple *stmt, tree op, int *index_p, > HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, > bool *by_ref, bool *guaranteed_unmodified = NULL); > diff --git a/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > new file mode 100644 > index 00000000000..58412afc3c8 > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 > @@ -0,0 +1,14 @@ > +! { dg-lto-do link } > +! { dg-lto-options {{ -Ofast -flto --param ggc-min-expand=0 --param ggc-min-heapsize=0 }} } > +! { dg-extra-ld-options "-r -nostdlib" } > + > +MODULE Errorcheck_mod > +CONTAINS > +SUBROUTINE Check_open(ios, outputstr, errortype) > +character(len=*), intent(in) :: outputstr > +if (ios > 0 .AND. errortype == FATAL) then > + write(*,*) 'The value of ios was:', ios > +end if > +END SUBROUTINE Check_open > +END MODULE Errorcheck_mod > + > -- > 2.11.0 >
Hi Martin, > when I fixed PR 78365 by streaming types of parameters that might not > have been anywhere else, I forgot that I was holding them in non-GC > memory and so I caused PR 79108. The following patch fixes it by > putting ipa_param_descriptor and ipa_node_params structures into GC > memory, together with summary holding class ipa_node_params_t which is > now a GC root. In the process, I have turned the destructor of the > latter into a remove and insert hooks of the summary holder. > > Bootstrapped and tested on x86_64-linux, also LTO-bootstrapped and > tested, although with only C,C++ and Fortran and with sanitizers and > multilib disabled. (It is now a part of an undergoing LTO bootstrap > with everything). OK for trunk? this broke bootstrap on i386-pc-solaris2.12, sparc-sun-solaris2.12, and i686-pc-linux-gnu (probably every 32-bit host), as confirmed by an i386-pc-solaris2.10 reghunt. E.g. in the Linux/i686 bootstrap, compiling tree-ssa-math-opts.o fails with virtual memory exhausted: Cannot allocate memory In the Solaris cases, various libstdc++ source files fail to compile in the same way. Rainer
Hi, On Mon, Jan 23, 2017 at 11:05:03PM +0100, Rainer Orth wrote: > Hi Martin, > > > when I fixed PR 78365 by streaming types of parameters that might not > > have been anywhere else, I forgot that I was holding them in non-GC > > memory and so I caused PR 79108. The following patch fixes it by > > putting ipa_param_descriptor and ipa_node_params structures into GC > > memory, together with summary holding class ipa_node_params_t which is > > now a GC root. In the process, I have turned the destructor of the > > latter into a remove and insert hooks of the summary holder. > > > > Bootstrapped and tested on x86_64-linux, also LTO-bootstrapped and > > tested, although with only C,C++ and Fortran and with sanitizers and > > multilib disabled. (It is now a part of an undergoing LTO bootstrap > > with everything). OK for trunk? > > this broke bootstrap on i386-pc-solaris2.12, sparc-sun-solaris2.12, and > i686-pc-linux-gnu (probably every 32-bit host), as confirmed by an > i386-pc-solaris2.10 reghunt. > > E.g. in the Linux/i686 bootstrap, compiling tree-ssa-math-opts.o fails > with > > virtual memory exhausted: Cannot allocate memory > > In the Solaris cases, various libstdc++ source files fail to compile in > the same way. > > Rainer > This is most likely PR 79198 for which I have just committed a fix. Please let me know if any issues persist. Thanks, Martin
Hi Martin, >> this broke bootstrap on i386-pc-solaris2.12, sparc-sun-solaris2.12, and >> i686-pc-linux-gnu (probably every 32-bit host), as confirmed by an >> i386-pc-solaris2.10 reghunt. >> >> E.g. in the Linux/i686 bootstrap, compiling tree-ssa-math-opts.o fails >> with >> >> virtual memory exhausted: Cannot allocate memory >> >> In the Solaris cases, various libstdc++ source files fail to compile in >> the same way. > > This is most likely PR 79198 for which I have just committed a fix. it was: was both sparc-sun-solaris2.12 and i386-pc-solaris2.12 bootstraps are back to normal again. Thanks. Rainer
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index c17a677b459..b9a5b4f2546 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -539,9 +539,8 @@ sem_function::param_used_p (unsigned int i) struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ()); - if (parms_info->descriptors.is_empty () - || parms_info->descriptors.length () <= i) - return true; + if (vec_safe_length (parms_info->descriptors) <= i) + return true; return ipa_is_param_used (IPA_NODE_REF (get_node ()), i); } diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index 3e9b2a915fc..ae1ca2f3762 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -621,7 +621,8 @@ ipa_profile (void) "and can be discarded.\n"); } else if (ipa_node_params_sum && ipa_edge_args_vector - && !IPA_NODE_REF (n2)->descriptors.is_empty () + && (!vec_safe_is_empty + (IPA_NODE_REF (n2)->descriptors)) && ipa_get_param_count (IPA_NODE_REF (n2)) != ipa_get_cs_argument_count (IPA_EDGE_REF (e)) && (ipa_get_param_count (IPA_NODE_REF (n2)) diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 1f68f736e46..4d77c9b25ef 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -99,13 +99,14 @@ ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) to INFO. */ static int -ipa_get_param_decl_index_1 (vec<ipa_param_descriptor> descriptors, tree ptree) +ipa_get_param_decl_index_1 (vec<ipa_param_descriptor, va_gc> *descriptors, + tree ptree) { int i, count; - count = descriptors.length (); + count = vec_safe_length (descriptors); for (i = 0; i < count; i++) - if (descriptors[i].decl_or_type == ptree) + if ((*descriptors)[i].decl_or_type == ptree) return i; return -1; @@ -125,7 +126,7 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) static void ipa_populate_param_decls (struct cgraph_node *node, - vec<ipa_param_descriptor> &descriptors) + vec<ipa_param_descriptor, va_gc> &descriptors) { tree fndecl; tree fnargs; @@ -168,10 +169,10 @@ void ipa_dump_param (FILE *file, struct ipa_node_params *info, int i) { fprintf (file, "param #%i", i); - if (info->descriptors[i].decl_or_type) + if ((*info->descriptors)[i].decl_or_type) { fprintf (file, " "); - print_generic_expr (file, info->descriptors[i].decl_or_type, 0); + print_generic_expr (file, (*info->descriptors)[i].decl_or_type, 0); } } @@ -183,8 +184,8 @@ ipa_alloc_node_params (struct cgraph_node *node, int param_count) { struct ipa_node_params *info = IPA_NODE_REF (node); - if (!info->descriptors.exists () && param_count) - info->descriptors.safe_grow_cleared (param_count); + if (!info->descriptors && param_count) + vec_safe_grow_cleared (info->descriptors, param_count); } /* Initialize the ipa_node_params structure associated with NODE by counting @@ -196,10 +197,10 @@ ipa_initialize_node_params (struct cgraph_node *node) { struct ipa_node_params *info = IPA_NODE_REF (node); - if (!info->descriptors.exists ()) + if (!info->descriptors) { ipa_alloc_node_params (node, count_formal_params (node->decl)); - ipa_populate_param_decls (node, info->descriptors); + ipa_populate_param_decls (node, *info->descriptors); } } @@ -867,7 +868,7 @@ parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index, static int load_from_param_1 (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descriptors, + vec<ipa_param_descriptor, va_gc> *descriptors, gimple *stmt) { int index; @@ -892,7 +893,7 @@ load_from_param_1 (struct ipa_func_body_info *fbi, static int load_from_unmodified_param (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descriptors, + vec<ipa_param_descriptor, va_gc> *descriptors, gimple *stmt) { if (!gimple_assign_single_p (stmt)) @@ -906,7 +907,7 @@ load_from_unmodified_param (struct ipa_func_body_info *fbi, static int load_from_param (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descriptors, + vec<ipa_param_descriptor, va_gc> *descriptors, gimple *stmt) { if (!is_gimple_assign (stmt)) @@ -1010,7 +1011,7 @@ parm_ref_data_pass_through_p (struct ipa_func_body_info *fbi, int index, bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descriptors, + vec<ipa_param_descriptor, va_gc> *descriptors, gimple *stmt, tree op, int *index_p, HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, bool *by_ref_p, bool *guaranteed_unmodified) @@ -3604,33 +3605,11 @@ ipa_free_all_edge_args (void) vec_free (ipa_edge_args_vector); } -/* Frees all dynamically allocated structures that the param info points - to. */ - -ipa_node_params::~ipa_node_params () -{ - descriptors.release (); - free (lattices); - /* Lattice values and their sources are deallocated with their alocation - pool. */ - known_csts.release (); - known_contexts.release (); - - lattices = NULL; - ipcp_orig_node = NULL; - analysis_done = 0; - node_enqueued = 0; - do_clone_for_all_contexts = 0; - is_all_contexts_clone = 0; - node_dead = 0; -} - /* Free all ipa_node_params structures. */ void ipa_free_all_node_params (void) { - delete ipa_node_params_sum; ipa_node_params_sum = NULL; } @@ -3792,6 +3771,36 @@ ipa_add_new_function (cgraph_node *node, void *data ATTRIBUTE_UNUSED) ipa_analyze_node (node); } +/* Initialize a newly created param info. */ + +void +ipa_node_params_t::insert (cgraph_node *, ipa_node_params *info) +{ + info->lattices = NULL; + info->ipcp_orig_node = NULL; + info->analysis_done = 0; + info->node_enqueued = 0; + info->do_clone_for_all_contexts = 0; + info->is_all_contexts_clone = 0; + info->node_dead = 0; + info->node_within_scc = 0; + info->node_calling_single_call = 0; + info->versionable = 0; +} + +/* Frees all dynamically allocated structures that the param info points + to. */ + +void +ipa_node_params_t::remove (cgraph_node *, ipa_node_params *info) +{ + free (info->lattices); + /* Lattice values and their sources are deallocated with their alocation + pool. */ + info->known_csts.release (); + info->known_contexts.release (); +} + /* Hook that is called by summary when a node is duplicated. */ void @@ -3801,9 +3810,11 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst, { ipa_agg_replacement_value *old_av, *new_av; - new_info->descriptors = old_info->descriptors.copy (); + new_info->descriptors = vec_safe_copy (old_info->descriptors); new_info->lattices = NULL; new_info->ipcp_orig_node = old_info->ipcp_orig_node; + new_info->known_csts = old_info->known_csts.copy (); + new_info->known_contexts = old_info->known_contexts.copy (); new_info->analysis_done = old_info->analysis_done; new_info->node_enqueued = old_info->node_enqueued; @@ -5022,7 +5033,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, ipa_alloc_node_params (node, streamer_read_uhwi (ib)); for (k = 0; k < ipa_get_param_count (info); k++) - info->descriptors[k].move_cost = streamer_read_uhwi (ib); + (*info->descriptors)[k].move_cost = streamer_read_uhwi (ib); bp = streamer_read_bitpack (ib); if (ipa_get_param_count (info) != 0) @@ -5033,7 +5044,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, for (k = 0; k < ipa_get_param_count (info); k++) { ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); - info->descriptors[k].decl_or_type = stream_read_tree (ib, data_in); + (*info->descriptors)[k].decl_or_type = stream_read_tree (ib, data_in); } for (e = node->callees; e; e = e->next_callee) { @@ -5483,7 +5494,7 @@ class ipcp_modif_dom_walker : public dom_walker { public: ipcp_modif_dom_walker (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descs, + vec<ipa_param_descriptor, va_gc> *descs, struct ipa_agg_replacement_value *av, bool *sc, bool *cc) : dom_walker (CDI_DOMINATORS), m_fbi (fbi), m_descriptors (descs), @@ -5493,7 +5504,7 @@ public: private: struct ipa_func_body_info *m_fbi; - vec<ipa_param_descriptor> m_descriptors; + vec<ipa_param_descriptor, va_gc> *m_descriptors; struct ipa_agg_replacement_value *m_aggval; bool *m_something_changed, *m_cfg_changed; }; @@ -5751,7 +5762,7 @@ ipcp_update_vr (struct cgraph_node *node) unsigned int ipcp_transform_function (struct cgraph_node *node) { - vec<ipa_param_descriptor> descriptors = vNULL; + vec<ipa_param_descriptor, va_gc> *descriptors = NULL; struct ipa_func_body_info fbi; struct ipa_agg_replacement_value *aggval; int param_count; @@ -5783,8 +5794,8 @@ ipcp_transform_function (struct cgraph_node *node) fbi.param_count = param_count; fbi.aa_walked = 0; - descriptors.safe_grow_cleared (param_count); - ipa_populate_param_decls (node, descriptors); + vec_safe_grow_cleared (descriptors, param_count); + ipa_populate_param_decls (node, *descriptors); calculate_dominance_info (CDI_DOMINATORS); ipcp_modif_dom_walker (&fbi, descriptors, aggval, &something_changed, &cfg_changed).walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); @@ -5799,7 +5810,7 @@ ipcp_transform_function (struct cgraph_node *node) (*ipcp_transformations)[node->uid].bits = NULL; (*ipcp_transformations)[node->uid].m_vr = NULL; - descriptors.release (); + vec_free (descriptors); if (!something_changed) return 0; diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index c9a69ab1f53..93a2390c321 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -298,7 +298,7 @@ ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc) /* Summary describing a single formal parameter. */ -struct ipa_param_descriptor +struct GTY(()) ipa_param_descriptor { /* In analysis and modification phase, this is the PARAM_DECL of this parameter, in IPA LTO phase, this is the type of the the described @@ -318,25 +318,23 @@ struct ipa_param_descriptor and some other information for interprocedural passes that operate on parameters (such as ipa-cp). */ -struct ipa_node_params +struct GTY((for_user)) ipa_node_params { - ~ipa_node_params (); - /* Information about individual formal parameters that are gathered when summaries are generated. */ - vec<ipa_param_descriptor> descriptors; + vec<ipa_param_descriptor, va_gc> *descriptors; /* Pointer to an array of structures describing individual formal parameters. */ - struct ipcp_param_lattices *lattices; + struct ipcp_param_lattices * GTY((skip)) lattices; /* Only for versioned nodes this field would not be NULL, it points to the node that IPA cp cloned from. */ - struct cgraph_node *ipcp_orig_node; + struct cgraph_node * GTY((skip)) ipcp_orig_node; /* If this node is an ipa-cp clone, these are the known constants that describe what it has been specialized for. */ - vec<tree> known_csts; + vec<tree> GTY((skip)) known_csts; /* If this node is an ipa-cp clone, these are the known polymorphic contexts that describe what it has been specialized for. */ - vec<ipa_polymorphic_call_context> known_contexts; + vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts; /* Whether the param uses analysis and jump function computation has already been performed. */ unsigned analysis_done : 1; @@ -417,7 +415,7 @@ struct ipa_func_body_info static inline int ipa_get_param_count (struct ipa_node_params *info) { - return info->descriptors.length (); + return vec_safe_length (info->descriptors); } /* Return the declaration of Ith formal parameter of the function corresponding @@ -428,8 +426,9 @@ ipa_get_param_count (struct ipa_node_params *info) static inline tree ipa_get_param (struct ipa_node_params *info, int i) { + gcc_checking_assert (info->descriptors); gcc_checking_assert (!flag_wpa); - tree t = info->descriptors[i].decl_or_type; + tree t = (*info->descriptors)[i].decl_or_type; gcc_checking_assert (TREE_CODE (t) == PARM_DECL); return t; } @@ -440,7 +439,8 @@ ipa_get_param (struct ipa_node_params *info, int i) static inline tree ipa_get_type (struct ipa_node_params *info, int i) { - tree t = info->descriptors[i].decl_or_type; + gcc_checking_assert (info->descriptors); + tree t = (*info->descriptors)[i].decl_or_type; if (!t) return NULL; if (TYPE_P (t)) @@ -455,7 +455,8 @@ ipa_get_type (struct ipa_node_params *info, int i) static inline int ipa_get_param_move_cost (struct ipa_node_params *info, int i) { - return info->descriptors[i].move_cost; + gcc_checking_assert (info->descriptors); + return (*info->descriptors)[i].move_cost; } /* Set the used flag corresponding to the Ith formal parameter of the function @@ -464,7 +465,8 @@ ipa_get_param_move_cost (struct ipa_node_params *info, int i) static inline void ipa_set_param_used (struct ipa_node_params *info, int i, bool val) { - info->descriptors[i].used = val; + gcc_checking_assert (info->descriptors); + (*info->descriptors)[i].used = val; } /* Return how many uses described by ipa-prop a parameter has or @@ -473,9 +475,9 @@ ipa_set_param_used (struct ipa_node_params *info, int i, bool val) static inline int ipa_get_controlled_uses (struct ipa_node_params *info, int i) { - /* FIXME: introducing speuclation causes out of bounds access here. */ - if (info->descriptors.length () > (unsigned)i) - return info->descriptors[i].controlled_uses; + /* FIXME: introducing speculation causes out of bounds access here. */ + if (vec_safe_length (info->descriptors) > (unsigned)i) + return (*info->descriptors)[i].controlled_uses; return IPA_UNDESCRIBED_USE; } @@ -484,7 +486,8 @@ ipa_get_controlled_uses (struct ipa_node_params *info, int i) static inline void ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) { - info->descriptors[i].controlled_uses = val; + gcc_checking_assert (info->descriptors); + (*info->descriptors)[i].controlled_uses = val; } /* Return the used flag corresponding to the Ith formal parameter of the @@ -493,7 +496,8 @@ ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val) static inline bool ipa_is_param_used (struct ipa_node_params *info, int i) { - return info->descriptors[i].used; + gcc_checking_assert (info->descriptors); + return (*info->descriptors)[i].used; } /* Information about replacements done in aggregates for a given node (each @@ -569,12 +573,16 @@ ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i) } /* Function summary for ipa_node_params. */ -class ipa_node_params_t: public function_summary <ipa_node_params *> +class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *> { public: - ipa_node_params_t (symbol_table *table): - function_summary<ipa_node_params *> (table) { } + ipa_node_params_t (symbol_table *table, bool ggc): + function_summary<ipa_node_params *> (table, ggc) { } + /* Hook that is called by summary when a node is deleted. */ + virtual void insert (cgraph_node *, ipa_node_params *info); + /* Hook that is called by summary when a node is deleted. */ + virtual void remove (cgraph_node *, ipa_node_params *info); /* Hook that is called by summary when a node is duplicated. */ virtual void duplicate (cgraph_node *node, cgraph_node *node2, @@ -583,12 +591,14 @@ public: }; /* Function summary where the parameter infos are actually stored. */ -extern ipa_node_params_t *ipa_node_params_sum; +extern GTY(()) ipa_node_params_t * ipa_node_params_sum; + /* Vector of IPA-CP transformation data for each clone. */ extern GTY(()) vec<ipcp_transformation_summary, va_gc> *ipcp_transformations; /* Vector where the parameter infos are actually stored. */ extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector; + /* Return the associated parameter/argument info corresponding to the given node/edge. */ #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE)) @@ -616,7 +626,9 @@ static inline void ipa_check_create_node_params (void) { if (!ipa_node_params_sum) - ipa_node_params_sum = new ipa_node_params_t (symtab); + ipa_node_params_sum + = (new (ggc_cleared_alloc <ipa_node_params_t> ()) + ipa_node_params_t (symtab, true)); } /* This function ensures the array of edge arguments infos is big enough to @@ -680,7 +692,7 @@ tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, tree scalar, HOST_WIDE_INT offset, bool by_ref, bool *from_global_constant = NULL); bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi, - vec<ipa_param_descriptor> descriptors, + vec<ipa_param_descriptor, va_gc> *descriptors, gimple *stmt, tree op, int *index_p, HOST_WIDE_INT *offset_p, HOST_WIDE_INT *size_p, bool *by_ref, bool *guaranteed_unmodified = NULL); diff --git a/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 new file mode 100644 index 00000000000..58412afc3c8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/lto/pr79108_0.f90 @@ -0,0 +1,14 @@ +! { dg-lto-do link } +! { dg-lto-options {{ -Ofast -flto --param ggc-min-expand=0 --param ggc-min-heapsize=0 }} } +! { dg-extra-ld-options "-r -nostdlib" } + +MODULE Errorcheck_mod +CONTAINS +SUBROUTINE Check_open(ios, outputstr, errortype) +character(len=*), intent(in) :: outputstr +if (ios > 0 .AND. errortype == FATAL) then + write(*,*) 'The value of ios was:', ios +end if +END SUBROUTINE Check_open +END MODULE Errorcheck_mod +