diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-25 19:23:15 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-25 19:23:15 +0000 |
commit | 18b64b3435311eed114dc13fb9c12d3a13d90b1d (patch) | |
tree | 81e2371d565ef985b588b64d19e5b6de88ca0df3 /gcc/ipa-inline-analysis.c | |
parent | b1f53c8b0389c810f9b94095ff63ebcedbf167a5 (diff) | |
download | gcc-18b64b3435311eed114dc13fb9c12d3a13d90b1d.tar.gz |
* ipa-cp.c (ipcp_discover_new_direct_edges): If something was turned
to direct call update the summary.
* ipa-inline-transform.c (inline_call): Sanity check that summaries
match the predicted effect; fix updating of summary after edge
redirection.
* ipa-inline-analysis.c (inline_node_duplication_hook): Do not try
to update the summary and recompute it instead.
(estimate_function_body_sizes): Fix self size estimation; double
check that it agrees with inline_update_overall_summary.
(estimate_edge_size_and_time): Handle devirtualizaiton costs.
(estimate_edge_devirt_benefit): Update to be called from
estimate_edge_size_and_time.
(estimate_calls_size_and_time): Update.
(estimate_node_size_and_time): Watch overflows.
(inline_merge_summary): Likewise.
* ipa-prob.c: Include ipa-inline.h
(ipa_make_edge_direct_to_target): After redirection update the summary.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192821 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-inline-analysis.c')
-rw-r--r-- | gcc/ipa-inline-analysis.c | 143 |
1 files changed, 74 insertions, 69 deletions
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 6cea94225b0..915f5f2059b 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -1081,7 +1081,6 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, struct predicate true_pred = true_predicate (); size_time_entry *e; int optimized_out_size = 0; - gcov_type optimized_out_time = 0; bool inlined_to_p = false; struct cgraph_edge *edge; @@ -1123,10 +1122,7 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, possible_truths, info); if (false_predicate_p (&new_predicate)) - { - optimized_out_size += e->size; - optimized_out_time += e->time; - } + optimized_out_size += e->size; else account_size_time (info, e->size, e->time, &new_predicate); } @@ -1149,9 +1145,6 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, && !false_predicate_p (es->predicate)) { optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE; - optimized_out_time += (es->call_stmt_time - * (INLINE_TIME_SCALE / CGRAPH_FREQ_BASE) - * edge->frequency); edge->frequency = 0; } edge_set_predicate (edge, &new_predicate); @@ -1174,9 +1167,6 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, && !false_predicate_p (es->predicate)) { optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE; - optimized_out_time += (es->call_stmt_time - * (INLINE_TIME_SCALE / CGRAPH_FREQ_BASE) - * edge->frequency); edge->frequency = 0; } edge_set_predicate (edge, &new_predicate); @@ -1193,22 +1183,7 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, about updating self sizes, because size vectors already contains sizes of the calees. */ gcc_assert (!inlined_to_p - || (!optimized_out_size && !optimized_out_time)); - - info->size -= optimized_out_size / INLINE_SIZE_SCALE; - info->self_size -= optimized_out_size / INLINE_SIZE_SCALE; - gcc_assert (info->size > 0); - gcc_assert (info->self_size > 0); - - optimized_out_time /= INLINE_TIME_SCALE; - if (optimized_out_time > MAX_TIME) - optimized_out_time = MAX_TIME; - info->time -= optimized_out_time; - info->self_time -= optimized_out_time; - if (info->time < 0) - info->time = 0; - if (info->self_time < 0) - info->self_time = 0; + || !optimized_out_size); } else { @@ -1226,6 +1201,7 @@ inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, set_hint_predicate (&info->loop_stride, p); } } + inline_update_overall_summary (dst); } @@ -2405,8 +2381,6 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) struct predicate p; this_time *= freq; - time += this_time; - size += this_size; prob = eliminated_by_inlining_prob (stmt); if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS)) @@ -2420,6 +2394,12 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) else p = true_predicate (); + if (!false_predicate_p (&p)) + { + time += this_time; + size += this_size; + } + /* We account everything but the calls. Calls have their own size/time info attached to cgraph edges. This is necessary in order to make the cost disappear after inlining. */ @@ -2621,6 +2601,12 @@ compute_inline_parameters (struct cgraph_node *node, bool early) info->size = info->self_size; info->stack_frame_offset = 0; info->estimated_stack_size = info->estimated_self_stack_size; +#ifdef ENABLE_CHECKING + inline_update_overall_summary (node); + gcc_assert (info->time == info->self_time + && info->size == info->self_size); +#endif + pop_cfun (); } @@ -2655,38 +2641,24 @@ struct gimple_opt_pass pass_inline_parameters = }; -/* Increase SIZE and TIME for size and time needed to handle edge E. */ - -static void -estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time, - int prob) -{ - struct inline_edge_summary *es = inline_edge_summary (e); - *size += es->call_stmt_size * INLINE_SIZE_SCALE; - *time += (es->call_stmt_time * prob / REG_BR_PROB_BASE - * e->frequency * (INLINE_TIME_SCALE / CGRAPH_FREQ_BASE)); - if (*time > MAX_TIME * INLINE_TIME_SCALE) - *time = MAX_TIME * INLINE_TIME_SCALE; -} - - /* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and KNOWN_BINFOS. */ static bool estimate_edge_devirt_benefit (struct cgraph_edge *ie, - int *size, int *time, int prob, + int *size, int *time, VEC (tree, heap) *known_vals, VEC (tree, heap) *known_binfos, VEC (ipa_agg_jump_function_p, heap) *known_aggs) { tree target; - int time_diff, size_diff; struct cgraph_node *callee; struct inline_summary *isummary; if (!known_vals && !known_binfos) return false; + if (!flag_indirect_inlining) + return false; target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos, known_aggs); @@ -2694,12 +2666,10 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, 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) - * INLINE_SIZE_SCALE); - *size -= size_diff; - time_diff = ((eni_time_weights.indirect_call_cost - eni_time_weights.call_cost) - * INLINE_TIME_SCALE * prob / REG_BR_PROB_BASE); - *time -= time_diff; + *size -= (eni_size_weights.indirect_call_cost - eni_size_weights.call_cost); + *time -= (eni_time_weights.indirect_call_cost - eni_time_weights.call_cost); + gcc_checking_assert (*time >= 0); + gcc_checking_assert (*size >= 0); callee = cgraph_get_node (target); if (!callee || !callee->analyzed) @@ -2708,6 +2678,34 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, return isummary->inlinable; } +/* Increase SIZE and TIME for size and time needed to handle edge E. */ + +static inline void +estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time, + int prob, + VEC (tree, heap) *known_vals, + VEC (tree, heap) *known_binfos, + VEC (ipa_agg_jump_function_p, heap) *known_aggs, + inline_hints *hints) + +{ + struct inline_edge_summary *es = inline_edge_summary (e); + int call_size = es->call_stmt_size; + int call_time = es->call_stmt_time; + if (!e->callee + && estimate_edge_devirt_benefit (e, &call_size, &call_time, + known_vals, known_binfos, known_aggs) + && hints + && cgraph_maybe_hot_edge_p (e)) + *hints |= INLINE_HINT_indirect_call; + *size += call_size * INLINE_SIZE_SCALE; + *time += call_time * prob / REG_BR_PROB_BASE + * e->frequency * (INLINE_TIME_SCALE / CGRAPH_FREQ_BASE); + if (*time > MAX_TIME * INLINE_TIME_SCALE) + *time = MAX_TIME * INLINE_TIME_SCALE; +} + + /* Increase SIZE and TIME for size and time needed to handle all calls in NODE. POSSIBLE_TRUTHS, KNOWN_VALS and KNOWN_BINFOS describe context of the call @@ -2731,7 +2729,9 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, { /* Predicates of calls shall not use NOT_CHANGED codes, sowe do not need to compute probabilities. */ - estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); + estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE, + known_vals, known_binfos, known_aggs, + hints); } else estimate_calls_size_and_time (e->callee, size, time, hints, @@ -2743,14 +2743,9 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, { struct inline_edge_summary *es = inline_edge_summary (e); if (!es->predicate || evaluate_predicate (es->predicate, possible_truths)) - { - estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); - 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; - } + estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE, + known_vals, known_binfos, known_aggs, + hints); } } @@ -2772,7 +2767,8 @@ estimate_node_size_and_time (struct cgraph_node *node, { struct inline_summary *info = inline_summary (node); size_time_entry *e; - int size = 0, time = 0; + int size = 0; + int time = 0; inline_hints hints = 0; int i; @@ -2801,6 +2797,8 @@ estimate_node_size_and_time (struct cgraph_node *node, if (evaluate_predicate (&e->predicate, possible_truths)) { size += e->size; + gcc_checking_assert (e->time >= 0); + gcc_checking_assert (time >= 0); if (!inline_param_summary) time += e->time; else @@ -2809,10 +2807,17 @@ estimate_node_size_and_time (struct cgraph_node *node, &e->predicate, possible_truths, inline_param_summary); - time += e->time * prob / REG_BR_PROB_BASE; + gcc_checking_assert (prob >= 0); + gcc_checking_assert (prob <= REG_BR_PROB_BASE); + time += ((gcov_type)e->time * prob) / REG_BR_PROB_BASE; } + if (time > MAX_TIME * INLINE_TIME_SCALE) + time = MAX_TIME * INLINE_TIME_SCALE; + gcc_checking_assert (time >= 0); } + gcc_checking_assert (size >= 0); + gcc_checking_assert (time >= 0); if (info->loop_iterations && !evaluate_predicate (info->loop_iterations, possible_truths)) @@ -2821,18 +2826,18 @@ estimate_node_size_and_time (struct cgraph_node *node, && !evaluate_predicate (info->loop_stride, possible_truths)) hints |=INLINE_HINT_loop_stride; - if (time > MAX_TIME * INLINE_TIME_SCALE) - time = MAX_TIME * INLINE_TIME_SCALE; 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; + gcc_checking_assert (size >= 0); + gcc_checking_assert (time >= 0); + time = RDIV (time, INLINE_TIME_SCALE); + size = RDIV (size, INLINE_SIZE_SCALE); if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\n size:%i time:%i\n", size, time); + fprintf (dump_file, "\n size:%i time:%i\n", (int)size, (int)time); if (ret_time) *ret_time = time; if (ret_size) @@ -3224,7 +3229,7 @@ inline_merge_summary (struct cgraph_edge *edge) int prob = predicate_probability (callee_info->conds, &e->predicate, clause, es->param); - add_time = add_time * prob / REG_BR_PROB_BASE; + add_time = ((gcov_type)add_time * prob) / REG_BR_PROB_BASE; if (add_time > MAX_TIME * INLINE_TIME_SCALE) add_time = MAX_TIME * INLINE_TIME_SCALE; if (prob != REG_BR_PROB_BASE |