On 06/15/2018 05:05 PM, Jan Hubicka wrote:
>> 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  <mli...@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.
>>
> 
> OK with changes marked below.
> 
>> 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;
> 
> I wonder how possibly we can get NULL here? That seems like bug to me...

Hello.

ICEs on:

$ cat ice.ii
#pragma GCC optimize 0
int main() {}

$ ./xgcc -B. -O2 ice.ii
during IPA pass: cp
ice.ii:2:13: internal compiler error: Segmentation fault
 int main() {}
             ^
0xdbb6bf crash_signal
        /home/marxin/Programming/gcc/gcc/toplev.c:324
0x7ffff6d8ba6f ???
        
/usr/src/debug/glibc-2.27-5.1.x86_64/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:0
0x15edd82 ipcp_propagate_stage
        /home/marxin/Programming/gcc/gcc/ipa-cp.c:3292
0x15f049a ipcp_driver
        /home/marxin/Programming/gcc/gcc/ipa-cp.c:5081
0x15f049a execute
        /home/marxin/Programming/gcc/gcc/ipa-cp.c:5172


>>      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)
> 
> Alias is the target we merge to. In what sictuation it can be unanalyzed?

Can't that also ICE for similar reason as IPA CP?

>> @@ -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)
> 
> Please add comment here that we can enounter not-yet-analyzed function during
> early inlining on callgraphs with strongly connected components.

Will do.

>> @@ -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;
> 
> And here too :)

Will do.

Martin

>>  
>>        /* 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);
>> +            }
> 
> This loop should add missing summaries (as comment explains) so you want to 
> use get_create.
> 
> Honza
> 

Reply via email to