This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/N] Clean-up usage of ipa_fn_summary and ipa_call_summary summaries.


Hi.

This is first part of IPA summary conversion clean-up. It removes ::get_create and
uses ::get for ipa-inline related symbol (and call) summaries. I'm planning to
investigate also other summaries.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Martin

gcc/ChangeLog:

2018-06-15  Martin Liska  <mliska@suse.cz>

	* config/i386/i386.c (ix86_can_inline_p): Do not use
        ipa_fn_summaries::get_create.
	* ipa-cp.c (ipcp_cloning_candidate_p): Replace get_create with
        get.
	(devirtualization_time_bonus): Likewise.
	(ipcp_propagate_stage): Likewise.
	* ipa-fnsummary.c (redirect_to_unreachable): Likewise.
	(edge_set_predicate): Likewise.
	(evaluate_conditions_for_known_args): Likewise.
	(evaluate_properties_for_edge): Likewise.
	(ipa_call_summary::reset): Tranform to ...
	(ipa_call_summary::~ipa_call_summary): ... this.
	(ipa_fn_summary::reset): Transform to ...
	(ipa_fn_summary::~ipa_fn_summary): ... this.
	(ipa_fn_summary_t::remove): Rename to ...
	(ipa_fn_summary_t::remove_callees): ... this.
	(ipa_fn_summary_t::duplicate): Use placement new
        instead of memory copy.
	(ipa_call_summary_t::duplicate): Likewise.
	(ipa_call_summary_t::remove): Remove.
	(dump_ipa_call_summary): Change get_create to get.
	(ipa_dump_fn_summary): Dump only when summary exists.
	(analyze_function_body): Use symbol_summary::get instead
        of get_create.
	(compute_fn_summary): Likewise.
	(estimate_edge_devirt_benefit): Likewise.
	(estimate_edge_size_and_time): Likewise.
	(inline_update_callee_summaries): Likewise.
	(remap_edge_change_prob): Likewise.
	(remap_edge_summaries): Likewise.
	(ipa_merge_fn_summary_after_inlining): Likewise.
	(write_ipa_call_summary): Likewise.
	(ipa_fn_summary_write): Likewise.
	(ipa_free_fn_summary): Likewise.
	* ipa-fnsummary.h (struct GTY): Add new ctor and copy ctor.
	(struct ipa_call_summary): Likewise.
	* ipa-icf.c (sem_function::merge): Use symbol_summary::get instead
        of get_create.
	* ipa-inline-analysis.c (do_estimate_edge_time): Likewise.
	(estimate_size_after_inlining): Likewise.
	(estimate_growth): Likewise.
	(growth_likely_positive): Likewise.
	* ipa-inline-transform.c (clone_inlined_nodes): Likewise.
	(inline_call): Likewise.
	* ipa-inline.c (caller_growth_limits): Likewise.
	(can_inline_edge_p): Likewise.
	(can_inline_edge_by_limits_p): Likewise.
	(compute_uninlined_call_time): Likewise.
	(compute_inlined_call_time): Likewise.
	(want_inline_small_function_p): Likewise.
	(edge_badness): Likewise.
	(update_caller_keys): Likewise.
	(update_callee_keys): Likewise.
	(inline_small_functions): Likewise.
	(inline_to_all_callers_1): Likewise.
	(dump_overall_stats): Likewise.
	(early_inline_small_functions): Likewise.
	(early_inliner): Likewise.
	* ipa-profile.c (ipa_propagate_frequency_1): Likewise.
	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
	* ipa-pure-const.c (malloc_candidate_p): Likewise.
	* ipa-split.c (execute_split_functions): Likewise.
	* symbol-summary.h: Likewise.
	* tree-sra.c (ipa_sra_preliminary_function_checks): Likewise.

gcc/lto/ChangeLog:

2018-06-15  Martin Liska  <mliska@suse.cz>

	* lto-partition.c (add_symbol_to_partition_1): Use symbol_summary::get instead
        of get_create.
	(undo_partition): Likewise.
	(lto_balanced_map): Likewise.
---
 gcc/config/i386/i386.c     |   5 +-
 gcc/ipa-cp.c               |   9 +-
 gcc/ipa-fnsummary.c        | 248 ++++++++++++++++---------------------
 gcc/ipa-fnsummary.h        |  83 ++++++++-----
 gcc/ipa-icf.c              |   3 +-
 gcc/ipa-inline-analysis.c  |  10 +-
 gcc/ipa-inline-transform.c |  12 +-
 gcc/ipa-inline.c           |  82 ++++++------
 gcc/ipa-profile.c          |  25 ++--
 gcc/ipa-prop.c             |   3 +-
 gcc/ipa-pure-const.c       |   4 +-
 gcc/ipa-split.c            |   3 +-
 gcc/lto/lto-partition.c    |   6 +-
 gcc/symbol-summary.h       |  12 ++
 gcc/tree-sra.c             |   3 +-
 15 files changed, 262 insertions(+), 246 deletions(-)


diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 95cfa05ce61..a40ee0d1258 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5760,6 +5760,7 @@ ix86_can_inline_p (tree caller, tree callee)
       && lookup_attribute ("always_inline",
 			   DECL_ATTRIBUTES (callee)));
 
+  cgraph_node *callee_node = cgraph_node::get (callee);
   /* Callee's isa options should be a subset of the caller's, i.e. a SSE4
      function can inline a SSE2 function but a SSE2 function can't inline
      a SSE4 function.  */
@@ -5789,8 +5790,8 @@ ix86_can_inline_p (tree caller, tree callee)
 	      for multi-versioning call optimization, so beware of
 	      ipa_fn_summaries not available.  */
 	   && (! ipa_fn_summaries
-	       || ipa_fn_summaries->get_create
-	       (cgraph_node::get (callee))->fp_expressions))
+	       || ipa_fn_summaries->get (callee_node) == NULL
+	       || ipa_fn_summaries->get (callee_node)->fp_expressions))
     ret = false;
 
   else if (!always_inline
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 435c9ee1638..c192e84f452 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -736,7 +736,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
   init_caller_stats (&stats);
   node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false);
 
-  if (ipa_fn_summaries->get_create (node)->self_size < stats.n_calls)
+  if (ipa_fn_summaries->get (node)->self_size < stats.n_calls)
     {
       if (dump_file)
 	fprintf (dump_file, "Considering %s for cloning; code might shrink.\n",
@@ -2583,7 +2583,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
       callee = callee->function_symbol (&avail);
       if (avail < AVAIL_AVAILABLE)
 	continue;
-      isummary = ipa_fn_summaries->get_create (callee);
+      isummary = ipa_fn_summaries->get (callee);
       if (!isummary->inlinable)
 	continue;
 
@@ -3287,8 +3287,9 @@ ipcp_propagate_stage (struct ipa_topo_info *topo)
 				   ipa_get_param_count (info));
 	initialize_node_lattices (node);
       }
