diff mbox

[PR,79108] Put ipa_node_params to GC memory

Message ID 20170120215807.yh7acd36yq4qd4ur@virgil.suse.cz
State New
Headers show

Commit Message

Martin Jambor Jan. 20, 2017, 9:58 p.m. UTC
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?

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

Comments

Andrew Pinski Jan. 21, 2017, 7:09 a.m. UTC | #1
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
>
Richard Biener Jan. 23, 2017, 9:52 a.m. UTC | #2
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
>
Rainer Orth Jan. 23, 2017, 10:05 p.m. UTC | #3
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
Martin Jambor Jan. 24, 2017, 10:06 a.m. UTC | #4
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
Rainer Orth Jan. 24, 2017, 2:25 p.m. UTC | #5
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 mbox

Patch

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
+