gcc/ChangeLog: 2015-07-03 Martin Liska <mli...@suse.cz>
* ipa-inline-analysis.c (inline_edge_summaries): New data structure. (redirect_to_unreachable): Use renamed function get_inline_edge_summary. (edge_set_predicate): Likewise. (evaluate_properties_for_edge): Likewise. (reset_inline_edge_summary): Likewise. (inline_summary_t::duplicate): New function. (inline_edge_summary_t::duplicate): Likewise. (dump_inline_edge_summary): Use renamed function get_inline_edge_summary. (estimate_function_body_sizes): Likewise. (compute_inline_parameters): Likewise. (estimate_edge_size_and_time): Likewise. (estimate_calls_size_and_time): Likewise. (inline_update_callee_summaries): Likewise. (remap_edge_change_prob): Likewise. (remap_edge_summaries): Likewise. (inline_merge_summary): Likewise. (do_estimate_edge_time): Likewise. (estimate_time_after_inlining): Likewise. (estimate_size_after_inlining): Likewise. (read_inline_edge_summary): Likewise. (write_inline_edge_summary): Likewise. (inline_summary_alloc): Remove symtab hook holders. (inline_free_summary): Likewise. * ipa-inline.c (can_inline_edge_p): Use get_inline_edge_summary. (compute_inlined_call_time): Likewise. (want_inline_small_function_p): Likewise. (edge_badness): Likewise. (early_inliner): Likewise. * ipa-inline.h (get_inline_edge_summary): Renamed from inline_edge_summary. (estimate_edge_growth): Use the function. * ipa-profile.c (ipa_propagate_frequency_1): Likewise. * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise. (ipa_free_all_edge_args): Remove unused arguments. * ipa-split.c (execute_split_functions): change guard to the newly added class. * ipa.c (symbol_table::remove_unreachable_nodes): Likewise. --- gcc/ipa-inline-analysis.c | 105 ++++++++++++++++++---------------------------- gcc/ipa-inline.c | 18 ++++---- gcc/ipa-inline.h | 28 +++++++++---- gcc/ipa-profile.c | 2 +- gcc/ipa-prop.c | 7 +--- gcc/ipa-split.c | 3 +- gcc/ipa.c | 2 +- 7 files changed, 73 insertions(+), 92 deletions(-) diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index c11dc9c..6ce737f 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -129,17 +129,10 @@ enum predicate_conditions of executions even when they are not compile time constants. */ #define CHANGED IDENTIFIER_NODE -/* Holders of ipa cgraph hooks: */ -static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; -static struct cgraph_edge_hook_list *edge_removal_hook_holder; -static void inline_edge_removal_hook (struct cgraph_edge *, void *); -static void inline_edge_duplication_hook (struct cgraph_edge *, - struct cgraph_edge *, void *); - /* VECtor holding inline summaries. In GGC memory because conditions might point to constant trees. */ function_summary <inline_summary *> *inline_summaries; -vec<inline_edge_summary_t> inline_edge_summary_vec; +inline_edge_summary_t *inline_edge_summaries; /* Cached node/edge growths. */ vec<edge_growth_cache_entry> edge_growth_cache; @@ -750,7 +743,7 @@ redirect_to_unreachable (struct cgraph_edge *e) e->make_direct (target); else e->redirect_callee (target); - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); e->inline_failed = CIF_UNREACHABLE; e->frequency = 0; e->count = 0; @@ -775,7 +768,7 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate) && (!e->speculative || e->callee)) e = redirect_to_unreachable (e); - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); if (predicate && !true_predicate_p (predicate)) { if (!es->predicate) @@ -924,7 +917,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, { struct ipa_node_params *parms_info; struct ipa_edge_args *args = IPA_EDGE_REF (e); - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); int i, count = ipa_get_cs_argument_count (args); if (e->caller->global.inlined_to) @@ -1007,18 +1000,11 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, static void inline_summary_alloc (void) { - if (!edge_removal_hook_holder) - edge_removal_hook_holder = - symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL); - if (!edge_duplication_hook_holder) - edge_duplication_hook_holder = - symtab->add_edge_duplication_hook (&inline_edge_duplication_hook, NULL); + if (!inline_edge_summaries) + inline_edge_summaries = new inline_edge_summary_t (symtab); if (!inline_summaries) inline_summaries = (inline_summary_t*) inline_summary_t::create_ggc (symtab); - - if (inline_edge_summary_vec.length () <= (unsigned) symtab->edges_max_uid) - inline_edge_summary_vec.safe_grow_cleared (symtab->edges_max_uid + 1); } /* We are called multiple time for given function; clear @@ -1027,9 +1013,9 @@ inline_summary_alloc (void) static void reset_inline_edge_summary (struct cgraph_edge *e) { - if (e->uid < (int) inline_edge_summary_vec.length ()) + if (inline_edge_summaries) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); es->call_stmt_size = es->call_stmt_time = 0; if (es->predicate) @@ -1209,7 +1195,7 @@ inline_summary_t::duplicate (cgraph_node *src, for (edge = dst->callees; edge; edge = next) { struct predicate new_predicate; - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); next = edge->next_callee; if (!edge->inline_failed) @@ -1230,7 +1216,7 @@ inline_summary_t::duplicate (cgraph_node *src, for (edge = dst->indirect_calls; edge; edge = next) { struct predicate new_predicate; - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); next = edge->next_callee; gcc_checking_assert (edge->inline_failed); @@ -1286,16 +1272,11 @@ inline_summary_t::duplicate (cgraph_node *src, /* Hook that is called by cgraph.c when a node is duplicated. */ -static void -inline_edge_duplication_hook (struct cgraph_edge *src, - struct cgraph_edge *dst, - ATTRIBUTE_UNUSED void *data) +void +inline_edge_summary_t::duplicate (cgraph_edge *src, cgraph_edge *dst, + inline_edge_summary *srcinfo, + inline_edge_summary *info) { - struct inline_edge_summary *info; - struct inline_edge_summary *srcinfo; - inline_summary_alloc (); - info = inline_edge_summary (dst); - srcinfo = inline_edge_summary (src); memcpy (info, srcinfo, sizeof (struct inline_edge_summary)); info->predicate = NULL; edge_set_predicate (dst, srcinfo->predicate); @@ -1312,9 +1293,9 @@ inline_edge_duplication_hook (struct cgraph_edge *src, /* Keep edge cache consistent across edge removal. */ -static void -inline_edge_removal_hook (struct cgraph_edge *edge, - void *data ATTRIBUTE_UNUSED) +void +inline_edge_summary_t::remove (cgraph_edge *edge, + inline_edge_summary *) { if (edge_growth_cache.exists ()) reset_edge_growth_cache (edge); @@ -1351,7 +1332,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, struct cgraph_edge *edge; for (edge = node->callees; edge; edge = edge->next_callee) { - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); struct cgraph_node *callee = edge->callee->ultimate_alias_target (); int i; @@ -1398,7 +1379,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, } for (edge = node->indirect_calls; edge; edge = edge->next_callee) { - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); fprintf (f, "%*sindirect call loop depth:%2i freq:%4i size:%2i" " time: %2i", indent, "", @@ -2644,7 +2625,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) && !gimple_call_internal_p (stmt)) { struct cgraph_edge *edge = node->get_edge (stmt); - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); /* Special case: results of BUILT_IN_CONSTANT_P will be always resolved as constant. We however don't want to optimize @@ -2886,7 +2867,7 @@ compute_inline_parameters (struct cgraph_node *node, bool early) statement size. */ if (node->thunk.thunk_p) { - struct inline_edge_summary *es = inline_edge_summary (node->callees); + struct inline_edge_summary *es = get_inline_edge_summary (node->callees); struct predicate t = true_predicate (); info->inlinable = 0; @@ -3068,7 +3049,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *min_size, vec<ipa_agg_jump_function_p> known_aggs, inline_hints *hints) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); int call_size = es->call_stmt_size; int call_time = es->call_stmt_time; int cur_size; @@ -3105,7 +3086,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, struct cgraph_edge *e; for (e = node->callees; e; e = e->next_callee) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); /* Do not care about zero sized builtins. */ if (e->inline_failed && !es->call_stmt_size) @@ -3136,7 +3117,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, } for (e = node->indirect_calls; e; e = e->next_callee) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); if (!es->predicate || evaluate_predicate (es->predicate, possible_truths)) estimate_edge_size_and_time (e, size, @@ -3401,10 +3382,10 @@ inline_update_callee_summaries (struct cgraph_node *node, int depth) { if (!e->inline_failed) inline_update_callee_summaries (e->callee, depth); - inline_edge_summary (e)->loop_depth += depth; + get_inline_edge_summary (e)->loop_depth += depth; } for (e = node->indirect_calls; e; e = e->next_callee) - inline_edge_summary (e)->loop_depth += depth; + get_inline_edge_summary (e)->loop_depth += depth; } /* Update change_prob of EDGE after INLINED_EDGE has been inlined. @@ -3421,9 +3402,9 @@ remap_edge_change_prob (struct cgraph_edge *inlined_edge, { int i; struct ipa_edge_args *args = IPA_EDGE_REF (edge); - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); struct inline_edge_summary *inlined_es - = inline_edge_summary (inlined_edge); + = get_inline_edge_summary (inlined_edge); for (i = 0; i < ipa_get_cs_argument_count (args); i++) { @@ -3466,7 +3447,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_edge *e, *next; for (e = node->callees; e; e = next) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); struct predicate p; next = e->next_callee; @@ -3491,7 +3472,7 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge, } for (e = node->indirect_calls; e; e = next) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); struct predicate p; next = e->next_callee; @@ -3552,7 +3533,7 @@ inline_merge_summary (struct cgraph_edge *edge) int i; struct predicate toplev_predicate; struct predicate true_p = true_predicate (); - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); if (es->predicate) toplev_predicate = *es->predicate; @@ -3638,7 +3619,7 @@ inline_merge_summary (struct cgraph_edge *edge) operand_map, offset_map, clause, &toplev_predicate); inline_update_callee_summaries (edge->callee, - inline_edge_summary (edge)->loop_depth); + get_inline_edge_summary (edge)->loop_depth); /* We do not maintain predicates of inlined edges, free it. */ edge_set_predicate (edge, &true_p); @@ -3714,7 +3695,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 inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); int min_size; callee = edge->callee->ultimate_alias_target (); @@ -3843,7 +3824,7 @@ int estimate_time_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge) { - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); if (!es->predicate || !false_predicate_p (es->predicate)) { gcov_type time = @@ -3865,7 +3846,7 @@ int estimate_size_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge) { - struct inline_edge_summary *es = inline_edge_summary (edge); + struct inline_edge_summary *es = get_inline_edge_summary (edge); if (!es->predicate || !false_predicate_p (es->predicate)) { int size = inline_summaries->get (node)->size + estimate_edge_growth (edge); @@ -4142,7 +4123,7 @@ read_predicate (struct lto_input_block *ib) static void read_inline_edge_summary (struct lto_input_block *ib, struct cgraph_edge *e) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); struct predicate p; int length, i; @@ -4315,7 +4296,7 @@ write_predicate (struct output_block *ob, struct predicate *p) static void write_inline_edge_summary (struct output_block *ob, struct cgraph_edge *e) { - struct inline_edge_summary *es = inline_edge_summary (e); + struct inline_edge_summary *es = get_inline_edge_summary (e); int i; streamer_write_uhwi (ob, es->call_stmt_size); @@ -4411,26 +4392,20 @@ inline_write_summary (void) ipa_prop_write_jump_functions (); } - /* Release inline summary. */ void inline_free_summary (void) { struct cgraph_node *node; - if (edge_removal_hook_holder) - symtab->remove_edge_removal_hook (edge_removal_hook_holder); - edge_removal_hook_holder = NULL; - if (edge_duplication_hook_holder) - symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); - edge_duplication_hook_holder = NULL; - if (!inline_edge_summary_vec.exists ()) + if (inline_edge_summaries == NULL) return; FOR_EACH_DEFINED_FUNCTION (node) if (!node->alias) reset_inline_summary (node, inline_summaries->get (node)); + delete inline_edge_summaries; + inline_edge_summaries = NULL; inline_summaries->release (); inline_summaries = NULL; - inline_edge_summary_vec.release (); edge_predicate_pool.release (); } diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index f836df6..fb6d007 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -515,7 +515,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, > opt_for_fn (caller->decl, optimize))) { if (estimate_edge_time (e) - >= 20 + inline_edge_summary (e)->call_stmt_time) + >= 20 + get_inline_edge_summary (e)->call_stmt_time) { e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false; @@ -695,7 +695,7 @@ compute_inlined_call_time (struct cgraph_edge *edge, FIXME: Once ipa-inline-analysis is converted to sreal this can be simplified. */ time -= (sreal) ((gcov_type) edge->frequency - * inline_edge_summary (edge)->call_stmt_time + * get_inline_edge_summary (edge)->call_stmt_time * (INLINE_TIME_SCALE / CGRAPH_FREQ_BASE)) / INLINE_TIME_SCALE; time += caller_time; if (time <= 0) @@ -745,7 +745,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) else if ((!DECL_DECLARED_INLINE_P (callee->decl) && (!e->count || !e->maybe_hot_p ())) && inline_summaries->get (callee)->min_size - - inline_edge_summary (e)->call_stmt_size + - get_inline_edge_summary (e)->call_stmt_size > MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO)) { e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT; @@ -753,7 +753,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) } else if ((DECL_DECLARED_INLINE_P (callee->decl) || e->count) && inline_summaries->get (callee)->min_size - - inline_edge_summary (e)->call_stmt_size + - get_inline_edge_summary (e)->call_stmt_size > 16 * MAX_INLINE_INSNS_SINGLE) { e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl) @@ -1191,7 +1191,7 @@ edge_badness (struct cgraph_edge *edge, bool dump) of functions fully inlined in program. */ else { - int nest = MIN (inline_edge_summary (edge)->loop_depth, 8); + int nest = MIN (get_inline_edge_summary (edge)->loop_depth, 8); badness = growth; /* Decrease badness if call is nested. */ @@ -2688,9 +2688,9 @@ early_inliner (function *fun) statements that don't have inline parameters computed. */ for (edge = node->callees; edge; edge = edge->next_callee) { - if (inline_edge_summary_vec.length () > (unsigned) edge->uid) + if (inline_edge_summaries) { - struct inline_edge_summary *es = inline_edge_summary (edge); + inline_edge_summary *es = get_inline_edge_summary (edge); es->call_stmt_size = estimate_num_insns (edge->call_stmt, &eni_size_weights); es->call_stmt_time @@ -2716,9 +2716,9 @@ early_inliner (function *fun) for (edge = node->callees; edge; edge = edge->next_callee) { /* We have no summary for new bound store calls yet. */ - if (inline_edge_summary_vec.length () > (unsigned)edge->uid) + if (inline_edge_summaries) { - struct inline_edge_summary *es = inline_edge_summary (edge); + inline_edge_summary *es = get_inline_edge_summary (edge); es->call_stmt_size = estimate_num_insns (edge->call_stmt, &eni_size_weights); es->call_stmt_time diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index 85041f6..8a6fd31 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -219,10 +219,20 @@ struct inline_edge_summary vec<inline_param_summary> param; }; -/* Need a typedef for inline_edge_summary because of inline function - 'inline_edge_summary' below. */ -typedef struct inline_edge_summary inline_edge_summary_t; -extern vec<inline_edge_summary_t> inline_edge_summary_vec; +class GTY((user)) inline_edge_summary_t: + public edge_summary <inline_edge_summary *> +{ +public: + inline_edge_summary_t (symbol_table *symtab): + edge_summary <inline_edge_summary *> (symtab) {} + + virtual void remove (cgraph_edge *edge, inline_edge_summary *s); + virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge, + inline_edge_summary *src_data, + inline_edge_summary *dst_data); +}; + +extern inline_edge_summary_t *inline_edge_summaries; struct edge_growth_cache_entry { @@ -275,10 +285,10 @@ void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *, extern int ncalls_inlined; extern int nfunctions_inlined; -static inline struct inline_edge_summary * -inline_edge_summary (struct cgraph_edge *edge) +static inline inline_edge_summary * +get_inline_edge_summary (cgraph_edge *edge) { - return &inline_edge_summary_vec[edge->uid]; + return inline_edge_summaries->get (edge); } @@ -300,11 +310,11 @@ static inline int estimate_edge_growth (struct cgraph_edge *edge) { #ifdef ENABLE_CHECKING - gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size + gcc_checking_assert (get_inline_edge_summary (edge)->call_stmt_size || !edge->callee->analyzed); #endif return (estimate_edge_size (edge) - - inline_edge_summary (edge)->call_stmt_size); + - get_inline_edge_summary (edge)->call_stmt_size); } /* Return estimated callee runtime increase after inlning diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index 6d6afb3..2e9c6ff 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -355,7 +355,7 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data) fprintf (dump_file, " Called by %s that is executed once\n", edge->caller->name ()); d->maybe_unlikely_executed = false; - if (inline_edge_summary (edge)->loop_depth) + if (get_inline_edge_summary (edge)->loop_depth) { d->maybe_executed_once = false; if (dump_file && (dump_flags & TDF_DETAILS)) diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 9750a26..a825643 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2578,7 +2578,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, bool speculative) { struct cgraph_node *callee; - struct inline_edge_summary *es = inline_edge_summary (ie); + struct inline_edge_summary *es = get_inline_edge_summary (ie); bool unreachable = false; if (TREE_CODE (target) == ADDR_EXPR) @@ -2727,7 +2727,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 = inline_edge_summary (ie); + es = get_inline_edge_summary (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 @@ -3336,9 +3336,6 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, void ipa_free_all_edge_args (void) { - int i; - struct ipa_edge_args *args; - if (!ipa_edge_args_sum) return; diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index df6572f..05d7967 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1698,8 +1698,7 @@ execute_split_functions (void) } /* This can be relaxed; function might become inlinable after splitting away the uninlinable part. */ - if (inline_edge_summary_vec.exists () - && !inline_summaries->get (node)->inlinable) + if (inline_edge_summaries && !inline_summaries->get (node)->inlinable) { if (dump_file) fprintf (dump_file, "Not splitting: not inlinable.\n"); diff --git a/gcc/ipa.c b/gcc/ipa.c index 75e367f..46fe636 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -683,7 +683,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) #endif /* If we removed something, perhaps profile could be improved. */ - if (changed && optimize && inline_edge_summary_vec.exists ()) + if (changed && optimize && inline_edge_summaries) FOR_EACH_DEFINED_FUNCTION (node) ipa_propagate_frequency (node); -- 2.4.5