===================================================================
@@ -176,7 +176,8 @@ ipa_fn_summary::account_size_time (int s
if (!size && time == 0 && table)
return;
- gcc_assert (time >= 0);
+ /* Only for calls we are unaccounting what we previously recoreded. */
+ gcc_checking_assert (time >= 0 || call);
for (i = 0; vec_safe_iterate (table, i, &e); i++)
if (e->exec_predicate == exec_pred
@@ -226,6 +227,10 @@ ipa_fn_summary::account_size_time (int s
{
e->size += size;
e->time += time;
+ gcc_checking_assert (e->time >= -1);
+ /* Tolerate small roundoff issues. */
+ if (e->time < 0)
+ e->time = 0;
}
}
@@ -3897,6 +3902,21 @@ ipa_merge_fn_summary_after_inlining (str
info->estimated_stack_size = peak;
inline_update_callee_summaries (edge->callee, es->loop_depth);
+ if (info->call_size_time_table)
+ {
+ int edge_size = 0;
+ sreal edge_time = 0;
+
+ estimate_edge_size_and_time (edge, &edge_size, NULL, &edge_time, vNULL,
+ vNULL, vNULL, 0);
+ /* Unaccount size and time of the optimized out call. */
+ info->account_size_time (-edge_size, -edge_time,
+ es->predicate ? *es->predicate : true,
+ es->predicate ? *es->predicate : true,
+ true);
+ /* Account new calls. */
+ summarize_calls_size_and_time (edge->callee, info);
+ }
/* Free summaries that are not maintained for inline clones/edges. */
ipa_call_summaries->remove (edge);
@@ -3905,10 +3925,11 @@ ipa_merge_fn_summary_after_inlining (str
}
/* For performance reasons ipa_merge_fn_summary_after_inlining is not updating
- overall size and time. Recompute it. */
+ overall size and time. Recompute it.
+ If RESET is true also recompute call_time_size_table. */
void
-ipa_update_overall_fn_summary (struct cgraph_node *node)
+ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset)
{
class ipa_fn_summary *info = ipa_fn_summaries->get (node);
class ipa_size_summary *size_info = ipa_size_summaries->get (node);
@@ -3923,7 +3944,8 @@ ipa_update_overall_fn_summary (struct cg
info->time += e->time;
}
info->min_size = (*info->size_time_table)[0].size;
- vec_free (info->call_size_time_table);
+ if (reset)
+ vec_free (info->call_size_time_table);
if (node->callees || node->indirect_calls)
estimate_calls_size_and_time (node, &size_info->size, &info->min_size,
&info->time, NULL,
===================================================================
@@ -358,7 +358,7 @@ void estimate_ipcp_clone_size_and_time (
int *, sreal *, sreal *,
ipa_hints *);
void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge);
-void ipa_update_overall_fn_summary (struct cgraph_node *node);
+void ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset = true);
void compute_fn_summary (struct cgraph_node *, bool);
===================================================================
@@ -489,9 +489,9 @@ inline_call (struct cgraph_edge *e, bool
mark_all_inlined_calls_cdtor (e->callee);
if (opt_for_fn (e->caller->decl, optimize))
new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
- check_speculations (e->callee, new_edges);
+ bool removed_p = check_speculations (e->callee, new_edges);
if (update_overall_summary)
- ipa_update_overall_fn_summary (to);
+ ipa_update_overall_fn_summary (to, new_edges_found || removed_p);
else
/* Update self size by the estimate so overall function growth limits
work for further inlining into this function. Before inlining
===================================================================
@@ -672,14 +672,29 @@ want_early_inline_function_p (struct cgr
}
else
{
- int growth = estimate_edge_growth (e);
+ /* First take care of very large functions. */
+ int min_growth = estimate_min_edge_growth (e), growth = 0;
int n;
int early_inlining_insns = opt_for_fn (e->caller->decl, optimize) >= 3
? param_early_inlining_insns
: param_early_inlining_insns_o2;
+ if (min_growth > early_inlining_insns)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt,
+ " will not early inline: %C->%C, "
+ "call is cold and code would grow "
+ "at least by %i\n",
+ e->caller, callee,
+ min_growth);
+ want_inline = false;
+ }
+ else
+ growth = estimate_edge_growth (e);
+
- if (growth <= param_max_inline_insns_size)
+ if (!want_inline || growth <= param_max_inline_insns_size)
;
else if (!e->maybe_hot_p ())
{
===================================================================
@@ -82,6 +82,16 @@ estimate_edge_size (struct cgraph_edge *
/* Return estimated callee growth after inlining EDGE. */
static inline int
+estimate_min_edge_growth (struct cgraph_edge *edge)
+{
+ ipa_call_summary *s = ipa_call_summaries->get (edge);
+ struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
+ return (ipa_fn_summaries->get (callee)->min_size - s->call_stmt_size);
+}
+
+/* Return estimated callee growth after inlining EDGE. */
+
+static inline int
estimate_edge_growth (struct cgraph_edge *edge)
{
ipa_call_summary *s = ipa_call_summaries->get (edge);