-    if (node->definition && !node->alias)
-      overall_size += ipa_fn_summaries->get_create (node)->self_size;
+    ipa_fn_summary *s = ipa_fn_summaries->get (node);
+    if (node->definition && !node->alias && s != NULL)
+      overall_size += s->self_size;
     max_count = max_count.max (node->count.ipa ());
   }
 
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index e40b537bf61..6061a470f38 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -241,7 +241,7 @@ redirect_to_unreachable (struct cgraph_edge *e)
     e->make_direct (target);
   else
     e->redirect_callee (target);
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+  struct ipa_call_summary *es = ipa_call_summaries->get (e);
   e->inline_failed = CIF_UNREACHABLE;
   e->count = profile_count::zero ();
   es->call_stmt_size = 0;
@@ -266,7 +266,7 @@ edge_set_predicate (struct cgraph_edge *e, predicate *predicate)
       && (!e->speculative || e->callee))
     e = redirect_to_unreachable (e);
 
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+  struct ipa_call_summary *es = ipa_call_summaries->get (e);
   if (predicate && *predicate != true)
     {
       if (!es->predicate)
@@ -328,7 +328,7 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
 {
   clause_t clause = inline_p ? 0 : 1 << predicate::not_inlined_condition;
   clause_t nonspec_clause = 1 << predicate::not_inlined_condition;
-  struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
+  struct ipa_fn_summary *info = ipa_fn_summaries->get (node);
   int i;
   struct condition *c;
 
@@ -428,7 +428,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
 			      vec<ipa_agg_jump_function_p> *known_aggs_ptr)
 {
   struct cgraph_node *callee = e->callee->ultimate_alias_target ();
-  struct ipa_fn_summary *info = ipa_fn_summaries->get_create (callee);
+  struct ipa_fn_summary *info = ipa_fn_summaries->get (callee);
   vec<tree> known_vals = vNULL;
   vec<ipa_agg_jump_function_p> known_aggs = vNULL;
 
@@ -445,7 +445,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p,
     {
       struct ipa_node_params *caller_parms_info, *callee_pi;
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+      struct ipa_call_summary *es = ipa_call_summaries->get (e);
       int i, count = ipa_get_cs_argument_count (args);
 
       if (e->caller->global.inlined_to)
@@ -535,66 +535,34 @@ ipa_fn_summary_alloc (void)
   ipa_call_summaries = new ipa_call_summary_t (symtab, false);
 }
 
-/* We are called multiple time for given function; clear
-   data from previous run so they are not cumulated.  */
-
-void
-ipa_call_summary::reset ()
+ipa_call_summary::~ipa_call_summary ()
 {
-  call_stmt_size = call_stmt_time = 0;
-  is_return_callee_uncaptured = false;
   if (predicate)
     edge_predicate_pool.remove (predicate);
-  predicate = NULL;
+
   param.release ();
 }
 
-/* We are called multiple time for given function; clear
-   data from previous run so they are not cumulated.  */
-
-void
-ipa_fn_summary::reset (struct cgraph_node *node)
+ipa_fn_summary::~ipa_fn_summary ()
 {
-  struct cgraph_edge *e;
-
-  self_size = 0;
-  estimated_stack_size = 0;
-  estimated_self_stack_size = 0;
-  stack_frame_offset = 0;
-  size = 0;
-  time = 0;
-  growth = 0;
-  scc_no = 0;
   if (loop_iterations)
-    {
-      edge_predicate_pool.remove (loop_iterations);
-      loop_iterations = NULL;
-    }
+    edge_predicate_pool.remove (loop_iterations);
   if (loop_stride)
-    {
-      edge_predicate_pool.remove (loop_stride);
-      loop_stride = NULL;
-    }
+    edge_predicate_pool.remove (loop_stride);
   if (array_index)
-    {
-      edge_predicate_pool.remove (array_index);
-      array_index = NULL;
-    }
+    edge_predicate_pool.remove (array_index);
   vec_free (conds);
   vec_free (size_time_table);
-  for (e = node->callees; e; e = e->next_callee)
-    ipa_call_summaries->get_create (e)->reset ();
-  for (e = node->indirect_calls; e; e = e->next_callee)
-    ipa_call_summaries->get_create (e)->reset ();
-  fp_expressions = false;
 }
 
-/* Hook that is called by cgraph.c when a node is removed.  */
-
 void
-ipa_fn_summary_t::remove (cgraph_node *node, ipa_fn_summary *info)
+ipa_fn_summary_t::remove_callees (cgraph_node *node)
 {
-  info->reset (node);
+  cgraph_edge *e;
+  for (e = node->callees; e; e = e->next_callee)
+    ipa_call_summaries->remove (e);
+  for (e = node->indirect_calls; e; e = e->next_callee)
+    ipa_call_summaries->remove (e);
 }
 
 /* Same as remap_predicate_after_duplication but handle hint predicate *P.
@@ -625,7 +593,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
 			     ipa_fn_summary *,
 			     ipa_fn_summary *info)
 {
-  memcpy (info, ipa_fn_summaries->get_create (src), sizeof (ipa_fn_summary));
+  new (info) ipa_fn_summary (*ipa_fn_summaries->get (src));
   /* TODO: as an optimization, we may avoid copying conditions
      that are known to be false or true.  */
   info->conds = vec_safe_copy (info->conds);
@@ -779,7 +747,7 @@ ipa_call_summary_t::duplicate (struct cgraph_edge *src,
 			       struct ipa_call_summary *srcinfo,
 			       struct ipa_call_summary *info)
 {
-  *info = *srcinfo;
+  new (info) ipa_call_summary (*srcinfo);
   info->predicate = NULL;
   edge_set_predicate (dst, srcinfo->predicate);
   info->param = srcinfo->param.copy ();
@@ -792,17 +760,6 @@ ipa_call_summary_t::duplicate (struct cgraph_edge *src,
     }
 }
 
-
-/* Keep edge cache consistent across edge removal.  */
-
-void
-ipa_call_summary_t::remove (struct cgraph_edge *,
-			    struct ipa_call_summary *sum)
-{
-  sum->reset ();
-}
-
-
 /* Dump edge summaries associated to NODE and recursively to all clones.
    Indent by INDENT.  */
 
@@ -813,21 +770,23 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
   struct cgraph_edge *edge;
   for (edge = node->callees; edge; edge = edge->next_callee)
     {
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+      struct ipa_call_summary *es = ipa_call_summaries->get (edge);
       struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
       int i;
 
       fprintf (f,
-	       "%*s%s/%i %s\n%*s  loop depth:%2i freq:%4.2f size:%2i"
-	       " time: %2i callee size:%2i stack:%2i",
+	       "%*s%s/%i %s\n%*s  loop depth:%2i freq:%4.2f size:%2i time: %2i",
 	       indent, "", callee->name (), callee->order,
 	       !edge->inline_failed
 	       ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
 	       indent, "", es->loop_depth, edge->sreal_frequency ().to_double (),
-	       es->call_stmt_size, es->call_stmt_time,
-	       (int) (ipa_fn_summaries->get_create (callee)->size
-		      / ipa_fn_summary::size_scale),
-	       (int) ipa_fn_summaries->get_create (callee)->estimated_stack_size);
+	       es->call_stmt_size, es->call_stmt_time);
+
+      ipa_fn_summary *s = ipa_fn_summaries->get (callee);
+      if (s != NULL)
+	fprintf (f, "callee size:%2i stack:%2i",
+		 (int) (s->size / ipa_fn_summary::size_scale),
+		 (int) s->estimated_stack_size);
 
       if (es->predicate)
 	{
@@ -862,7 +821,7 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
     }
   for (edge = node->indirect_calls; edge; edge = edge->next_callee)
     {
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+      struct ipa_call_summary *es = ipa_call_summaries->get (edge);
       fprintf (f, "%*sindirect call loop depth:%2i freq:%4.2f size:%2i"
 	       " time: %2i",
 	       indent, "",
@@ -885,63 +844,67 @@ ipa_dump_fn_summary (FILE *f, struct cgraph_node *node)
 {
   if (node->definition)
     {
-      struct ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
-      size_time_entry *e;
-      int i;
-      fprintf (f, "IPA function summary for %s/%i", node->name (),
-	       node->order);
-      if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
-	fprintf (f, " always_inline");
-      if (s->inlinable)
-	fprintf (f, " inlinable");
-      if (s->fp_expressions)
-	fprintf (f, " fp_expression");
-      fprintf (f, "\n  global time:     %f\n", s->time.to_double ());
-      fprintf (f, "  self size:       %i\n", s->self_size);
-      fprintf (f, "  global size:     %i\n", s->size);
-      fprintf (f, "  min size:       %i\n", s->min_size);
-      fprintf (f, "  self stack:      %i\n",
-	       (int) s->estimated_self_stack_size);
-      fprintf (f, "  global stack:    %i\n", (int) s->estimated_stack_size);
-      if (s->growth)
-	fprintf (f, "  estimated growth:%i\n", (int) s->growth);
-      if (s->scc_no)
-	fprintf (f, "  In SCC:          %i\n", (int) s->scc_no);
-      for (i = 0; vec_safe_iterate (s->size_time_table, i, &e); i++)
+      struct ipa_fn_summary *s = ipa_fn_summaries->get (node);
+      if (s != NULL)
 	{
-	  fprintf (f, "    size:%f, time:%f",
-		   (double) e->size / ipa_fn_summary::size_scale,
-		   e->time.to_double ());
-	  if (e->exec_predicate != true)
+	  size_time_entry *e;
+	  int i;
+	  fprintf (f, "IPA function summary for %s", node->dump_name ());
+	  if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
+	    fprintf (f, " always_inline");
+	  if (s->inlinable)
+	    fprintf (f, " inlinable");
+	  if (s->fp_expressions)
+	    fprintf (f, " fp_expression");
+	  fprintf (f, "\n  global time:     %f\n", s->time.to_double ());
+	  fprintf (f, "  self size:       %i\n", s->self_size);
+	  fprintf (f, "  global size:     %i\n", s->size);
+	  fprintf (f, "  min size:       %i\n", s->min_size);
+	  fprintf (f, "  self stack:      %i\n",
+		   (int) s->estimated_self_stack_size);
+	  fprintf (f, "  global stack:    %i\n", (int) s->estimated_stack_size);
+	  if (s->growth)
+	    fprintf (f, "  estimated growth:%i\n", (int) s->growth);
+	  if (s->scc_no)
+	    fprintf (f, "  In SCC:          %i\n", (int) s->scc_no);
+	  for (i = 0; vec_safe_iterate (s->size_time_table, i, &e); i++)
+	    {
+	      fprintf (f, "    size:%f, time:%f",
+		       (double) e->size / ipa_fn_summary::size_scale,
+		       e->time.to_double ());
+	      if (e->exec_predicate != true)
+		{
+		  fprintf (f, ",  executed if:");
+		  e->exec_predicate.dump (f, s->conds, 0);
+		}
+	      if (e->exec_predicate != e->nonconst_predicate)
+		{
+		  fprintf (f, ",  nonconst if:");
+		  e->nonconst_predicate.dump (f, s->conds, 0);
+		}
+	      fprintf (f, "\n");
+	    }
+	  if (s->loop_iterations)
 	    {
-	      fprintf (f, ",  executed if:");
-	      e->exec_predicate.dump (f, s->conds, 0);
+	      fprintf (f, "  loop iterations:");
+	      s->loop_iterations->dump (f, s->conds);
 	    }
-	  if (e->exec_predicate != e->nonconst_predicate)
+	  if (s->loop_stride)
 	    {
-	      fprintf (f, ",  nonconst if:");
-	      e->nonconst_predicate.dump (f, s->conds, 0);
+	      fprintf (f, "  loop stride:");
+	      s->loop_stride->dump (f, s->conds);
 	    }
+	  if (s->array_index)
+	    {
+	      fprintf (f, "  array index:");
+	      s->array_index->dump (f, s->conds);
+	    }
+	  fprintf (f, "  calls:\n");
+	  dump_ipa_call_summary (f, 4, node, s);
 	  fprintf (f, "\n");
 	}
-      if (s->loop_iterations)
-	{
-	  fprintf (f, "  loop iterations:");
-	  s->loop_iterations->dump (f, s->conds);
-	}
-      if (s->loop_stride)
-	{
-	  fprintf (f, "  loop stride:");
-	  s->loop_stride->dump (f, s->conds);
-	}
-      if (s->array_index)
-	{
-	  fprintf (f, "  array index:");
-	  s->array_index->dump (f, s->conds);
-	}
-      fprintf (f, "  calls:\n");
-      dump_ipa_call_summary (f, 4, node, s);
-      fprintf (f, "\n");
+      else
+	fprintf (f, "IPA summary for %s is missing.\n", node->dump_name ());
     }
 }
 
@@ -2363,7 +2326,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
 	    }
 	  free (body);
 	}
-      ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
+      ipa_fn_summary *s = ipa_fn_summaries->get (node);
       set_hint_predicate (&s->loop_iterations, loop_iterations);
       set_hint_predicate (&s->loop_stride, loop_stride);
       scev_finalize ();
@@ -2383,7 +2346,7 @@ analyze_function_body (struct cgraph_node *node, bool early)
 	  e->aux = NULL;
 	}
     }
