summaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-transform.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-24 16:15:46 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-24 16:15:46 +0000
commit7fbf53b8667745c0122e964e1b11dcb99959e377 (patch)
tree43174ebb8202281dbb77d8e7f7ce4901d574c71a /gcc/ipa-inline-transform.c
parent4f77a7737d9b0ecd56785c7cd9b91ab23f529eb9 (diff)
downloadgcc-7fbf53b8667745c0122e964e1b11dcb99959e377.tar.gz
PR ipa/63671
* ipa-inline-transform.c (can_remove_node_now_p_1): Handle alises and -fno-devirtualize more carefully. (can_remove_node_now_p): Update. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@218024 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-inline-transform.c')
-rw-r--r--gcc/ipa-inline-transform.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index a64e4dd379c..063cd94cda6 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -93,19 +93,28 @@ update_noncloned_frequencies (struct cgraph_node *node,
copy of function was removed. */
static bool
-can_remove_node_now_p_1 (struct cgraph_node *node)
+can_remove_node_now_p_1 (struct cgraph_node *node, struct cgraph_edge *e)
{
+ ipa_ref *ref;
+
+ FOR_EACH_ALIAS (node, ref)
+ {
+ cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ if ((alias->callers && alias->callers != e)
+ || !can_remove_node_now_p_1 (alias, e))
+ return false;
+ }
/* FIXME: When address is taken of DECL_EXTERNAL function we still
can remove its offline copy, but we would need to keep unanalyzed node in
the callgraph so references can point to it. */
return (!node->address_taken
- && !node->has_aliases_p ()
&& node->can_remove_if_no_direct_calls_p ()
/* Inlining might enable more devirtualizing, so we want to remove
those only after all devirtualizable virtual calls are processed.
Lacking may edges in callgraph we just preserve them post
inlining. */
- && !DECL_VIRTUAL_P (node->decl)
+ && (!DECL_VIRTUAL_P (node->decl)
+ || !opt_for_fn (node->decl, flag_devirtualize))
/* During early inlining some unanalyzed cgraph nodes might be in the
callgraph and they might reffer the function in question. */
&& !cgraph_new_nodes.exists ());
@@ -119,7 +128,7 @@ static bool
can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
{
struct cgraph_node *next;
- if (!can_remove_node_now_p_1 (node))
+ if (!can_remove_node_now_p_1 (node, e))
return false;
/* When we see same comdat group, we need to be sure that all
@@ -128,9 +137,13 @@ can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
return true;
for (next = dyn_cast<cgraph_node *> (node->same_comdat_group);
next != node; next = dyn_cast<cgraph_node *> (next->same_comdat_group))
- if ((next->callers && next->callers != e)
- || !can_remove_node_now_p_1 (next))
- return false;
+ {
+ if (next->alias)
+ continue;
+ if ((next->callers && next->callers != e)
+ || !can_remove_node_now_p_1 (next, e))
+ return false;
+ }
return true;
}