aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraph.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/cgraph.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/cgraph.c')
-rw-r--r--gcc/cgraph.c76
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;