-  ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
+  ipa_fn_summary *s = ipa_fn_summaries->get (node);
   s->time = time;
   s->self_size = size;
   nonconstant_names.release ();
@@ -2419,8 +2382,10 @@ compute_fn_summary (struct cgraph_node *node, bool early)
   if (!ipa_fn_summaries)
     ipa_fn_summary_alloc ();
 
+  /* Create a new ipa_fn_summary.  */
+  ((ipa_fn_summary_t *)ipa_fn_summaries)->remove_callees (node);
+  ipa_fn_summaries->remove (node);
   info = ipa_fn_summaries->get_create (node);
-  info->reset (node);
 
   /* Estimate the stack size for the function if we're optimizing.  */
   self_stack_size = optimize && !node->thunk.thunk_p
@@ -2575,7 +2540,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
   callee = callee->function_symbol (&avail);
   if (avail < AVAIL_AVAILABLE)
     return false;
-  isummary = ipa_fn_summaries->get_create (callee);
+  isummary = ipa_fn_summaries->get (callee);
   return isummary->inlinable;
 }
 
@@ -2594,7 +2559,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size,
 			     vec<ipa_agg_jump_function_p> known_aggs,
 			     ipa_hints *hints)
 {
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+  struct ipa_call_summary *es = ipa_call_summaries->get (e);
   int call_size = es->call_stmt_size;
   int call_time = es->call_stmt_time;
   int cur_size;
@@ -2851,9 +2816,8 @@ static void
 inline_update_callee_summaries (struct cgraph_node *node, int depth)
 {
   struct cgraph_edge *e;
-  ipa_fn_summary *callee_info = ipa_fn_summaries->get_create (node);
-  ipa_fn_summary *caller_info
-    = ipa_fn_summaries->get_create (node->callers->caller);
+  ipa_fn_summary *callee_info = ipa_fn_summaries->get (node);
+  ipa_fn_summary *caller_info = ipa_fn_summaries->get (node->callers->caller);
   HOST_WIDE_INT peak;
 
   callee_info->stack_frame_offset
@@ -2862,7 +2826,7 @@ inline_update_callee_summaries (struct cgraph_node *node, int depth)
   peak = callee_info->stack_frame_offset
     + callee_info->estimated_self_stack_size;
 
-  ipa_fn_summary *s = ipa_fn_summaries->get_create (node->global.inlined_to);
+  ipa_fn_summary *s = ipa_fn_summaries->get (node->global.inlined_to);
   if (s->estimated_stack_size < peak)
     s->estimated_stack_size = peak;
   ipa_propagate_frequency (node);
@@ -2870,10 +2834,10 @@ inline_update_callee_summaries (struct cgraph_node *node, int depth)
     {
       if (!e->inline_failed)
 	inline_update_callee_summaries (e->callee, depth);
-      ipa_call_summaries->get_create (e)->loop_depth += depth;
+      ipa_call_summaries->get (e)->loop_depth += depth;
     }
   for (e = node->indirect_calls; e; e = e->next_callee)
-    ipa_call_summaries->get_create (e)->loop_depth += depth;
+    ipa_call_summaries->get (e)->loop_depth += depth;
 }
 
 /* Update change_prob of EDGE after INLINED_EDGE has been inlined.
@@ -2890,9 +2854,9 @@ remap_edge_change_prob (struct cgraph_edge *inlined_edge,
     {
       int i;
       struct ipa_edge_args *args = IPA_EDGE_REF (edge);
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+      struct ipa_call_summary *es = ipa_call_summaries->get (edge);
       struct ipa_call_summary *inlined_es
-	= ipa_call_summaries->get_create (inlined_edge);
+	= ipa_call_summaries->get (inlined_edge);
 
       for (i = 0; i < ipa_get_cs_argument_count (args); i++)
 	{
@@ -2939,7 +2903,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
   struct cgraph_edge *e, *next;
   for (e = node->callees; e; e = next)
     {
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+      struct ipa_call_summary *es = ipa_call_summaries->get (e);
       predicate p;
       next = e->next_callee;
 
@@ -2965,7 +2929,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
     }
   for (e = node->indirect_calls; e; e = next)
     {
-      struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+      struct ipa_call_summary *es = ipa_call_summaries->get (e);
       predicate p;
       next = e->next_callee;
 
@@ -3015,10 +2979,10 @@ remap_hint_predicate (struct ipa_fn_summary *info,
 void
 ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
 {
-  ipa_fn_summary *callee_info = ipa_fn_summaries->get_create (edge->callee);
+  ipa_fn_summary *callee_info = ipa_fn_summaries->get (edge->callee);
   struct cgraph_node *to = (edge->caller->global.inlined_to
 			    ? edge->caller->global.inlined_to : edge->caller);
-  struct ipa_fn_summary *info = ipa_fn_summaries->get_create (to);
+  struct ipa_fn_summary *info = ipa_fn_summaries->get (to);
   clause_t clause = 0;	/* not_inline is known to be false.  */
   size_time_entry *e;
   vec<int> operand_map = vNULL;
@@ -3026,7 +2990,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
   int i;
   predicate toplev_predicate;
   predicate true_p = true;
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+  struct ipa_call_summary *es = ipa_call_summaries->get (edge);
 
   if (es->predicate)
     toplev_predicate = *es->predicate;
@@ -3115,7 +3079,7 @@ ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge)
 			&callee_info->array_index,
 			operand_map, offset_map, clause, &toplev_predicate);
 
