diff options
author | Jan Hubicka <jh@suse.cz> | 2010-10-26 18:40:16 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2010-10-26 16:40:16 +0000 |
commit | 530f3a1bf62964c0c52d6fcf4ca0d321ce9d5156 (patch) | |
tree | f4fc3981e343130fc38f5d142b14b9d00708d62f /gcc/ipa.c | |
parent | 0d600fce5ba0aae8073f84b9c5f9296233f6f269 (diff) | |
download | gcc-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.c | 43 |
1 files changed, 31 insertions, 12 deletions
@@ -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 |