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/cgraph.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/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index e1f47c2..1451d2b 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1723,6 +1723,7 @@ cgraph_mark_needed_node (struct cgraph_node *node) void cgraph_mark_address_taken_node (struct cgraph_node *node) { + gcc_assert (!node->global.inlined_to); cgraph_mark_reachable_node (node); node->address_taken = 1; } @@ -2591,37 +2592,50 @@ cgraph_set_nothrow_flag (struct cgraph_node *node, bool nothrow) if any to READONLY. */ void -cgraph_set_readonly_flag (struct cgraph_node *node, bool readonly) +cgraph_set_const_flag (struct cgraph_node *node, bool readonly, bool looping) { struct cgraph_node *alias; + /* Static constructors and destructors without a side effect can be + optimized out. */ + if (!looping && readonly) + { + if (DECL_STATIC_CONSTRUCTOR (node->decl)) + DECL_STATIC_CONSTRUCTOR (node->decl) = 0; + if (DECL_STATIC_DESTRUCTOR (node->decl)) + DECL_STATIC_DESTRUCTOR (node->decl) = 0; + } TREE_READONLY (node->decl) = readonly; + DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping; for (alias = node->same_body; alias; alias = alias->next) - TREE_READONLY (alias->decl) = readonly; + { + TREE_READONLY (alias->decl) = readonly; + DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping; + } } /* Set DECL_PURE_P on NODE's decl and on same_body aliases of NODE if any to PURE. */ void -cgraph_set_pure_flag (struct cgraph_node *node, bool pure) +cgraph_set_pure_flag (struct cgraph_node *node, bool pure, bool looping) { struct cgraph_node *alias; + /* Static constructors and destructors without a side effect can be + optimized out. */ + if (!looping && pure) + { + if (DECL_STATIC_CONSTRUCTOR (node->decl)) + DECL_STATIC_CONSTRUCTOR (node->decl) = 0; + if (DECL_STATIC_DESTRUCTOR (node->decl)) + DECL_STATIC_DESTRUCTOR (node->decl) = 0; + } DECL_PURE_P (node->decl) = pure; + DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping; for (alias = node->same_body; alias; alias = alias->next) - DECL_PURE_P (alias->decl) = pure; -} - -/* Set DECL_LOOPING_CONST_OR_PURE_P on NODE's decl and on - same_body aliases of NODE if any to LOOPING_CONST_OR_PURE. */ - -void -cgraph_set_looping_const_or_pure_flag (struct cgraph_node *node, - bool looping_const_or_pure) -{ - struct cgraph_node *alias; - DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping_const_or_pure; - for (alias = node->same_body; alias; alias = alias->next) - DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping_const_or_pure; + { + DECL_PURE_P (alias->decl) = pure; + DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping; + } } /* See if the frequency of NODE can be updated based on frequencies of its @@ -2768,25 +2782,21 @@ cgraph_edge_cannot_lead_to_return (struct cgraph_edge *e) bool cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) { + gcc_assert (!node->global.inlined_to); + /* Extern inlines can always go, we will use the external definition. */ + if (DECL_EXTERNAL (node->decl)) + return true; /* When function is needed, we can not remove it. */ if (node->needed || node->reachable_from_other_partition) return false; + if (DECL_STATIC_CONSTRUCTOR (node->decl) + || DECL_STATIC_DESTRUCTOR (node->decl)) + return false; /* Only COMDAT functions can be removed if externally visible. */ if (node->local.externally_visible && (!DECL_COMDAT (node->decl) || cgraph_used_from_object_file_p (node))) return false; - /* Constructors and destructors are executed by the runtime, however - we can get rid of all pure constructors and destructors. */ - if (DECL_STATIC_CONSTRUCTOR (node->decl) - || DECL_STATIC_DESTRUCTOR (node->decl)) - { - int flags = flags_from_decl_or_type (node->decl); - if (!optimize - || !(flags & (ECF_CONST | ECF_PURE)) - || (flags & ECF_LOOPING_CONST_OR_PURE)) - return false; - } return true; } @@ -2807,12 +2817,17 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) 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)) return false; if (!in_lto_p && !flag_whole_program) return cgraph_only_called_directly_p (node); else - return cgraph_can_remove_if_no_direct_calls_p (node); + { + if (DECL_EXTERNAL (node->decl)) + return true; + return cgraph_can_remove_if_no_direct_calls_p (node); + } } /* Return true when RESOLUTION indicate that linker will use @@ -2835,7 +2850,8 @@ cgraph_used_from_object_file_p (struct cgraph_node *node) { struct cgraph_node *alias; - if (!TREE_PUBLIC (node->decl)) + gcc_assert (!node->global.inlined_to); + if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) return false; if (resolution_used_from_other_file_p (node->resolution)) return true; |