-  ipa_call_summary *s = ipa_call_summaries->get_create (edge);
+  ipa_call_summary *s = ipa_call_summaries->get (edge);
   inline_update_callee_summaries (edge->callee, s->loop_depth);
 
   /* We do not maintain predicates of inlined edges, free it.  */
@@ -3390,7 +3354,7 @@ ipa_fn_summary_read (void)
 static void
 write_ipa_call_summary (struct output_block *ob, struct cgraph_edge *e)
 {
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (e);
+  struct ipa_call_summary *es = ipa_call_summaries->get (e);
   int i;
 
   streamer_write_uhwi (ob, es->call_stmt_size);
@@ -3438,7 +3402,7 @@ ipa_fn_summary_write (void)
       cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
       if (cnode && cnode->definition && !cnode->alias)
 	{
-	  struct ipa_fn_summary *info = ipa_fn_summaries->get_create (cnode);
+	  struct ipa_fn_summary *info = ipa_fn_summaries->get (cnode);
 	  struct bitpack_d bp;
 	  struct cgraph_edge *edge;
 	  int i;
@@ -3513,7 +3477,7 @@ ipa_free_fn_summary (void)
     return;
   FOR_EACH_DEFINED_FUNCTION (node)
     if (!node->alias)
-      ipa_fn_summaries->get_create (node)->reset (node);
+      ipa_fn_summaries->remove (node);
   ipa_fn_summaries->release ();
   ipa_fn_summaries = NULL;
   ipa_call_summaries->release ();
diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h
index c2187510cb6..9e795944236 100644
--- a/gcc/ipa-fnsummary.h
+++ b/gcc/ipa-fnsummary.h
@@ -87,6 +87,34 @@ struct GTY(()) size_time_entry
 /* Function inlining information.  */
 struct GTY(()) ipa_fn_summary
 {
+  /* Keep all field empty so summary dumping works during its computation.
+     This is useful for debugging.  */
+  ipa_fn_summary ()
+    : estimated_self_stack_size (0), self_size (0), min_size (0),
+      inlinable (false), single_caller (false),
+      fp_expressions (false), estimated_stack_size (false),
+      stack_frame_offset (false), time (0), size (0), conds (NULL),
+      size_time_table (NULL), loop_iterations (NULL), loop_stride (NULL),
+      array_index (NULL), growth (0), scc_no (0)
+  {
+  }
+
+  /* Copy constructor.  */
+  ipa_fn_summary (const ipa_fn_summary &s)
+    : estimated_self_stack_size (s.estimated_self_stack_size),
+    self_size (s.self_size), min_size (s.min_size),
+    inlinable (s.inlinable), single_caller (s.single_caller),
+    fp_expressions (s.fp_expressions),
+    estimated_stack_size (s.estimated_stack_size),
+    stack_frame_offset (s.stack_frame_offset), time (s.time), size (s.size),
+    conds (s.conds), size_time_table (s.size_time_table),
+    loop_iterations (s.loop_iterations), loop_stride (s.loop_stride),
+    array_index (s.array_index), growth (s.growth), scc_no (s.scc_no)
+  {}
+
+  /* Default constructor.  */
+  ~ipa_fn_summary ();
+
   /* Information about the function body itself.  */
 
   /* Estimated stack frame consumption by the function.  */
@@ -138,24 +166,9 @@ struct GTY(()) ipa_fn_summary
   /* Number of SCC on the beginning of inlining process.  */
   int scc_no;
 
-  /* Keep all field empty so summary dumping works during its computation.
-     This is useful for debugging.  */
-  ipa_fn_summary ()
-    : estimated_self_stack_size (0), self_size (0), min_size (0),
-      inlinable (false), single_caller (false),
-      fp_expressions (false), estimated_stack_size (false),
-      stack_frame_offset (false), time (0), size (0), conds (NULL),
-      size_time_table (NULL), loop_iterations (NULL), loop_stride (NULL),
-      array_index (NULL), growth (0), scc_no (0)
-    {
-    }
-
   /* Record time and size under given predicates.  */
   void account_size_time (int, sreal, const predicate &, const predicate &);
 
-  /* Reset summary to empty state.  */
-  void reset (struct cgraph_node *node);
-
   /* We keep values scaled up, so fractional sizes can be accounted.  */
   static const int size_scale = 2;
 };
@@ -174,9 +187,15 @@ public:
     return summary;
   }
 
+  /* Remove ipa_fn_summary for all callees of NODE.  */
+  void remove_callees (cgraph_node *node);
 
   virtual void insert (cgraph_node *, ipa_fn_summary *);
-  virtual void remove (cgraph_node *node, ipa_fn_summary *);
+  virtual void remove (cgraph_node *node, ipa_fn_summary *)
+  {
+    remove_callees (node);
+  }
+
   virtual void duplicate (cgraph_node *src, cgraph_node *dst,
 			  ipa_fn_summary *src_data, ipa_fn_summary *dst_data);
 };
