ipa-inline-analysis.c (check_callers): Check node->can_remove_if_no_direct_calls_and_refs_p.

* ipa-inline-analysis.c (check_callers): Check
	node->can_remove_if_no_direct_calls_and_refs_p.
	(growth_likely_positive): Reorganize to call
	can_remove_if_no_direct_calls_p later.
	* cgraph.h (will_be_removed_from_program_if_no_direct_calls_p,
	will_be_removed_from_program_if_no_direct_calls_p): Add 
	will_inline parameter.
	* cgraph.c (cgraph_node::can_remove_if_no_direct_calls_p,
	cgraph_node::will_be_removed_from_program_if_no_direct_calls_p):
	Handle inliner case correctly.

From-SVN: r221277
This commit is contained in:
Jan Hubicka 2015-03-09 05:53:54 +01:00 committed by Jan Hubicka
parent 68ca4ac90b
commit e0d514da7b
4 changed files with 68 additions and 32 deletions

View File

@ -1,3 +1,16 @@
2015-03-08 Jan Hubicka <hubicka@ucw.cz>
* ipa-inline-analysis.c (check_callers): Check
node->can_remove_if_no_direct_calls_and_refs_p.
(growth_likely_positive): Reorganize to call
can_remove_if_no_direct_calls_p later.
* cgraph.h (will_be_removed_from_program_if_no_direct_calls_p,
will_be_removed_from_program_if_no_direct_calls_p): Add
will_inline parameter.
* cgraph.c (cgraph_node::can_remove_if_no_direct_calls_p,
cgraph_node::will_be_removed_from_program_if_no_direct_calls_p):
Handle inliner case correctly.
2015-03-09 Thomas Preud'homme <thomas.preudhomme@arm.com> 2015-03-09 Thomas Preud'homme <thomas.preudhomme@arm.com>
PR tree-optimization/63743 PR tree-optimization/63743

View File

@ -2415,7 +2415,7 @@ nonremovable_p (cgraph_node *node, void *)
calls to THIS. */ calls to THIS. */
bool bool
cgraph_node::can_remove_if_no_direct_calls_p (void) cgraph_node::can_remove_if_no_direct_calls_p (bool will_inline)
{ {
struct ipa_ref *ref; struct ipa_ref *ref;
@ -2430,6 +2430,9 @@ cgraph_node::can_remove_if_no_direct_calls_p (void)
return !call_for_symbol_and_aliases (nonremovable_p, NULL, true); return !call_for_symbol_and_aliases (nonremovable_p, NULL, true);
} }
if (will_inline && address_taken)
return false;
/* Otheriwse check if we can remove the symbol itself and then verify /* Otheriwse check if we can remove the symbol itself and then verify
that only uses of the comdat groups are direct call to THIS that only uses of the comdat groups are direct call to THIS
or its aliases. */ or its aliases. */
@ -2454,12 +2457,16 @@ cgraph_node::can_remove_if_no_direct_calls_p (void)
/* If we see different symbol than THIS, be sure to check calls. */ /* If we see different symbol than THIS, be sure to check calls. */
if (next->ultimate_alias_target () != target) if (next->ultimate_alias_target () != target)
for (cgraph_edge *e = next->callers; e; e = e->next_caller) for (cgraph_edge *e = next->callers; e; e = e->next_caller)
if (e->caller->get_comdat_group () != get_comdat_group ()) if (e->caller->get_comdat_group () != get_comdat_group ()
|| will_inline)
return false; return false;
for (int i = 0; next->iterate_referring (i, ref); i++) /* If function is not being inlined, we care only about
if (ref->referring->get_comdat_group () != get_comdat_group ()) references outside of the comdat group. */
return false; if (!will_inline)
for (int i = 0; next->iterate_referring (i, ref); i++)
if (ref->referring->get_comdat_group () != get_comdat_group ())
return false;
} }
return true; return true;
} }
@ -2479,9 +2486,9 @@ cgraph_node::can_remove_if_no_direct_calls_p (void)
linkonce section. */ linkonce section. */
bool bool
cgraph_node::will_be_removed_from_program_if_no_direct_calls_p (void) cgraph_node::will_be_removed_from_program_if_no_direct_calls_p
(bool will_inline)
{ {
struct ipa_ref *ref;
gcc_assert (!global.inlined_to); gcc_assert (!global.inlined_to);
if (DECL_EXTERNAL (decl)) if (DECL_EXTERNAL (decl))
return true; return true;
@ -2496,6 +2503,9 @@ cgraph_node::will_be_removed_from_program_if_no_direct_calls_p (void)
if (same_comdat_group && externally_visible) if (same_comdat_group && externally_visible)
{ {
struct cgraph_node *target = ultimate_alias_target (); struct cgraph_node *target = ultimate_alias_target ();
if (will_inline && address_taken)
return true;
for (cgraph_node *next = dyn_cast<cgraph_node *> (same_comdat_group); for (cgraph_node *next = dyn_cast<cgraph_node *> (same_comdat_group);
next != this; next != this;
next = dyn_cast<cgraph_node *> (next->same_comdat_group)) next = dyn_cast<cgraph_node *> (next->same_comdat_group))
@ -2510,18 +2520,15 @@ cgraph_node::will_be_removed_from_program_if_no_direct_calls_p (void)
be sure to check calls. */ be sure to check calls. */
if (next->ultimate_alias_target () != target) if (next->ultimate_alias_target () != target)
for (cgraph_edge *e = next->callers; e; e = e->next_caller) for (cgraph_edge *e = next->callers; e; e = e->next_caller)
if (e->caller->get_comdat_group () != get_comdat_group ()) if (e->caller->get_comdat_group () != get_comdat_group ()
|| will_inline)
return false; return false;
for (int i = 0; next->iterate_referring (i, ref); i++)
if (ref->referring->get_comdat_group () != get_comdat_group ())
return false;
} }
} }
return true; return true;
} }
else else
return can_remove_if_no_direct_calls_p (); return can_remove_if_no_direct_calls_p (will_inline);
} }

