From: Martin Liska Date: Tue, 19 Jun 2018 14:31:20 +0000 (+0200) Subject: Clean-up usage of ipa_fn_summary and ipa_call_summary summaries. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=56f62793be7b655f02889ef04f58df0d6e8fb1af;p=gcc.git Clean-up usage of ipa_fn_summary and ipa_call_summary summaries. 2018-06-19 Martin Liska * 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. 2018-06-19 Martin Liska * lto-partition.c (add_symbol_to_partition_1): Use symbol_summary::get instead of get_create. (undo_partition): Likewise. (lto_balanced_map): Likewise. From-SVN: r261744 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7c4b9e6ae96..c4a48f068c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,70 @@ +2018-06-19 Martin Liska + + * 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. + 2018-06-19 Richard Biener * tree-vectorizer.c (try_vectorize_loop_1): Split out of ... diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f88680703ed..ba23cd0a1ab 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 504a2d1ce55..c99718a265f 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 *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 known_vals = vNULL; vec 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 ()); } } @@ -2365,7 +2328,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 (); @@ -2385,7 +2348,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 (); @@ -2421,8 +2384,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 @@ -2577,7 +2542,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; } @@ -2596,7 +2561,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size, vec 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; @@ -2853,9 +2818,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 @@ -2864,7 +2828,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); @@ -2872,10 +2836,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. @@ -2892,9 +2856,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++) { @@ -2941,7 +2905,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; @@ -2967,7 +2931,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; @@ -3017,10 +2981,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 operand_map = vNULL; @@ -3028,7 +2992,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; @@ -3117,7 +3081,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. */ @@ -3392,7 +3356,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); @@ -3440,7 +3404,7 @@ ipa_fn_summary_write (void) cgraph_node *cnode = dyn_cast (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; @@ -3515,7 +3479,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_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 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 @@ -215,8 +242,6 @@ public: ipa_call_summary_t (symbol_table *symtab, bool ggc): 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 known_vals; vec known_contexts; vec 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..a62c1ffd3b0 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,12 @@ 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) + + /* We can enounter not-yet-analyzed function during + early inlining on callgraphs with strongly + connected components. */ + 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. */ @@ -2765,6 +2774,9 @@ early_inliner (function *fun) statements that don't have inline parameters computed. */ for (edge = node->callees; edge; edge = edge->next_callee) { + /* We can enounter not-yet-analyzed function during + early inlining on callgraphs with strongly + connected components. */ ipa_call_summary *es = ipa_call_summaries->get_create (edge); es->call_stmt_size = estimate_num_insns (edge->call_stmt, &eni_size_weights); @@ -2790,11 +2802,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/ChangeLog b/gcc/lto/ChangeLog index aaede9a7264..67db280d400 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,10 @@ +2018-06-19 Martin Liska + + * lto-partition.c (add_symbol_to_partition_1): Use symbol_summary::get instead + of get_create. + (undo_partition): Likewise. + (lto_balanced_map): Likewise. + 2018-06-19 Martin Liska * config-lang.in: Remove stagestuff. 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 (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");