@@ -186,6 +205,25 @@ extern GTY(()) function_summary <ipa_fn_summary *> *ipa_fn_summaries;
 /* Information kept about callgraph edges.  */
 struct ipa_call_summary
 {
+  /* Keep all field empty so summary dumping works during its computation.
+     This is useful for debugging.  */
+  ipa_call_summary ()
+    : predicate (NULL), param (vNULL), call_stmt_size (0), call_stmt_time (0),
+      loop_depth (0), is_return_callee_uncaptured (false)
+    {
+    }
+
+  /* Copy constructor.  */
+  ipa_call_summary (const ipa_call_summary &s):
+    predicate (s.predicate), param (s.param), call_stmt_size (s.call_stmt_size),
+    call_stmt_time (s.call_stmt_time), loop_depth (s.loop_depth),
+    is_return_callee_uncaptured (s.is_return_callee_uncaptured)
+  {
+  }
+
+  /* Default destructor.  */
+  ~ipa_call_summary ();
+
   class predicate *predicate;
   /* Vector indexed by parameters.  */
   vec<inline_param_summary> param;
@@ -196,17 +234,6 @@ struct ipa_call_summary
   unsigned int loop_depth;
   /* Indicates whether the caller returns the value of it's callee.  */
   bool is_return_callee_uncaptured;
-
-  /* Keep all field empty so summary dumping works during its computation.
-     This is useful for debugging.  */
-  ipa_call_summary ()
-    : predicate (NULL), param (vNULL), call_stmt_size (0), call_stmt_time (0),
-      loop_depth (0)
-    {
-    }
-
-  /* Reset inline summary to empty state.  */
-  void reset ();
 };
 
 class ipa_call_summary_t: public call_summary <ipa_call_summary *>
@@ -215,8 +242,6 @@ public:
   ipa_call_summary_t (symbol_table *symtab, bool ggc):
     call_summary <ipa_call_summary *> (symtab, ggc) {}
 
