diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-11-24 16:15:46 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-11-24 16:15:46 +0000 |
commit | 7fbf53b8667745c0122e964e1b11dcb99959e377 (patch) | |
tree | 43174ebb8202281dbb77d8e7f7ce4901d574c71a /gcc/ipa-inline-transform.c | |
parent | 4f77a7737d9b0ecd56785c7cd9b91ab23f529eb9 (diff) | |
download | gcc-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.c | 27 |
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; } |