Commit 100411f8 by Jan Hubicka Committed by Jan Hubicka

ipa-inline.c (want_inline_function_called_once_p): Rename to ...


	* ipa-inline.c (want_inline_function_called_once_p): Rename to ...
	(want_inline_function_to_all_callers_p): check also functions with
	multiple callers.
	(ipa_inline): Handle inlining for size into multiple callers.

From-SVN: r192946
parent 8277de34
2012-10-29 Jan Hubicka <jh@suse.cz>
* ipa-inline.c (want_inline_function_called_once_p): Rename to ...
(want_inline_function_to_all_callers_p): check also functions with
multiple callers.
(ipa_inline): Handle inlining for size into multiple callers.
2012-10-29 Richard Guenther <rguenther@suse.de> 2012-10-29 Richard Guenther <rguenther@suse.de>
PR middle-end/53695 PR middle-end/53695
...@@ -681,34 +681,41 @@ check_caller_edge (struct cgraph_node *node, void *edge) ...@@ -681,34 +681,41 @@ check_caller_edge (struct cgraph_node *node, void *edge)
} }
/* Decide if NODE is called once inlining it would eliminate need /* Decide if inlining NODE would reduce unit size by eliminating
for the offline copy of function. */ the offline copy of function.
When COLD is true the cold calls are considered, too. */
static bool static bool
want_inline_function_called_once_p (struct cgraph_node *node) want_inline_function_to_all_callers_p (struct cgraph_node *node, bool cold)
{ {
struct cgraph_node *function = cgraph_function_or_thunk_node (node, NULL); struct cgraph_node *function = cgraph_function_or_thunk_node (node, NULL);
struct cgraph_edge *e;
bool has_hot_call = false;
/* Does it have callers? */
if (!node->callers)
return false;
/* Already inlined? */ /* Already inlined? */
if (function->global.inlined_to) if (function->global.inlined_to)
return false; return false;
/* Zero or more then one callers? */ if (cgraph_function_or_thunk_node (node, NULL) != node)
if (!node->callers return false;
|| node->callers->next_caller) /* Inlining into all callers would increase size? */
if (estimate_growth (node) > 0)
return false; return false;
/* Maybe other aliases has more direct calls. */ /* Maybe other aliases has more direct calls. */
if (cgraph_for_node_and_aliases (node, check_caller_edge, node->callers, true)) if (cgraph_for_node_and_aliases (node, check_caller_edge, node->callers, true))
return false; return false;
/* Recursive call makes no sense to inline. */ /* All inlines must be possible. */
if (cgraph_edge_recursive_p (node->callers)) for (e = node->callers; e; e = e->next_caller)
return false; {
/* External functions are not really in the unit, so inlining if (!can_inline_edge_p (e, true))
them when called once would just increase the program size. */ return false;
if (DECL_EXTERNAL (function->symbol.decl)) if (!has_hot_call && cgraph_maybe_hot_edge_p (e))
return false; has_hot_call = 1;
/* Offline body must be optimized out. */ }
if (!cgraph_will_be_removed_from_program_if_no_direct_calls (function))
return false; if (!cold && !has_hot_call)
if (!can_inline_edge_p (node->callers, true))
return false; return false;
return true; return true;
} }
...@@ -1729,14 +1736,16 @@ ipa_inline (void) ...@@ -1729,14 +1736,16 @@ ipa_inline (void)
symtab_remove_unreachable_nodes (true, dump_file); symtab_remove_unreachable_nodes (true, dump_file);
free (order); free (order);
/* We already perform some inlining of functions called once during /* Inline functions with a property that after inlining into all callers the
inlining small functions above. After unreachable nodes are removed, code size will shrink because the out-of-line copy is eliminated.
we still might do a quick check that nothing new is found. */ We do this regardless on the callee size as long as function growth limits
are met. */
if (flag_inline_functions_called_once) if (flag_inline_functions_called_once)
{ {
int cold; int cold;
if (dump_file) if (dump_file)
fprintf (dump_file, "\nDeciding on functions called once:\n"); fprintf (dump_file,
"\nDeciding on functions to be inlined into all callers:\n");
/* Inlining one function called once has good chance of preventing /* Inlining one function called once has good chance of preventing
inlining other function into the same callee. Ideally we should inlining other function into the same callee. Ideally we should
...@@ -1757,31 +1766,30 @@ ipa_inline (void) ...@@ -1757,31 +1766,30 @@ ipa_inline (void)
{ {
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
{ {
if (want_inline_function_called_once_p (node) if (want_inline_function_to_all_callers_p (node, cold))
&& (cold while (node->callers && !node->global.inlined_to)
|| cgraph_maybe_hot_edge_p (node->callers))) {
{ struct cgraph_node *caller = node->callers->caller;
struct cgraph_node *caller = node->callers->caller;
if (dump_file)
if (dump_file) {
{ fprintf (dump_file,
fprintf (dump_file, "\nInlining %s size %i.\n",
"\nInlining %s size %i.\n", cgraph_node_name (node),
cgraph_node_name (node), inline_summary (node)->size);
inline_summary (node)->size); fprintf (dump_file,
" Called once from %s %i insns.\n",
cgraph_node_name (node->callers->caller),
inline_summary (node->callers->caller)->size);
}
inline_call (node->callers, true, NULL, NULL, true);
if (dump_file)
fprintf (dump_file, fprintf (dump_file,
" Called once from %s %i insns.\n", " Inlined into %s which now has %i size\n",
cgraph_node_name (node->callers->caller), cgraph_node_name (caller),
inline_summary (node->callers->caller)->size); inline_summary (caller)->size);
} }
inline_call (node->callers, true, NULL, NULL, true);
if (dump_file)
fprintf (dump_file,
" Inlined into %s which now has %i size\n",
cgraph_node_name (caller),
inline_summary (caller)->size);
}
} }
} }
} }
......
2012-10-29 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/inline-6.c: New testcase.
2012-10-29 Vladimir Makarov <vmakarov@redhat.com> 2012-10-29 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/55106 PR rtl-optimization/55106
......
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