aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-10-26 18:40:16 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2010-10-26 16:40:16 +0000
commit530f3a1bf62964c0c52d6fcf4ca0d321ce9d5156 (patch)
treef4fc3981e343130fc38f5d142b14b9d00708d62f /gcc/ipa.c
parent0d600fce5ba0aae8073f84b9c5f9296233f6f269 (diff)
downloadgcc-530f3a1bf62964c0c52d6fcf4ca0d321ce9d5156.zip
gcc-530f3a1bf62964c0c52d6fcf4ca0d321ce9d5156.tar.gz
gcc-530f3a1bf62964c0c52d6fcf4ca0d321ce9d5156.tar.bz2
re PR lto/45736 (ICE: in cgraph_remove_unreachable_nodes, at ipa.c:245 with -flto and attribute((constructor)))
PR middle-end/45736 * cgraph.c (cgraph_set_readonly_flag): Rename to... (cgraph_set_const_flags) ... this one; get also looping argument; clear constructor/destructor flags. (cgraph_set_pure_flag): Likewise. (cgraph_set_looping_const_or_pure_flag): Remove. (cgraph_can_remove_if_no_direct_calls_and_refs): Do not try to optimize away static ctors/dtors; it does not work on inline clones; external functions can always be rmeoved. (cgraph_will_be_removed_from_program_if_no_direct_calls): Assert on inline clones; in LTO external functions always can go. (cgraph_used_from_object_file_p): Handle EXTERNAL functions correctly. (cgraph_mark_address_taken_node): Assert that we are not taking address of inline clone. (cgraph_can_remove_if_no_direct_calls_p): We always eventually remove external functions. * ipa-cp.c (ipcp_cloning_candidate_p): Do not clone functions with address taken. (ipcp_initialize_node_lattices): Only local functions can be handled without cloning. * cgraph.h (cgraph_set_readonly_flag, cgraph_set_looping_const_or_pure_flag): Remove. (cgraph_set_const_flag): Declare. (cgraph_set_pure_flag): Update. * ipa-pure-const (propagate_pure_const, local_pure_const): Update flags setting code. * ipa.c (cgraph_remove_unreachable_nodes): Fix formating; do not look at inline clones; fix handling of external definitions. (cgraph_postorder): Do not look at inline clones in the first pass. (function_and_variable_visibility): Drop constructors/destructor flags at pure and const functions. * tree-profile.c (tree_profiling): Update. * ipa-inline.c (cgraph_clone_inlined_nodes): Always clone functions with address taken; external functions do not account to whole program size. (cgraph_decide_inlining): Likewise; do not try to inline functions already inlined. * testsuite/gcc.dg/lto/pr45736_0.c: New function. From-SVN: r165972
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 7db27f3..2eb43b8 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -57,8 +57,9 @@ cgraph_postorder (struct cgraph_node **order)
for (node = cgraph_nodes; node; node = node->next)
if (!node->aux
&& (pass
- || (!cgraph_only_called_directly_p (node)
- && !node->address_taken)))
+ || (!node->address_taken
+ && !node->global.inlined_to
+ && !cgraph_only_called_directly_p (node))))
{
node2 = node;
if (!node->callers)
@@ -237,15 +238,22 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
gcc_assert (!vnode->aux);
#endif
varpool_reset_queue ();
+ /* Mark functions whose bodies are obviously needed.
+ This is mostly when they can be referenced externally. Inline clones
+ are special since their declarations are shared with master clone and thus
+ cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
for (node = cgraph_nodes; node; node = node->next)
- if ((!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
- /* Keep around virtual functions for possible devirtualization. */
- || (!before_inlining_p
- && !node->global.inlined_to
- && DECL_VIRTUAL_P (node->decl)
- && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))))
- && ((!DECL_EXTERNAL (node->decl))
- || before_inlining_p))
+ if (node->analyzed && !node->global.inlined_to
+ && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+ /* Keep around virtual functions for possible devirtualization. */
+ || (before_inlining_p
+ && DECL_VIRTUAL_P (node->decl)
+ && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))
+ /* Also external functions with address taken are better to stay
+ for indirect inlining. */
+ || (before_inlining_p
+ && DECL_EXTERNAL (node->decl)
+ && node->address_taken)))
{
gcc_assert (!node->global.inlined_to);
enqueue_cgraph_node (node, &first);
@@ -256,6 +264,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
gcc_assert (!node->aux);
node->reachable = false;
}
+
+ /* Mark variables that are obviously needed. */
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
{
vnode->next_needed = NULL;
@@ -428,10 +438,10 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
node->clone_of->clones = node->next_sibling_clone;
if (node->next_sibling_clone)
node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
- #ifdef ENABLE_CHECKING
+#ifdef ENABLE_CHECKING
if (node->clone_of)
node->former_clone_of = node->clone_of->decl;
- #endif
+#endif
node->clone_of = NULL;
node->next_sibling_clone = NULL;
node->prev_sibling_clone = NULL;
@@ -771,6 +781,15 @@ function_and_variable_visibility (bool whole_program)
for (node = cgraph_nodes; node; node = node->next)
{
+ int flags = flags_from_decl_or_type (node->decl);
+ if (optimize
+ && (flags & (ECF_CONST | ECF_PURE))
+ && !(flags & ECF_LOOPING_CONST_OR_PURE))
+ {
+ DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
+ DECL_STATIC_DESTRUCTOR (node->decl) = 0;
+ }
+
/* C++ FE on lack of COMDAT support create local COMDAT functions
(that ought to be shared but can not due to object format
limitations). It is neccesary to keep the flag to make rest of C++ FE