From: Jan Hubicka Date: Mon, 13 Jun 2011 09:19:09 +0000 (+0200) Subject: cgraph.c (cgraph_for_node_thunks_and_aliases, [...]): Fix thinko in recursive walking. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9aa3f5c58c228ee74b8a2d9b3977fee1c97cc6bd;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87bb65fc55a..5404f099f21 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2011-06-13 Jan Hubicka + + * 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 PR target/48454 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 2805d46dfad..dfa5439ad96 100644 --- a/gcc/cgraph.c +++ b/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); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 09d99b1c1f7..feb742d387e 100644 --- a/gcc/cgraph.h +++ b/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. */ diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 473f554e4ae..43e0f8124d0 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -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 diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 4283770a1c3..a2e55b981b7 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -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;