View File

@ -1110,16 +1110,23 @@ public:
all uses of COMDAT function does not make it necessarily disappear from all uses of COMDAT function does not make it necessarily disappear from
the program unless we are compiling whole program or we do LTO. In this the program unless we are compiling whole program or we do LTO. In this
case we know we win since dynamic linking will not really discard the case we know we win since dynamic linking will not really discard the
linkonce section. */ linkonce section.
bool will_be_removed_from_program_if_no_direct_calls_p (void);
If WILL_INLINE is true, assume that function will be inlined into all the
direct calls. */
bool will_be_removed_from_program_if_no_direct_calls_p
(bool will_inline = false);
/* Return true when function can be removed from callgraph /* Return true when function can be removed from callgraph
if all direct calls are eliminated. */ if all direct calls and references are eliminated. The function does
not take into account comdat groups. */
bool can_remove_if_no_direct_calls_and_refs_p (void); bool can_remove_if_no_direct_calls_and_refs_p (void);
/* Return true when function cgraph_node and its aliases can be removed from /* Return true when function cgraph_node and its aliases can be removed from
callgraph if all direct calls are eliminated. */ callgraph if all direct calls are eliminated.
bool can_remove_if_no_direct_calls_p (void); If WILL_INLINE is true, assume that function will be inlined into all the
direct calls. */
bool can_remove_if_no_direct_calls_p (bool will_inline = false);
/* Return true when callgraph node is a function with Gimple body defined /* Return true when callgraph node is a function with Gimple body defined
in current unit. Functions can also be define externally or they in current unit. Functions can also be define externally or they

View File

@ -3978,6 +3978,9 @@ check_callers (cgraph_node *node, int *max_callers)
{ {
ipa_ref *ref; ipa_ref *ref;
if (!node->can_remove_if_no_direct_calls_and_refs_p ())
return true;
for (cgraph_edge *e = node->callers; e; e = e->next_caller) for (cgraph_edge *e = node->callers; e; e = e->next_caller)
{ {
(*max_callers)--; (*max_callers)--;
@ -4007,8 +4010,28 @@ growth_likely_positive (struct cgraph_node *node,
struct cgraph_edge *e; struct cgraph_edge *e;
gcc_checking_assert (edge_growth > 0); gcc_checking_assert (edge_growth > 0);
/* First quickly check if NODE is removable at all. */
if (DECL_EXTERNAL (node->decl)) if (DECL_EXTERNAL (node->decl))
return true; return true;
if (!node->can_remove_if_no_direct_calls_and_refs_p ()
|| node->address_taken)
return true;
max_callers = inline_summaries->get (node)->size * 4 / edge_growth + 2;
for (e = node->callers; e; e = e->next_caller)
{
max_callers--;
if (!max_callers
|| cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
return true;
}
ipa_ref *ref;
FOR_EACH_ALIAS (node, ref)
if (check_callers (dyn_cast <cgraph_node *> (ref->referring), &max_callers))
return true;
/* Unlike for functions called once, we play unsafe with /* Unlike for functions called once, we play unsafe with
COMDATs. We can allow that since we know functions COMDATs. We can allow that since we know functions
in consideration are small (and thus risk is small) and in consideration are small (and thus risk is small) and
@ -4024,20 +4047,6 @@ growth_likely_positive (struct cgraph_node *node,
} }
else if (!node->will_be_removed_from_program_if_no_direct_calls_p ()) else if (!node->will_be_removed_from_program_if_no_direct_calls_p ())
return true; return true;
max_callers = inline_summaries->get (node)->size * 4 / edge_growth + 2;
for (e = node->callers; e; e = e->next_caller)
{
max_callers--;
if (!max_callers
|| cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
return true;
}
ipa_ref *ref;
FOR_EACH_ALIAS (node, ref)
if (check_callers (dyn_cast <cgraph_node *> (ref->referring), &max_callers))
return true;
return estimate_growth (node) > 0; return estimate_growth (node) > 0;
} }