mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 03:40:26 +08:00
cgraph.c (cgraph_for_node_thunks_and_aliases, [...]): Fix thinko in recursive walking.
* cgraph.c (cgraph_for_node_thunks_and_aliases, cgraph_for_node_and_aliases): Fix thinko in recursive walking. (nonremovable_p): New function. (cgraph_can_remove_if_no_direct_calls_p): New function. (used_from_object_file_p): New functoin. (cgraph_will_be_removed_from_program_if_no_direct_calls): Look for references from aliases. * cgraph.h (cgraph_can_remove_if_no_direct_calls_p): Bring offline. * ipa-inline.c (check_caller_edge): New function. (want_inline_function_called_once_p): Use it; accept aliases called once, too. * ipa-inline-analysis.c (do_estimate_growth): Remove FIXME. From-SVN: r174985
This commit is contained in:
parent
30cecf17a9
commit
9aa3f5c58c
@ -1,3 +1,17 @@
|
||||
2011-06-13 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cgraph.c (cgraph_for_node_thunks_and_aliases,
|
||||
cgraph_for_node_and_aliases): Fix thinko in recursive walking.
|
||||
(nonremovable_p): New function.
|
||||
(cgraph_can_remove_if_no_direct_calls_p): New function.
|
||||
(used_from_object_file_p): New functoin.
|
||||
(cgraph_will_be_removed_from_program_if_no_direct_calls): Look for references
|
||||
from aliases.
|
||||
* cgraph.h (cgraph_can_remove_if_no_direct_calls_p): Bring offline.
|
||||
* ipa-inline.c (check_caller_edge): New function.
|
||||
(want_inline_function_called_once_p): Use it; accept aliases called once, too.
|
||||
* ipa-inline-analysis.c (do_estimate_growth): Remove FIXME.
|
||||
|
||||
2011-06-13 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
|
||||
|
||||
PR target/48454
|
||||
|
44
gcc/cgraph.c
44
gcc/cgraph.c
@ -2567,14 +2567,18 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
|
||||
if (e->caller->thunk.thunk_p
|
||||
&& (include_overwritable
|
||||
|| cgraph_function_body_availability (e->caller)))
|
||||
cgraph_for_node_thunks_and_aliases (e->caller, callback, data, include_overwritable);
|
||||
if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
|
||||
include_overwritable))
|
||||
return true;
|
||||
for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
|
||||
if (ref->use == IPA_REF_ALIAS)
|
||||
{
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
if (include_overwritable
|
||||
|| cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
|
||||
cgraph_for_node_thunks_and_aliases (alias, callback, data, include_overwritable);
|
||||
if (cgraph_for_node_thunks_and_aliases (alias, callback, data,
|
||||
include_overwritable))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2600,7 +2604,9 @@ cgraph_for_node_and_aliases (struct cgraph_node *node,
|
||||
struct cgraph_node *alias = ipa_ref_refering_node (ref);
|
||||
if (include_overwritable
|
||||
|| cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
|
||||
cgraph_for_node_and_aliases (alias, callback, data, include_overwritable);
|
||||
if (cgraph_for_node_and_aliases (alias, callback, data,
|
||||
include_overwritable))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2900,6 +2906,36 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Worker for cgraph_can_remove_if_no_direct_calls_p. */
|
||||
|
||||
static bool
|
||||
nonremovable_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return !cgraph_can_remove_if_no_direct_calls_and_refs_p (node);
|
||||
}
|
||||
|
||||
/* Return true when function NODE and its aliases can be removed from callgraph
|
||||
if all direct calls are eliminated. */
|
||||
|
||||
bool
|
||||
cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
|
||||
{
|
||||
/* Extern inlines can always go, we will use the external definition. */
|
||||
if (DECL_EXTERNAL (node->decl))
|
||||
return true;
|
||||
if (node->address_taken)
|
||||
return false;
|
||||
return !cgraph_for_node_and_aliases (node, nonremovable_p, NULL, true);
|
||||
}
|
||||
|
||||
/* Worker for cgraph_can_remove_if_no_direct_calls_p. */
|
||||
|
||||
static bool
|
||||
used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return cgraph_used_from_object_file_p (node);
|
||||
}
|
||||
|
||||
/* Return true when function NODE can be expected to be removed
|
||||
from program when direct calls in this compilation unit are removed.
|
||||
|
||||
@ -2918,7 +2954,7 @@ bool
|
||||
cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node)
|
||||
{
|
||||
gcc_assert (!node->global.inlined_to);
|
||||
if (cgraph_used_from_object_file_p (node))
|
||||
if (cgraph_for_node_and_aliases (node, used_from_object_file_p, NULL, true))
|
||||
return false;
|
||||
if (!in_lto_p && !flag_whole_program)
|
||||
return cgraph_only_called_directly_p (node);
|
||||
|
15
gcc/cgraph.h
15
gcc/cgraph.h
@ -535,6 +535,7 @@ bool cgraph_will_be_removed_from_program_if_no_direct_calls
|
||||
(struct cgraph_node *node);
|
||||
bool cgraph_can_remove_if_no_direct_calls_and_refs_p
|
||||
(struct cgraph_node *node);
|
||||
bool cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node);
|
||||
bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
|
||||
bool cgraph_used_from_object_file_p (struct cgraph_node *);
|
||||
bool varpool_used_from_object_file_p (struct varpool_node *);
|
||||
@ -922,20 +923,6 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
|
||||
&& !node->local.externally_visible);
|
||||
}
|
||||
|
||||
/* Return true when function NODE can be removed from callgraph
|
||||
if all direct calls are eliminated. */
|
||||
|
||||
static inline bool
|
||||
cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
|
||||
{
|
||||
/* Extern inlines can always go, we will use the external definition. */
|
||||
if (DECL_EXTERNAL (node->decl))
|
||||
return true;
|
||||
return (!node->address_taken
|
||||
&& cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
|
||||
&& !ipa_ref_has_aliases_p (&node->ref_list));
|
||||
}
|
||||
|
||||
/* Return true when function NODE can be removed from callgraph
|
||||
if all direct calls are eliminated. */
|
||||
|
||||
|
@ -2229,8 +2229,7 @@ do_estimate_growth (struct cgraph_node *node)
|
||||
&& !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.
|
||||
FIXME: allow also COMDATs with COMDAT aliases. */
|
||||
come from various template instantiations. Take this into account. */
|
||||
else if (DECL_COMDAT (node->decl)
|
||||
&& cgraph_can_remove_if_no_direct_calls_p (node))
|
||||
d.growth -= (info->size
|
||||
|
@ -643,6 +643,16 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
|
||||
return want_inline;
|
||||
}
|
||||
|
||||
/* Return true when NODE has caller other than EDGE.
|
||||
Worker for cgraph_for_node_and_aliases. */
|
||||
|
||||
static bool
|
||||
check_caller_edge (struct cgraph_node *node, void *edge)
|
||||
{
|
||||
return (node->callers
|
||||
&& node->callers != edge);
|
||||
}
|
||||
|
||||
|
||||
/* Decide if NODE is called once inlining it would eliminate need
|
||||
for the offline copy of function. */
|
||||
@ -650,24 +660,26 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
|
||||
static bool
|
||||
want_inline_function_called_once_p (struct cgraph_node *node)
|
||||
{
|
||||
if (node->alias)
|
||||
return false;
|
||||
struct cgraph_node *function = cgraph_function_or_thunk_node (node, NULL);
|
||||
/* Already inlined? */
|
||||
if (node->global.inlined_to)
|
||||
if (function->global.inlined_to)
|
||||
return false;
|
||||
/* Zero or more then one callers? */
|
||||
if (!node->callers
|
||||
|| node->callers->next_caller)
|
||||
return false;
|
||||
/* Maybe other aliases has more direct calls. */
|
||||
if (cgraph_for_node_and_aliases (node, check_caller_edge, node->callers, true))
|
||||
return false;
|
||||
/* Recursive call makes no sense to inline. */
|
||||
if (node->callers->caller == node)
|
||||
if (cgraph_edge_recursive_p (node->callers))
|
||||
return false;
|
||||
/* External functions are not really in the unit, so inlining
|
||||
them when called once would just increase the program size. */
|
||||
if (DECL_EXTERNAL (node->decl))
|
||||
if (DECL_EXTERNAL (function->decl))
|
||||
return false;
|
||||
/* Offline body must be optimized out. */
|
||||
if (!cgraph_will_be_removed_from_program_if_no_direct_calls (node))
|
||||
if (!cgraph_will_be_removed_from_program_if_no_direct_calls (function))
|
||||
return false;
|
||||
if (!can_inline_edge_p (node->callers, true))
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user