-  /* Hook that is called by summary when an edge is duplicated.  */
-  virtual void remove (cgraph_edge *cs, ipa_call_summary *);
   /* Hook that is called by summary when an edge is duplicated.  */
   virtual void duplicate (cgraph_edge *src, cgraph_edge *dst,
 			  ipa_call_summary *src_data,
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index bededc3bbd5..90d1e17e5cd 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -1199,7 +1199,8 @@ sem_function::merge (sem_item *alias_item)
 		     "can not create wrapper of stdarg function.\n");
 	}
       else if (ipa_fn_summaries
-	       && ipa_fn_summaries->get_create (alias)->self_size <= 2)
+	       && ipa_fn_summaries->get (alias) != NULL
+	       && ipa_fn_summaries->get (alias)->self_size <= 2)
 	{
 	  if (dump_file)
 	    fprintf (dump_file, "Wrapper creation is not "
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index c781d368a8a..c967eaa91b5 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -128,7 +128,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
   vec<tree> known_vals;
   vec<ipa_polymorphic_call_context> known_contexts;
   vec<ipa_agg_jump_function_p> known_aggs;
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+  struct ipa_call_summary *es = ipa_call_summaries->get (edge);
   int min_size;
 
   callee = edge->callee->ultimate_alias_target ();
@@ -264,8 +264,8 @@ int
 estimate_size_after_inlining (struct cgraph_node *node,
 			      struct cgraph_edge *edge)
 {
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (edge);
-  ipa_fn_summary *s = ipa_fn_summaries->get_create (node);
+  struct ipa_call_summary *es = ipa_call_summaries->get (edge);
+  ipa_fn_summary *s = ipa_fn_summaries->get (node);
   if (!es->predicate || *es->predicate != false)
     {
       int size = s->size + estimate_edge_growth (edge);
@@ -321,7 +321,7 @@ int
 estimate_growth (struct cgraph_node *node)
 {
   struct growth_data d = { node, false, false, 0 };
-  struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
+  struct ipa_fn_summary *info = ipa_fn_summaries->get (node);
 
   node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true);
 
@@ -396,7 +396,7 @@ growth_likely_positive (struct cgraph_node *node,
       || node->address_taken)
     return true;
 
-  max_callers = ipa_fn_summaries->get_create (node)->size * 4 / edge_growth + 2;
+  max_callers = ipa_fn_summaries->get (node)->size * 4 / edge_growth + 2;
 
   for (e = node->callers; e; e = e->next_caller)
     {
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 6a3b5291c13..0e749985291 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -200,7 +200,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
 	    {
 	      gcc_assert (!e->callee->alias);
 	      if (overall_size)
-		*overall_size -= ipa_fn_summaries->get_create (e->callee)->size;
+		*overall_size -= ipa_fn_summaries->get (e->callee)->size;
 	      nfunctions_inlined++;
 	    }
 	  duplicate = false;
@@ -351,8 +351,8 @@ inline_call (struct cgraph_edge *e, bool update_original,
       reload_optimization_node = true;
     }
 
-  ipa_fn_summary *caller_info = ipa_fn_summaries->get_create (to);
-  ipa_fn_summary *callee_info = ipa_fn_summaries->get_create (callee);
+  ipa_fn_summary *caller_info = ipa_fn_summaries->get (to);
+  ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
   if (!caller_info->fp_expressions && callee_info->fp_expressions)
     {
       caller_info->fp_expressions = true;
@@ -444,7 +444,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
 
   gcc_assert (curr->callee->global.inlined_to == to);
 
-  old_size = ipa_fn_summaries->get_create (to)->size;
+  old_size = ipa_fn_summaries->get (to)->size;
   ipa_merge_fn_summary_after_inlining (e);
   if (e->in_polymorphic_cdtor)
     mark_all_inlined_calls_cdtor (e->callee);
@@ -458,8 +458,8 @@ inline_call (struct cgraph_edge *e, bool update_original,
        work for further inlining into this function.  Before inlining
        the function we inlined to again we expect the caller to update
        the overall summary.  */
-    ipa_fn_summaries->get_create (to)->size += estimated_growth;
-  new_size = ipa_fn_summaries->get_create (to)->size;
+    ipa_fn_summaries->get (to)->size += estimated_growth;
+  new_size = ipa_fn_summaries->get (to)->size;
 
   if (callee->calls_comdat_local)
     to->calls_comdat_local = true;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 7e4468a7331..8d442f6d6fd 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -151,7 +151,7 @@ caller_growth_limits (struct cgraph_edge *e)
   int limit = 0;
   HOST_WIDE_INT stack_size_limit = 0, inlined_stack;
   ipa_fn_summary *info, *what_info;
-  ipa_fn_summary *outer_info = ipa_fn_summaries->get_create (to);
+  ipa_fn_summary *outer_info = ipa_fn_summaries->get (to);
 
   /* Look for function e->caller is inlined to.  While doing
      so work out the largest function body on the way.  As
@@ -163,7 +163,7 @@ caller_growth_limits (struct cgraph_edge *e)
      too much in order to prevent compiler from exploding".  */
   while (true)
     {
-      info = ipa_fn_summaries->get_create (to);
+      info = ipa_fn_summaries->get (to);
       if (limit < info->self_size)
 	limit = info->self_size;
       if (stack_size_limit < info->estimated_self_stack_size)
@@ -174,7 +174,7 @@ caller_growth_limits (struct cgraph_edge *e)
 	break;
     }
 
-  what_info = ipa_fn_summaries->get_create (what);
+  what_info = ipa_fn_summaries->get (what);
 
   if (limit < what_info->self_size)
     limit = what_info->self_size;
@@ -364,7 +364,8 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
       inlinable = false;
     }
-  else if (!ipa_fn_summaries->get_create (callee)->inlinable)
+  else if (ipa_fn_summaries->get (callee) == NULL
+	   || !ipa_fn_summaries->get (callee)->inlinable)
     {
       e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
       inlinable = false;
@@ -426,8 +427,8 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
 	     (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
 	      && lookup_attribute ("always_inline",
 				   DECL_ATTRIBUTES (callee->decl)));
-      ipa_fn_summary *caller_info = ipa_fn_summaries->get_create (caller);
-      ipa_fn_summary *callee_info = ipa_fn_summaries->get_create (callee);
+      ipa_fn_summary *caller_info = ipa_fn_summaries->get (caller);
+      ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
 
      /* Until GCC 4.9 we did not check the semantics alterning flags
 	bellow and inline across optimization boundry.
@@ -530,7 +531,7 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
 		   > opt_for_fn (caller->decl, optimize)))
 	{
 	  if (estimate_edge_time (e)
-	      >= 20 + ipa_call_summaries->get_create (e)->call_stmt_time)
+	      >= 20 + ipa_call_summaries->get (e)->call_stmt_time)
 	    {
 	      e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
 	      inlinable = false;
@@ -680,7 +681,7 @@ compute_uninlined_call_time (struct cgraph_edge *edge,
   else
     uninlined_call_time = uninlined_call_time >> 11;
 
-  sreal caller_time = ipa_fn_summaries->get_create (caller)->time;
+  sreal caller_time = ipa_fn_summaries->get (caller)->time;
   return uninlined_call_time + caller_time;
 }
 
@@ -694,7 +695,7 @@ compute_inlined_call_time (struct cgraph_edge *edge,
   cgraph_node *caller = (edge->caller->global.inlined_to 
 			 ? edge->caller->global.inlined_to
 			 : edge->caller);
-  sreal caller_time = ipa_fn_summaries->get_create (caller)->time;
+  sreal caller_time = ipa_fn_summaries->get (caller)->time;
 
   sreal freq = edge->sreal_frequency ();
   if (freq > 0)
@@ -704,7 +705,7 @@ compute_inlined_call_time (struct cgraph_edge *edge,
 
   /* This calculation should match one in ipa-inline-analysis.c
      (estimate_edge_size_and_time).  */
-  time -= (sreal)ipa_call_summaries->get_create (edge)->call_stmt_time * freq;
+  time -= (sreal)ipa_call_summaries->get (edge)->call_stmt_time * freq;
   time += caller_time;
   if (time <= 0)
     time = ((sreal) 1) >> 8;
@@ -756,8 +757,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
      MAX_INLINE_INSNS_SINGLE 16-fold for inline functions.  */
   else if ((!DECL_DECLARED_INLINE_P (callee->decl)
 	   && (!e->count.ipa ().initialized_p () || !e->maybe_hot_p ()))
-	   && ipa_fn_summaries->get_create (callee)->min_size
-		- ipa_call_summaries->get_create (e)->call_stmt_size
+	   && ipa_fn_summaries->get (callee)->min_size
+		- ipa_call_summaries->get (e)->call_stmt_size
 	      > MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO))
     {
       e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
@@ -765,8 +766,8 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
     }
   else if ((DECL_DECLARED_INLINE_P (callee->decl)
 	    || e->count.ipa ().nonzero_p ())
-	   && ipa_fn_summaries->get_create (callee)->min_size
-		- ipa_call_summaries->get_create (e)->call_stmt_size
+	   && ipa_fn_summaries->get (callee)->min_size
+		- ipa_call_summaries->get (e)->call_stmt_size
 	      > 16 * MAX_INLINE_INSNS_SINGLE)
     {
       e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
@@ -1018,7 +1019,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
   int growth;
   sreal edge_time, unspec_edge_time;
   struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
-  struct ipa_fn_summary *callee_info = ipa_fn_summaries->get_create (callee);
+  struct ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
   ipa_hints hints;
   cgraph_node *caller = (edge->caller->global.inlined_to 
 			 ? edge->caller->global.inlined_to
@@ -1131,7 +1132,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
 		  && (!DECL_DECLARED_INLINE_P (edge->callee->decl)
 		      || DECL_DECLARED_INLINE_P (caller->decl)))))
 	{
-	  ipa_fn_summary *caller_info = ipa_fn_summaries->get_create (caller);
+	  ipa_fn_summary *caller_info = ipa_fn_summaries->get (caller);
 	  int caller_growth = caller_info->growth;
 
 	  /* Only apply the penalty when caller looks like inline candidate,
@@ -1190,7 +1191,7 @@ edge_badness (struct cgraph_edge *edge, bool dump)
      of functions fully inlined in program.  */
   else
     {
-      int nest = MIN (ipa_call_summaries->get_create (edge)->loop_depth, 8);
+      int nest = MIN (ipa_call_summaries->get (edge)->loop_depth, 8);
       badness = growth;
 
       /* Decrease badness if call is nested.  */
@@ -1334,7 +1335,7 @@ update_caller_keys (edge_heap_t *heap, struct cgraph_node *node,
   struct cgraph_edge *edge;
   struct ipa_ref *ref;
 
-  if ((!node->alias && !ipa_fn_summaries->get_create (node)->inlinable)
+  if ((!node->alias && !ipa_fn_summaries->get (node)->inlinable)
       || node->global.inlined_to)
     return;
   if (!bitmap_set_bit (updated_nodes, node->get_uid ()))
@@ -1393,7 +1394,8 @@ update_callee_keys (edge_heap_t *heap, struct cgraph_node *node,
            don't need updating.  */
 	if (e->inline_failed
 	    && (callee = e->callee->ultimate_alias_target (&avail, e->caller))
-	    && ipa_fn_summaries->get_create (callee)->inlinable
+	    && ipa_fn_summaries->get (callee) != NULL
+	    && ipa_fn_summaries->get (callee)->inlinable
 	    && avail >= AVAIL_AVAILABLE
 	    && !bitmap_bit_p (updated_nodes, callee->get_uid ()))
 	  {
@@ -1769,7 +1771,7 @@ inline_small_functions (void)
 	    && (node->has_gimple_body_p () || node->thunk.thunk_p)
 	    && opt_for_fn (node->decl, optimize))
 	  {
-	    struct ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
+	    struct ipa_fn_summary *info = ipa_fn_summaries->get (node);
 	    struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux;
 
 	    /* Do not account external functions, they will be optimized out
@@ -1791,7 +1793,7 @@ inline_small_functions (void)
 		     n2 = ((struct ipa_dfs_info *) n2->aux)->next_cycle)
 		  if (opt_for_fn (n2->decl, optimize))
 		    {
-		      ipa_fn_summary *info2 = ipa_fn_summaries->get_create (n2);
+		      ipa_fn_summary *info2 = ipa_fn_summaries->get (n2);
 		      if (info2->scc_no)
 			break;
 		      info2->scc_no = id;
@@ -1952,7 +1954,7 @@ inline_small_functions (void)
 	  fprintf (dump_file,
 		   "\nConsidering %s with %i size\n",
 		   callee->dump_name (),
-		   ipa_fn_summaries->get_create (callee)->size);
+		   ipa_fn_summaries->get (callee)->size);
 	  fprintf (dump_file,
 		   " to be inlined into %s in %s:%i\n"
 		   " Estimated badness is %f, frequency %.2f.\n",
@@ -2078,7 +2080,7 @@ inline_small_functions (void)
 
       if (dump_file)
 	{
-	  ipa_fn_summary *s = ipa_fn_summaries->get_create (edge->caller);
+	  ipa_fn_summary *s = ipa_fn_summaries->get (edge->caller);
 	  fprintf (dump_file,
 		   " Inlined %s into %s which now has time %f and size %i, "
 		   "net change of %+i.\n",
@@ -2220,11 +2222,11 @@ inline_to_all_callers_1 (struct cgraph_node *node, void *data,
 	  fprintf (dump_file,
 		   "\nInlining %s size %i.\n",
 		   node->name (),
-		   ipa_fn_summaries->get_create (node)->size);
+		   ipa_fn_summaries->get (node)->size);
 	  fprintf (dump_file,
 		   " Called once from %s %i insns.\n",
 		   node->callers->caller->name (),
-		   ipa_fn_summaries->get_create (node->callers->caller)->size);
+		   ipa_fn_summaries->get (node->callers->caller)->size);
 	}
 
       /* Remember which callers we inlined to, delaying updating the
@@ -2235,7 +2237,7 @@ inline_to_all_callers_1 (struct cgraph_node *node, void *data,
 	fprintf (dump_file,
 		 " Inlined into %s which now has %i size\n",
 		 caller->name (),
-		 ipa_fn_summaries->get_create (caller)->size);
+		 ipa_fn_summaries->get (caller)->size);
       if (!(*num_calls)--)
 	{
 	  if (dump_file)
@@ -2276,10 +2278,13 @@ dump_overall_stats (void)
     if (!node->global.inlined_to
 	&& !node->alias)
       {
-	sreal time = ipa_fn_summaries->get_create (node)->time;
-	sum += time;
-	if (node->count.ipa ().initialized_p ())
-	  sum_weighted += time * node->count.ipa ().to_gcov_type ();
+	ipa_fn_summary *s = ipa_fn_summaries->get (node);
+	if (s != NULL)
+	  {
+	  sum += s->time;
+	  if (node->count.ipa ().initialized_p ())
+	    sum_weighted += s->time * node->count.ipa ().to_gcov_type ();
+	  }
       }
   fprintf (dump_file, "Overall time estimate: "
 	   "%f weighted by profile: "
@@ -2655,8 +2660,8 @@ early_inline_small_functions (struct cgraph_node *node)
   for (e = node->callees; e; e = e->next_callee)
     {
       struct cgraph_node *callee = e->callee->ultimate_alias_target ();
-      if (!ipa_fn_summaries->get_create (callee)->inlinable
-	  || !e->inline_failed)
+      ipa_fn_summary *s = ipa_fn_summaries->get (callee);
+      if (s == NULL || !s->inlinable || !e->inline_failed)
 	continue;
 
       /* Do not consider functions not declared inline.  */
@@ -2790,11 +2795,14 @@ early_inliner (function *fun)
 	  for (edge = node->callees; edge; edge = edge->next_callee)
 	    {
 	      /* We have no summary for new bound store calls yet.  */
-	      ipa_call_summary *es = ipa_call_summaries->get_create (edge);
-	      es->call_stmt_size
-		= estimate_num_insns (edge->call_stmt, &eni_size_weights);
-	      es->call_stmt_time
-		= estimate_num_insns (edge->call_stmt, &eni_time_weights);
+	      ipa_call_summary *es = ipa_call_summaries->get (edge);
+	      if (es != NULL)
+		{
+		  es->call_stmt_size
+		    = estimate_num_insns (edge->call_stmt, &eni_size_weights);
+		  es->call_stmt_time
+		    = estimate_num_insns (edge->call_stmt, &eni_time_weights);
+		}
 
 	      if (edge->callee->decl
 		  && !gimple_check_call_matching_types (
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index 7500f5438e8..f921d1bb6f4 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -345,17 +345,20 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data)
 	case NODE_FREQUENCY_UNLIKELY_EXECUTED:
 	  break;
 	case NODE_FREQUENCY_EXECUTED_ONCE:
-	  if (dump_file && (dump_flags & TDF_DETAILS))
-	    fprintf (dump_file, "  Called by %s that is executed once\n",
-		     edge->caller->name ());
-	  d->maybe_unlikely_executed = false;
-	  if (ipa_call_summaries->get_create (edge)->loop_depth)
-	    {
-	      d->maybe_executed_once = false;
-	      if (dump_file && (dump_flags & TDF_DETAILS))
-	        fprintf (dump_file, "  Called in loop\n");
-	    }
-	  break;
+	  {
+	    if (dump_file && (dump_flags & TDF_DETAILS))
+	      fprintf (dump_file, "  Called by %s that is executed once\n",
+		       edge->caller->name ());
+	    d->maybe_unlikely_executed = false;
+	    ipa_call_summary *s = ipa_call_summaries->get (edge);
+	    if (s != NULL && s->loop_depth)
+	      {
+		d->maybe_executed_once = false;
+		if (dump_file && (dump_flags & TDF_DETAILS))
+		  fprintf (dump_file, "  Called in loop\n");
+	      }
+	    break;
+	  }
 	case NODE_FREQUENCY_HOT:
 	case NODE_FREQUENCY_NORMAL:
 	  if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index daada4d55a5..000c05ffd89 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -2819,7 +2819,6 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target,
 				bool speculative)
 {
   struct cgraph_node *callee;
-  struct ipa_call_summary *es = ipa_call_summaries->get_create (ie);
   bool unreachable = false;
 
   if (TREE_CODE (target) == ADDR_EXPR)
@@ -2957,7 +2956,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target,
 	 for direct call (adjusted by inline_edge_duplication_hook).  */
       if (ie == orig)
 	{
-	  es = ipa_call_summaries->get_create (ie);
+	  ipa_call_summary *es = ipa_call_summaries->get (ie);
 	  es->call_stmt_size -= (eni_size_weights.indirect_call_cost
 				 - eni_size_weights.call_cost);
 	  es->call_stmt_time -= (eni_time_weights.indirect_call_cost
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 9441d2508ab..4de609e7ca1 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -923,7 +923,7 @@ malloc_candidate_p (function *fun, bool ipa)
 	  cgraph_edge *cs = node->get_edge (call_stmt);
 	  if (cs)
 	    {
-	      ipa_call_summary *es = ipa_call_summaries->get_create (cs);
+	      ipa_call_summary *es = ipa_call_summaries->get (cs);
 	      gcc_assert (es);
 	      es->is_return_callee_uncaptured = true;
 	    }
@@ -959,7 +959,7 @@ malloc_candidate_p (function *fun, bool ipa)
 	      cgraph_edge *cs = node->get_edge (call_stmt);
 	      if (cs)
 		{
-		  ipa_call_summary *es = ipa_call_summaries->get_create (cs);
+		  ipa_call_summary *es = ipa_call_summaries->get (cs);
 		  gcc_assert (es);
 		  es->is_return_callee_uncaptured = true;
 		}
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index c3771f178bf..0e6440f8997 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1691,7 +1691,8 @@ execute_split_functions (void)
   /* This can be relaxed; function might become inlinable after splitting
      away the uninlinable part.  */
   if (ipa_fn_summaries
-      && !ipa_fn_summaries->get_create (node)->inlinable)
+      && ipa_fn_summaries->get (node)
+      && !ipa_fn_summaries->get (node)->inlinable)
     {
       if (dump_file)
 	fprintf (dump_file, "Not splitting: not inlinable.\n");
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 0ceb1b63f95..c7a5710f776 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -171,7 +171,7 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
     {
       struct cgraph_edge *e;
       if (!node->alias && c == SYMBOL_PARTITION)
-        part->insns += ipa_fn_summaries->get_create (cnode)->size;
+	part->insns += ipa_fn_summaries->get (cnode)->size;
 
       /* Add all inline clones and callees that are duplicated.  */
       for (e = cnode->callees; e; e = e->next_callee)
@@ -291,7 +291,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes)
 
       if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node))
           && node->get_partitioning_class () == SYMBOL_PARTITION)
-        partition->insns -= ipa_fn_summaries->get_create (cnode)->size;
+	partition->insns -= ipa_fn_summaries->get (cnode)->size;
       lto_symtab_encoder_delete_node (partition->encoder, node);
       node->aux = (void *)((size_t)node->aux - 1);
     }
@@ -528,7 +528,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size)
 	else
 	  order.safe_push (node);
 	if (!node->alias)
-	  total_size += ipa_fn_summaries->get_create (node)->size;
+	  total_size += ipa_fn_summaries->get (node)->size;
       }
 
   original_total_size = total_size;
diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index ebf4b175e71..bf32810abd7 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -99,6 +99,18 @@ public:
     return get (node->get_uid (), false);
   }
 
+  /* Remove node from summary.  */
+  void remove (cgraph_node *node)
+  {
+    int uid = node->get_uid ();
+    T **v = m_map.get (uid);
+    if (v)
+      {
+	m_map.remove (uid);
+	release (*v);
+      }
+  }
+
   /* Return number of elements handled by data structure.  */
   size_t elements ()
   {
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 494afd83046..3e30f6bc3d4 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -5458,7 +5458,8 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
     }
 
   if ((DECL_ONE_ONLY (node->decl) || DECL_EXTERNAL (node->decl))
-      && ipa_fn_summaries->get_create (node)->size >= MAX_INLINE_INSNS_AUTO)
+      && ipa_fn_summaries->get (node)
+      && ipa_fn_summaries->get (node)->size >= MAX_INLINE_INSNS_AUTO)
     {
       if (dump_file)
 	fprintf (dump_file, "Function too big to be made truly local.\n");


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]