aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2011-06-13 11:19:09 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2011-06-13 09:19:09 +0000
commit9aa3f5c58c228ee74b8a2d9b3977fee1c97cc6bd (patch)
tree7e356df77924fcdd550af73036e37d71e9ab5ddb
parent30cecf17a92a1e52374fa04e25c8b921372f676c (diff)
downloadgcc-9aa3f5c58c228ee74b8a2d9b3977fee1c97cc6bd.zip
gcc-9aa3f5c58c228ee74b8a2d9b3977fee1c97cc6bd.tar.gz
gcc-9aa3f5c58c228ee74b8a2d9b3977fee1c97cc6bd.tar.bz2
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/cgraph.c44
-rw-r--r--gcc/cgraph.h15
-rw-r--r--gcc/ipa-inline-analysis.c3
-rw-r--r--gcc/ipa-inline.c24
5 files changed, 74 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 87bb65f..5404f09 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 2805d46..dfa5439 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 09d99b1..feb742d 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 *);
@@ -926,20 +927,6 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
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. */
-
-static inline bool
varpool_can_remove_if_no_refs (struct varpool_node *node)
{
return (!node->force_output && !node->used_from_other_partition
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 473f554..43e0f81 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 4283770..a2e55b9 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;