Commit a5b1779f by Jan Hubicka Committed by Jan Hubicka

ipa-inline-transform.c (can_remove_node_now_p): Move out of...

	* ipa-inline-transform.c (can_remove_node_now_p): Move out of...
	(clone_inlined_nodes): ... here.
	(inline_call): Use cgraph_function_or_thunk_node; redirect edge
	to real destination prior inlining.
	* ipa-inline.c (caller_growth_limits, can_inline_edge_p,
	can_early_inline_edge_p, want_early_inline_function_p,
	want_early_inline_function_p, want_inline_small_function_p,
	want_inline_self_recursive_call_p, want_inline_function_called_once_p,
	edge_badness, update_all_callee_keys, lookup_recursive_calls,
	add_new_edges_to_heap, inline_small_functions, flatten_function,
	inline_always_inline_functions, early_inline_small_functions): Use
	cgraph_function_or_thunk_node.
	* ipa-inline-analysis.c (evaluate_conditions_for_edge,
	dump_inline_edge_summary, estimate_function_body_sizes): Likewise.
	(do_estimate_edge_growth_1): Break out from ...
	(do_estimate_growth) ... here; walk aliases.
	(inline_generate_summary): Skip aliases.

From-SVN: r174901
parent c1ae3ca5
2011-06-10 Jan Hubicka <jh@suse.cz>
* ipa-inline-transform.c (can_remove_node_now_p): Move out of...
(clone_inlined_nodes): ... here.
(inline_call): Use cgraph_function_or_thunk_node; redirect edge
to real destination prior inlining.
* ipa-inline.c (caller_growth_limits, can_inline_edge_p,
can_early_inline_edge_p, want_early_inline_function_p,
want_early_inline_function_p, want_inline_small_function_p,
want_inline_self_recursive_call_p, want_inline_function_called_once_p,
edge_badness, update_all_callee_keys, lookup_recursive_calls,
add_new_edges_to_heap, inline_small_functions, flatten_function,
inline_always_inline_functions, early_inline_small_functions): Use
cgraph_function_or_thunk_node.
* ipa-inline-analysis.c (evaluate_conditions_for_edge,
dump_inline_edge_summary, estimate_function_body_sizes): Likewise.
(do_estimate_edge_growth_1): Break out from ...
(do_estimate_growth) ... here; walk aliases.
(inline_generate_summary): Skip aliases.
2011-06-10 Richard Guenther <rguenther@suse.de>
* tree-ssa-forwprop.c (ssa_forward_propagate_and_combine):
......
......@@ -589,7 +589,8 @@ static clause_t
evaluate_conditions_for_edge (struct cgraph_edge *e, bool inline_p)
{
clause_t clause = inline_p ? 0 : 1 << predicate_not_inlined_condition;
struct inline_summary *info = inline_summary (e->callee);
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
struct inline_summary *info = inline_summary (callee);
int i;
if (ipa_node_params_vector && info->conds
......@@ -615,7 +616,7 @@ evaluate_conditions_for_edge (struct cgraph_edge *e, bool inline_p)
if (cst)
VEC_replace (tree, known_vals, i, cst);
}
clause = evaluate_conditions_for_known_args (e->callee,
clause = evaluate_conditions_for_known_args (callee,
inline_p, known_vals);
VEC_free (tree, heap, known_vals);
}
......@@ -919,9 +920,10 @@ dump_inline_edge_summary (FILE * f, int indent, struct cgraph_node *node,
for (edge = node->callees; edge; edge = edge->next_callee)
{
struct inline_edge_summary *es = inline_edge_summary (edge);
struct cgraph_node *callee = cgraph_function_or_thunk_node (edge->callee, NULL);
fprintf (f, "%*s%s/%i %s\n%*s loop depth:%2i freq:%4i size:%2i time: %2i callee size:%2i stack:%2i",
indent, "", cgraph_node_name (edge->callee),
edge->callee->uid,
indent, "", cgraph_node_name (callee),
callee->uid,
!edge->inline_failed ? "inlined"
: cgraph_inline_failed_string (edge->inline_failed),
indent, "",
......@@ -929,8 +931,8 @@ dump_inline_edge_summary (FILE * f, int indent, struct cgraph_node *node,
edge->frequency,
es->call_stmt_size,
es->call_stmt_time,
(int)inline_summary (edge->callee)->size,
(int)inline_summary (edge->callee)->estimated_stack_size);
(int)inline_summary (callee)->size,
(int)inline_summary (callee)->estimated_stack_size);
if (es->predicate)
{
fprintf (f, " predicate: ");
......@@ -942,10 +944,10 @@ dump_inline_edge_summary (FILE * f, int indent, struct cgraph_node *node,
{
fprintf (f, "%*sStack frame offset %i, callee self size %i, callee size %i\n",
indent+2, "",
(int)inline_summary (edge->callee)->stack_frame_offset,
(int)inline_summary (edge->callee)->estimated_self_stack_size,
(int)inline_summary (edge->callee)->estimated_stack_size);
dump_inline_edge_summary (f, indent+2, edge->callee, info);
(int)inline_summary (callee)->stack_frame_offset,
(int)inline_summary (callee)->estimated_self_stack_size,
(int)inline_summary (callee)->estimated_stack_size);
dump_inline_edge_summary (f, indent+2, callee, info);
}
}
for (edge = node->indirect_calls; edge; edge = edge->next_callee)
......@@ -1525,7 +1527,10 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
/* Do not inline calls where we cannot triviall work around
mismatches in argument or return types. */
if (edge->callee
&& !gimple_check_call_matching_types (stmt, edge->callee->decl))
&& cgraph_function_or_thunk_node (edge->callee, NULL)
&& !gimple_check_call_matching_types (stmt,
cgraph_function_or_thunk_node (edge->callee,
NULL)->decl))
{
edge->call_stmt_cannot_inline_p = true;
gimple_call_set_cannot_inline (stmt, true);
......@@ -2110,6 +2115,7 @@ int
do_estimate_edge_growth (struct cgraph_edge *edge)
{
int size;
struct cgraph_node *callee;
/* When we do caching, use do_estimate_edge_time to populate the entry. */
......@@ -2122,10 +2128,11 @@ do_estimate_edge_growth (struct cgraph_edge *edge)
gcc_checking_assert (size);
return size - (size > 0);
}
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);
estimate_node_size_and_time (edge->callee,
estimate_node_size_and_time (callee,
evaluate_conditions_for_edge (edge, true),
&size, NULL);
gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size);
......@@ -2171,15 +2178,20 @@ estimate_size_after_inlining (struct cgraph_node *node,
}
/* Estimate the growth caused by inlining NODE into all callees. */
struct growth_data
{
bool self_recursive;
int growth;
};
int
do_estimate_growth (struct cgraph_node *node)
/* Worker for do_estimate_growth. Collect growth for all callers. */
static bool
do_estimate_growth_1 (struct cgraph_node *node, void *data)
{
int growth = 0;
struct cgraph_edge *e;
bool self_recursive = false;
struct inline_summary *info = inline_summary (node);
struct growth_data *d = (struct growth_data *) data;
for (e = node->callers; e; e = e->next_caller)
{
......@@ -2188,37 +2200,50 @@ do_estimate_growth (struct cgraph_node *node)
if (e->caller == node
|| (e->caller->global.inlined_to
&& e->caller->global.inlined_to == node))
self_recursive = true;
growth += estimate_edge_growth (e);
d->self_recursive = true;
d->growth += estimate_edge_growth (e);
}
return false;
}
/* Estimate the growth caused by inlining NODE into all callees. */
int
do_estimate_growth (struct cgraph_node *node)
{
struct growth_data d = {0, false};
struct inline_summary *info = inline_summary (node);
cgraph_for_node_and_aliases (node, do_estimate_growth_1, &d, true);
/* For self recursive functions the growth estimation really should be
infinity. We don't want to return very large values because the growth
plays various roles in badness computation fractions. Be sure to not
return zero or negative growths. */
if (self_recursive)
growth = growth < info->size ? info->size : growth;
if (d.self_recursive)
d.growth = d.growth < info->size ? info->size : d.growth;
else
{
if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
&& !DECL_EXTERNAL (node->decl))
growth -= info->size;
if (!DECL_EXTERNAL (node->decl)
&& !cgraph_will_be_removed_from_program_if_no_direct_calls (node))
d.growth -= info->size;
/* COMDAT functions are very often not shared across multiple units since they
come from various template instantiations. Take this into account. */
come from various template instantiations. Take this into account.
FIXME: allow also COMDATs with COMDAT aliases. */
else if (DECL_COMDAT (node->decl)
&& cgraph_can_remove_if_no_direct_calls_p (node))
growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
d.growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
}
if (node_growth_cache)
{
if ((int)VEC_length (int, node_growth_cache) <= node->uid)
VEC_safe_grow_cleared (int, heap, node_growth_cache, cgraph_max_uid);
VEC_replace (int, node_growth_cache, node->uid, growth + (growth >= 0));
VEC_replace (int, node_growth_cache, node->uid, d.growth + (d.growth >= 0));
}
return growth;
return d.growth;
}
......@@ -2282,6 +2307,7 @@ inline_generate_summary (void)
ipa_register_cgraph_hooks ();
FOR_EACH_DEFINED_FUNCTION (node)
if (!node->alias)
inline_analyze_function (node);
}
......
......@@ -76,6 +76,35 @@ update_noncloned_frequencies (struct cgraph_node *node,
}
}
/* We removed or are going to remove the last call to NODE.
Return true if we can and want proactively remove the NODE now.
This is important to do, since we want inliner to know when offline
copy of function was removed. */
static bool
can_remove_node_now_p (struct cgraph_node *node)
{
/* FIXME: When address is taken of DECL_EXTERNAL function we still
can remove its offline copy, but we would need to keep unanalyzed node in
the callgraph so references can point to it. */
return (!node->address_taken
&& cgraph_can_remove_if_no_direct_calls_p (node)
/* Inlining might enable more devirtualizing, so we want to remove
those only after all devirtualizable virtual calls are processed.
Lacking may edges in callgraph we just preserve them post
inlining. */
&& (!DECL_VIRTUAL_P (node->decl)
|| (!DECL_COMDAT (node->decl)
&& !DECL_EXTERNAL (node->decl)))
/* Don't reuse if more than one function shares a comdat group.
If the other function(s) are needed, we need to emit even
this function out of line. */
&& !node->same_comdat_group
/* During early inlining some unanalyzed cgraph nodes might be in the
callgraph and they might reffer the function in question. */
&& !cgraph_new_nodes);
}
/* E is expected to be an edge being inlined. Clone destination node of
the edge and redirect it to the new clone.
......@@ -97,25 +126,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
/* Recursive inlining never wants the master clone to
be overwritten. */
&& update_original
/* FIXME: When address is taken of DECL_EXTERNAL function we still
can remove its offline copy, but we would need to keep unanalyzed
node in the callgraph so references can point to it. */
&& !e->callee->address_taken
&& cgraph_can_remove_if_no_direct_calls_p (e->callee)
/* Inlining might enable more devirtualizing, so we want to remove
those only after all devirtualizable virtual calls are processed.
Lacking may edges in callgraph we just preserve them post
inlining. */
&& (!DECL_VIRTUAL_P (e->callee->decl)
|| (!DECL_COMDAT (e->callee->decl)
&& !DECL_EXTERNAL (e->callee->decl)))
/* Don't reuse if more than one function shares a comdat group.
If the other function(s) are needed, we need to emit even
this function out of line. */
&& !e->callee->same_comdat_group
/* During early inlining some unanalyzed cgraph nodes might be in the
callgraph and they might reffer the function in question. */
&& !cgraph_new_nodes)
&& can_remove_node_now_p (e->callee))
{
gcc_assert (!e->callee->global.inlined_to);
if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
......@@ -164,19 +175,25 @@ inline_call (struct cgraph_edge *e, bool update_original,
int old_size = 0, new_size = 0;
struct cgraph_node *to = NULL;
struct cgraph_edge *curr = e;
struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
/* Don't inline inlined edges. */
gcc_assert (e->inline_failed);
/* Don't even think of inlining inline clone. */
gcc_assert (!e->callee->global.inlined_to);
gcc_assert (!callee->global.inlined_to);
e->inline_failed = CIF_OK;
DECL_POSSIBLY_INLINED (e->callee->decl) = true;
DECL_POSSIBLY_INLINED (callee->decl) = true;
to = e->caller;
if (to->global.inlined_to)
to = to->global.inlined_to;
/* If aliases are involved, redirect edge to the actual destination and
possibly remove the aliases. */
if (e->callee != callee)
cgraph_redirect_edge_callee (e, callee);
clone_inlined_nodes (e, true, update_original, overall_size);
gcc_assert (curr->callee->global.inlined_to == to);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment