diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-19 05:55:20 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-19 05:55:20 +0000 |
commit | eb7c606e1e1222b20023e10832593ae0e5478c8d (patch) | |
tree | 032d8e752b8a993f1aa19d59d320266d25238378 /gcc/ipa-inline-analysis.c | |
parent | f260f060e739be598c8ff906ff61b6fdffe64571 (diff) | |
download | gcc-eb7c606e1e1222b20023e10832593ae0e5478c8d.tar.gz |
PR lto/45375
* ipa-inline.c (want_inline_small_function_p): Bypass
inline limits for hinted functions.
(edge_badness): Dump hints; decrease badness for hinted funcitons.
* ipa-inline.h (enum inline_hints_vals): New enum.
(inline_hints): New type.
(edge_growth_cache_entry): Add hints.
(dump_inline_summary): Update.
(dump_inline_hints): Declare.
(do_estimate_edge_hints): Declare.
(estimate_edge_hints): New inline function.
(reset_edge_growth_cache): Update.
* predict.c (cgraph_maybe_hot_edge_p): Do not ice on indirect edges.
* ipa-inline-analysis.c (dump_inline_hints): New function.
(estimate_edge_devirt_benefit): Return true when function should be
hinted.
(estimate_calls_size_and_time): New hints argument; set it when
devritualization happens.
(estimate_node_size_and_time): New hints argument.
(do_estimate_edge_time): Cache hints.
(do_estimate_edge_growth): Update.
(do_estimate_edge_hints): New function
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190509 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-inline-analysis.c')
-rw-r--r-- | gcc/ipa-inline-analysis.c | 125 |
1 files changed, 83 insertions, 42 deletions
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 9f96ca8a3ba..c30e81a88f1 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -615,6 +615,22 @@ dump_predicate (FILE *f, conditions conds, struct predicate *pred) } +/* Dump inline hints. */ +void +dump_inline_hints (FILE *f, inline_hints hints) +{ + if (!hints) + return; + fprintf (f, "inline hints:"); + if (hints & INLINE_HINT_indirect_call) + { + hints &= ~INLINE_HINT_indirect_call; + fprintf (f, " indirect_call"); + } + gcc_assert (!hints); +} + + /* Record SIZE and TIME under condition PRED into the inline summary. */ static void @@ -2302,7 +2318,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time, /* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and KNOWN_BINFOS. */ -static void +static bool estimate_edge_devirt_benefit (struct cgraph_edge *ie, int *size, int *time, int prob, VEC (tree, heap) *known_vals, @@ -2311,14 +2327,16 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, { tree target; int time_diff, size_diff; + struct cgraph_node *callee; + struct inline_summary *isummary; if (!known_vals && !known_binfos) - return; + return false; target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos, known_aggs); if (!target) - return; + return false; /* Account for difference in cost between indirect and direct calls. */ size_diff = ((eni_size_weights.indirect_call_cost - eni_size_weights.call_cost) @@ -2328,40 +2346,11 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, * INLINE_TIME_SCALE * prob / REG_BR_PROB_BASE); *time -= time_diff; - /* TODO: This code is trying to benefit indirect calls that will be inlined later. - The logic however do not belong into local size/time estimates and can not be - done here, or the accounting of changes will get wrong and we result with - negative function body sizes. We need to introduce infrastructure for independent - benefits to the inliner. */ -#if 0 - struct cgraph_node *callee; - struct inline_summary *isummary; - int edge_size, edge_time, time_diff, size_diff; - callee = cgraph_get_node (target); if (!callee || !callee->analyzed) - return; + return false; isummary = inline_summary (callee); - if (!isummary->inlinable) - return; - - estimate_edge_size_and_time (ie, &edge_size, &edge_time, prob); - - /* Count benefit only from functions that definitely will be inlined - if additional context from NODE's caller were available. - - We just account overall size change by inlining. TODO: - we really need to add sort of benefit metrics for these kind of - cases. */ - if (edge_size - size_diff >= isummary->size * INLINE_SIZE_SCALE) - { - /* Subtract size and time that we added for edge IE. */ - *size -= edge_size - size_diff; - - /* Account inlined call. */ - *size += isummary->size * INLINE_SIZE_SCALE; - } -#endif + return isummary->inlinable; } @@ -2371,6 +2360,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, static void estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, + inline_hints *hints, clause_t possible_truths, VEC (tree, heap) *known_vals, VEC (tree, heap) *known_binfos, @@ -2389,7 +2379,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); } else - estimate_calls_size_and_time (e->callee, size, time, + estimate_calls_size_and_time (e->callee, size, time, hints, possible_truths, known_vals, known_binfos, known_aggs); } @@ -2400,8 +2390,11 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, if (!es->predicate || evaluate_predicate (es->predicate, possible_truths)) { estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); - estimate_edge_devirt_benefit (e, size, time, REG_BR_PROB_BASE, - known_vals, known_binfos, known_aggs); + if (estimate_edge_devirt_benefit (e, size, time, REG_BR_PROB_BASE, + known_vals, known_binfos, known_aggs) + && hints + && cgraph_maybe_hot_edge_p (e)) + *hints |= INLINE_HINT_indirect_call; } } } @@ -2418,12 +2411,14 @@ estimate_node_size_and_time (struct cgraph_node *node, VEC (tree, heap) *known_binfos, VEC (ipa_agg_jump_function_p, heap) *known_aggs, int *ret_size, int *ret_time, + inline_hints *ret_hints, VEC (inline_param_summary_t, heap) *inline_param_summary) { struct inline_summary *info = inline_summary (node); size_time_entry *e; int size = 0, time = 0; + inline_hints hints = 0; int i; if (dump_file @@ -2467,7 +2462,7 @@ estimate_node_size_and_time (struct cgraph_node *node, if (time > MAX_TIME * INLINE_TIME_SCALE) time = MAX_TIME * INLINE_TIME_SCALE; - estimate_calls_size_and_time (node, &size, &time, possible_truths, + estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths, known_vals, known_binfos, known_aggs); time = (time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE; size = (size + INLINE_SIZE_SCALE / 2) / INLINE_SIZE_SCALE; @@ -2480,6 +2475,8 @@ estimate_node_size_and_time (struct cgraph_node *node, *ret_time = time; if (ret_size) *ret_size = size; + if (ret_hints) + *ret_hints = hints; return; } @@ -2499,7 +2496,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node, clause = evaluate_conditions_for_known_args (node, false, known_vals, NULL); estimate_node_size_and_time (node, clause, known_vals, known_binfos, NULL, - ret_size, ret_time, + ret_size, ret_time, NULL, NULL); } @@ -2871,7 +2868,7 @@ inline_update_overall_summary (struct cgraph_node *node) info->time = 0; for (i = 0; VEC_iterate (size_time_entry, info->entry, i, e); i++) info->size += e->size, info->time += e->time; - estimate_calls_size_and_time (node, &info->size, &info->time, + estimate_calls_size_and_time (node, &info->size, &info->time, NULL, ~(clause_t)(1 << predicate_false_condition), NULL, NULL, NULL); info->time = (info->time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE; @@ -2890,6 +2887,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) { int time; int size; + inline_hints hints; gcov_type ret; struct cgraph_node *callee; clause_t clause; @@ -2905,7 +2903,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) &clause, &known_vals, &known_binfos, &known_aggs); estimate_node_size_and_time (callee, clause, known_vals, known_binfos, - known_aggs, &size, &time, es->param); + known_aggs, &size, &time, &hints, es->param); VEC_free (tree, heap, known_vals); VEC_free (tree, heap, known_binfos); VEC_free (ipa_agg_jump_function_p, heap, known_aggs); @@ -2929,6 +2927,8 @@ do_estimate_edge_time (struct cgraph_edge *edge) gcc_checking_assert (es->call_stmt_size); VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).size = ret_size + (ret_size >= 0); + VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).hints + = hints + 1; } return ret; } @@ -2967,7 +2967,7 @@ do_estimate_edge_growth (struct cgraph_edge *edge) &clause, &known_vals, &known_binfos, &known_aggs); estimate_node_size_and_time (callee, clause, known_vals, known_binfos, - known_aggs, &size, NULL, NULL); + known_aggs, &size, NULL, NULL, NULL); VEC_free (tree, heap, known_vals); VEC_free (tree, heap, known_binfos); VEC_free (ipa_agg_jump_function_p, heap, known_aggs); @@ -2976,6 +2976,47 @@ do_estimate_edge_growth (struct cgraph_edge *edge) } +/* Estimate the growth of the caller when inlining EDGE. + Only to be called via estimate_edge_size. */ + +inline_hints +do_estimate_edge_hints (struct cgraph_edge *edge) +{ + inline_hints hints; + struct cgraph_node *callee; + clause_t clause; + VEC (tree, heap) *known_vals; + VEC (tree, heap) *known_binfos; + VEC (ipa_agg_jump_function_p, heap) *known_aggs; + + /* When we do caching, use do_estimate_edge_time to populate the entry. */ + + if (edge_growth_cache) + { + do_estimate_edge_time (edge); + hints = VEC_index (edge_growth_cache_entry, + edge_growth_cache, + edge->uid).hints; + gcc_checking_assert (hints); + return hints - 1; + } + + callee = cgraph_function_or_thunk_node (edge->callee, NULL); + + /* Early inliner runs without caching, go ahead and do the dirty work. */ + gcc_checking_assert (edge->inline_failed); + evaluate_properties_for_edge (edge, true, + &clause, &known_vals, &known_binfos, + &known_aggs); + estimate_node_size_and_time (callee, clause, known_vals, known_binfos, + known_aggs, NULL, NULL, &hints, NULL); + VEC_free (tree, heap, known_vals); + VEC_free (tree, heap, known_binfos); + VEC_free (ipa_agg_jump_function_p, heap, known_aggs); + return hints; +} + + /* Estimate self time of the function NODE after inlining EDGE. */ int |