Commit 93a18a70 by Jan Hubicka Committed by Jan Hubicka

lto-symtab.c (lto_cgraph_replace_node): Do not call mark_reahcable_node.


	* lto-symtab.c (lto_cgraph_replace_node): Do not call
	mark_reahcable_node.
	* cgraph.c (cgraph_remove_node): Do not clear reachable.
	(cgraph_mark_reachable_node): Remove.
	(cgraph_mark_force_output_node): Do not set reachable.
	(dump_cgraph_node): Do not dump reachable.
	(cgraph_create_virtual_clone): Do not set reachable.
	* cgraph.h (cgraph_node): Remove reachable flag.
	(varpool_node): Remove reachable flag.
	(cgraph_mark_if_needed): Remove.
	(cgraph_mark_reachable_node): Remove.
	* tree-emutls.c (ipa_lower_emutls): Do not check
	reachable.
	* cgraphunit.c (cgraph_finalize_function): Do not mark node as
	reachable.
	(cgraph_add_new_function): Likewise.
	(cgraph_mark_if_needed): Remove.
	(cgraph_analyze_function): Do not set target as reachable.
	(process_function_and_variable_attributes): Do not care about dllexport.
	(cgraph_analyze_functions): Do not set reachable flags.
	(cgraph_mark_functions_to_output): Do not check reachability.
	(cgraph_copy_node_for_versioning): Do not set reachable flag.
	(dbxout_expand_expr): Update.
	* c-decl.c (merge_decls): Do not track changed externs.
	* ipa.c: Include pointer-set.h
	(enqueue_cgraph_node): Use reachable pointer set.
	(process_references): Likewise.
	(cgraph_remove_unreachable_nodes): Likewise.
	(whole_program_function_and_variable_visibility): Do not recompute reachable.
	* trans-mem.c (ipa_tm_execute): Do not check reachable flag.

From-SVN: r186700
parent da4343c3
2012-04-23 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_cgraph_replace_node): Do not call
mark_reahcable_node.
* cgraph.c (cgraph_remove_node): Do not clear reachable.
(cgraph_mark_reachable_node): Remove.
(cgraph_mark_force_output_node): Do not set reachable.
(dump_cgraph_node): Do not dump reachable.
(cgraph_create_virtual_clone): Do not set reachable.
* cgraph.h (cgraph_node): Remove reachable flag.
(varpool_node): Remove reachable flag.
(cgraph_mark_if_needed): Remove.
(cgraph_mark_reachable_node): Remove.
* tree-emutls.c (ipa_lower_emutls): Do not check
reachable.
* cgraphunit.c (cgraph_finalize_function): Do not mark node as
reachable.
(cgraph_add_new_function): Likewise.
(cgraph_mark_if_needed): Remove.
(cgraph_analyze_function): Do not set target as reachable.
(process_function_and_variable_attributes): Do not care about dllexport.
(cgraph_analyze_functions): Do not set reachable flags.
(cgraph_mark_functions_to_output): Do not check reachability.
(cgraph_copy_node_for_versioning): Do not set reachable flag.
(dbxout_expand_expr): Update.
* c-decl.c (merge_decls): Do not track changed externs.
* ipa.c: Include pointer-set.h
(enqueue_cgraph_node): Use reachable pointer set.
(process_references): Likewise.
(cgraph_remove_unreachable_nodes): Likewise.
(whole_program_function_and_variable_visibility): Do not recompute reachable.
* trans-mem.c (ipa_tm_execute): Do not check reachable flag.
2012-04-23 Georg-Johann Lay <avr@gjlay.de> 2012-04-23 Georg-Johann Lay <avr@gjlay.de>
* doc/extend.texi (AVR Named Address Spaces): Fix typos. * doc/extend.texi (AVR Named Address Spaces): Fix typos.
......
...@@ -2172,7 +2172,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) ...@@ -2172,7 +2172,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
&& prototype_p (TREE_TYPE (newdecl))); && prototype_p (TREE_TYPE (newdecl)));
bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
&& prototype_p (TREE_TYPE (olddecl))); && prototype_p (TREE_TYPE (olddecl)));
bool extern_changed = false;
/* For real parm decl following a forward decl, rechain the old decl /* For real parm decl following a forward decl, rechain the old decl
in its new location and clear TREE_ASM_WRITTEN (it's not a in its new location and clear TREE_ASM_WRITTEN (it's not a
...@@ -2443,8 +2442,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) ...@@ -2443,8 +2442,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
} }
} }
extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
/* Merge the USED information. */ /* Merge the USED information. */
if (TREE_USED (olddecl)) if (TREE_USED (olddecl))
TREE_USED (newdecl) = 1; TREE_USED (newdecl) = 1;
...@@ -2506,13 +2503,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) ...@@ -2506,13 +2503,6 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|| (TREE_CODE (olddecl) == VAR_DECL || (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl)))) && TREE_STATIC (olddecl))))
make_decl_rtl (olddecl); make_decl_rtl (olddecl);
/* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
and the definition is coming from the old version, cgraph needs
to be called again. */
if (extern_changed && !new_is_definition
&& TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
cgraph_mark_if_needed (olddecl);
} }
/* Handle when a new declaration NEWDECL has the same name as an old /* Handle when a new declaration NEWDECL has the same name as an old
......
...@@ -1344,7 +1344,7 @@ cgraph_remove_node (struct cgraph_node *node) ...@@ -1344,7 +1344,7 @@ cgraph_remove_node (struct cgraph_node *node)
/* Incremental inlining access removed nodes stored in the postorder list. /* Incremental inlining access removed nodes stored in the postorder list.
*/ */
node->symbol.force_output = node->reachable = false; node->symbol.force_output = false;
for (n = node->nested; n; n = n->next_nested) for (n = node->nested; n; n = n->next_nested)
n->origin = NULL; n->origin = NULL;
node->nested = NULL; node->nested = NULL;
...@@ -1472,27 +1472,6 @@ cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_no ...@@ -1472,27 +1472,6 @@ cgraph_remove_node_and_inline_clones (struct cgraph_node *node, struct cgraph_no
return found; return found;
} }
/* Notify finalize_compilation_unit that given node is reachable. */
void
cgraph_mark_reachable_node (struct cgraph_node *node)
{
if (!node->reachable && node->local.finalized)
{
if (cgraph_global_info_ready)
{
/* Verify that function does not appear to be needed out of blue
during the optimization process. This can happen for extern
inlines when bodies was removed after inlining. */
gcc_assert ((node->analyzed || node->symbol.in_other_partition
|| DECL_EXTERNAL (node->symbol.decl)));
}
else
notice_global_symbol (node->symbol.decl);
node->reachable = 1;
}
}
/* Likewise indicate that a node is needed, i.e. reachable via some /* Likewise indicate that a node is needed, i.e. reachable via some
external means. */ external means. */
...@@ -1501,7 +1480,6 @@ cgraph_mark_force_output_node (struct cgraph_node *node) ...@@ -1501,7 +1480,6 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
{ {
node->symbol.force_output = 1; node->symbol.force_output = 1;
gcc_assert (!node->global.inlined_to); gcc_assert (!node->global.inlined_to);
cgraph_mark_reachable_node (node);
} }
/* Likewise indicate that a node is having address taken. */ /* Likewise indicate that a node is having address taken. */
...@@ -1510,7 +1488,6 @@ void ...@@ -1510,7 +1488,6 @@ void
cgraph_mark_address_taken_node (struct cgraph_node *node) cgraph_mark_address_taken_node (struct cgraph_node *node)
{ {
gcc_assert (!node->global.inlined_to); gcc_assert (!node->global.inlined_to);
cgraph_mark_reachable_node (node);
/* FIXME: address_taken flag is used both as a shortcut for testing whether /* FIXME: address_taken flag is used both as a shortcut for testing whether
IPA_REF_ADDR reference exists (and thus it should be set on node IPA_REF_ADDR reference exists (and thus it should be set on node
representing alias we take address of) and as a test whether address representing alias we take address of) and as a test whether address
...@@ -1621,8 +1598,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) ...@@ -1621,8 +1598,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
(HOST_WIDEST_INT)node->count); (HOST_WIDEST_INT)node->count);
if (node->origin) if (node->origin)
fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin)); fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
else if (node->reachable)
fprintf (f, " reachable");
if (gimple_has_body_p (node->symbol.decl)) if (gimple_has_body_p (node->symbol.decl))
fprintf (f, " body"); fprintf (f, " body");
if (node->process) if (node->process)
...@@ -2048,7 +2023,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, ...@@ -2048,7 +2023,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
new_node->symbol.externally_visible = 0; new_node->symbol.externally_visible = 0;
new_node->local.local = 1; new_node->local.local = 1;
new_node->lowered = true; new_node->lowered = true;
new_node->reachable = true;
cgraph_call_node_duplication_hooks (old_node, new_node); cgraph_call_node_duplication_hooks (old_node, new_node);
......
...@@ -248,13 +248,6 @@ struct GTY(()) cgraph_node { ...@@ -248,13 +248,6 @@ struct GTY(()) cgraph_node {
/* Set when decl is an abstract function pointed to by the /* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */ ABSTRACT_DECL_ORIGIN of a reachable function. */
unsigned abstract_and_needed : 1; unsigned abstract_and_needed : 1;
/* Set when function is reachable by call from other function
that is either reachable or needed.
This flag is computed at original cgraph construction and then
updated in cgraph_remove_unreachable_nodes. Note that after
cgraph_remove_unreachable_nodes cgraph still can contain unreachable
nodes when they are needed for virtual clone instantiation. */
unsigned reachable : 1;
/* Set once the function is lowered (i.e. its CFG is built). */ /* Set once the function is lowered (i.e. its CFG is built). */
unsigned lowered : 1; unsigned lowered : 1;
/* Set once the function has been instantiated and its callee /* Set once the function has been instantiated and its callee
...@@ -416,9 +409,6 @@ struct GTY(()) varpool_node { ...@@ -416,9 +409,6 @@ struct GTY(()) varpool_node {
/* For aliases points to declaration DECL is alias of. */ /* For aliases points to declaration DECL is alias of. */
tree alias_of; tree alias_of;
/* Set when function must be output - it is externally visible
or its address is taken. */
unsigned needed : 1;
/* Set once the variable has been instantiated and its callee /* Set once the variable has been instantiated and its callee
lists created. */ lists created. */
unsigned analyzed : 1; unsigned analyzed : 1;
...@@ -589,13 +579,11 @@ VEC (cgraph_edge_p, heap) * collect_callers_of_node (struct cgraph_node *node); ...@@ -589,13 +579,11 @@ VEC (cgraph_edge_p, heap) * collect_callers_of_node (struct cgraph_node *node);
/* In cgraphunit.c */ /* In cgraphunit.c */
extern FILE *cgraph_dump_file; extern FILE *cgraph_dump_file;
void cgraph_finalize_function (tree, bool); void cgraph_finalize_function (tree, bool);
void cgraph_mark_if_needed (tree);
void cgraph_analyze_function (struct cgraph_node *); void cgraph_analyze_function (struct cgraph_node *);
void cgraph_finalize_compilation_unit (void); void cgraph_finalize_compilation_unit (void);
void cgraph_optimize (void); void cgraph_optimize (void);
void cgraph_mark_force_output_node (struct cgraph_node *); void cgraph_mark_force_output_node (struct cgraph_node *);
void cgraph_mark_address_taken_node (struct cgraph_node *); void cgraph_mark_address_taken_node (struct cgraph_node *);
void cgraph_mark_reachable_node (struct cgraph_node *);
bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason); bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
bool cgraph_preserve_function_body_p (struct cgraph_node *); bool cgraph_preserve_function_body_p (struct cgraph_node *);
void verify_cgraph (void); void verify_cgraph (void);
......
...@@ -362,9 +362,6 @@ cgraph_finalize_function (tree decl, bool nested) ...@@ -362,9 +362,6 @@ cgraph_finalize_function (tree decl, bool nested)
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
node->symbol.force_output = 1; node->symbol.force_output = 1;
if (cgraph_decide_is_function_needed (node, decl))
cgraph_mark_reachable_node (node);
/* If we've not yet emitted decl, tell the debug info about it. */ /* If we've not yet emitted decl, tell the debug info about it. */
if (!TREE_ASM_WRITTEN (decl)) if (!TREE_ASM_WRITTEN (decl))
(*debug_hooks->deferred_inline_function) (decl); (*debug_hooks->deferred_inline_function) (decl);
...@@ -416,7 +413,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) ...@@ -416,7 +413,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
node = cgraph_get_create_node (fndecl); node = cgraph_get_create_node (fndecl);
node->local.local = false; node->local.local = false;
node->local.finalized = true; node->local.finalized = true;
node->reachable = node->symbol.force_output = true; node->symbol.force_output = true;
if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION) if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
{ {
push_cfun (DECL_STRUCT_FUNCTION (fndecl)); push_cfun (DECL_STRUCT_FUNCTION (fndecl));
...@@ -468,18 +465,6 @@ cgraph_add_new_function (tree fndecl, bool lowered) ...@@ -468,18 +465,6 @@ cgraph_add_new_function (tree fndecl, bool lowered)
DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
} }
/* C99 extern inline keywords allow changing of declaration after function
has been finalized. We need to re-decide if we want to mark the function as
needed then. */
void
cgraph_mark_if_needed (tree decl)
{
struct cgraph_node *node = cgraph_get_node (decl);
if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
cgraph_mark_reachable_node (node);
}
/* Return TRUE if NODE2 is equivalent to NODE or its clone. */ /* Return TRUE if NODE2 is equivalent to NODE or its clone. */
static bool static bool
clone_of_p (struct cgraph_node *node, struct cgraph_node *node2) clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
...@@ -916,7 +901,6 @@ cgraph_analyze_function (struct cgraph_node *node) ...@@ -916,7 +901,6 @@ cgraph_analyze_function (struct cgraph_node *node)
if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references)) if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
ipa_record_reference ((symtab_node)node, (symtab_node)tgt, ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
IPA_REF_ALIAS, NULL); IPA_REF_ALIAS, NULL);
cgraph_mark_reachable_node (tgt);
if (node->same_body_alias) if (node->same_body_alias)
{ {
DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias); DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
...@@ -952,11 +936,8 @@ cgraph_analyze_function (struct cgraph_node *node) ...@@ -952,11 +936,8 @@ cgraph_analyze_function (struct cgraph_node *node)
} }
} }
} }
cgraph_mark_reachable_node (cgraph_alias_aliased_node (node));
if (node->symbol.address_taken) if (node->symbol.address_taken)
cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node)); cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
if (cgraph_decide_is_function_needed (node, node->symbol.decl))
cgraph_mark_reachable_node (node);
} }
else if (node->thunk.thunk_p) else if (node->thunk.thunk_p)
{ {
...@@ -1078,21 +1059,12 @@ process_function_and_variable_attributes (struct cgraph_node *first, ...@@ -1078,21 +1059,12 @@ process_function_and_variable_attributes (struct cgraph_node *first,
tree decl = node->symbol.decl; tree decl = node->symbol.decl;
if (DECL_PRESERVE_P (decl)) if (DECL_PRESERVE_P (decl))
cgraph_mark_force_output_node (node); cgraph_mark_force_output_node (node);
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
&& TREE_PUBLIC (node->symbol.decl))
{
if (node->local.finalized)
cgraph_mark_reachable_node (node);
}
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
{ {
if (! TREE_PUBLIC (node->symbol.decl)) if (! TREE_PUBLIC (node->symbol.decl))
warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes, warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
"%<externally_visible%>" "%<externally_visible%>"
" attribute have effect only on public objects"); " attribute have effect only on public objects");
else if (node->local.finalized)
cgraph_mark_reachable_node (node);
} }
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
&& (node->local.finalized && !node->alias)) && (node->local.finalized && !node->alias))
...@@ -1280,11 +1252,8 @@ cgraph_analyze_functions (void) ...@@ -1280,11 +1252,8 @@ cgraph_analyze_functions (void)
cgraph_analyze_function (cnode); cgraph_analyze_function (cnode);
for (edge = cnode->callees; edge; edge = edge->next_callee) for (edge = cnode->callees; edge; edge = edge->next_callee)
{ if (edge->callee->local.finalized)
cgraph_mark_reachable_node (edge->callee); enqueue_node ((symtab_node)edge->callee);
if (edge->callee->local.finalized)
enqueue_node ((symtab_node)edge->callee);
}
/* If decl is a clone of an abstract function, mark that abstract /* If decl is a clone of an abstract function, mark that abstract
function so that we don't release its body. The DECL_INITIAL() of that function so that we don't release its body. The DECL_INITIAL() of that
...@@ -1300,9 +1269,7 @@ cgraph_analyze_functions (void) ...@@ -1300,9 +1269,7 @@ cgraph_analyze_functions (void)
} }
else if (symtab_variable_p (node) else if (symtab_variable_p (node)
&& varpool (node)->finalized) && varpool (node)->finalized)
{ varpool_analyze_node (varpool (node));
varpool_analyze_node (varpool (node));
}
if (node->symbol.same_comdat_group) if (node->symbol.same_comdat_group)
{ {
...@@ -1479,9 +1446,6 @@ cgraph_mark_functions_to_output (void) ...@@ -1479,9 +1446,6 @@ cgraph_mark_functions_to_output (void)
&& !node->thunk.thunk_p && !node->thunk.thunk_p
&& !node->alias && !node->alias
&& !node->global.inlined_to && !node->global.inlined_to
&& (!cgraph_only_called_directly_p (node)
|| ((e || ipa_ref_has_aliases_p (&node->symbol.ref_list))
&& node->reachable))
&& !TREE_ASM_WRITTEN (decl) && !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl)) && !DECL_EXTERNAL (decl))
{ {
...@@ -2085,7 +2049,6 @@ cgraph_expand_all_functions (void) ...@@ -2085,7 +2049,6 @@ cgraph_expand_all_functions (void)
node = order[i]; node = order[i];
if (node->process) if (node->process)
{ {
gcc_assert (node->reachable);
node->process = 0; node->process = 0;
cgraph_expand_function (node); cgraph_expand_function (node);
} }
...@@ -2370,7 +2333,6 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version, ...@@ -2370,7 +2333,6 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
new_version->local.local = old_version->analyzed; new_version->local.local = old_version->analyzed;
new_version->global = old_version->global; new_version->global = old_version->global;
new_version->rtl = old_version->rtl; new_version->rtl = old_version->rtl;
new_version->reachable = true;
new_version->count = old_version->count; new_version->count = old_version->count;
for (e = old_version->callees; e; e=e->next_callee) for (e = old_version->callees; e; e=e->next_callee)
......
...@@ -2483,7 +2483,7 @@ dbxout_expand_expr (tree expr) ...@@ -2483,7 +2483,7 @@ dbxout_expand_expr (tree expr)
return NULL, otherwise stabs might reference an undefined return NULL, otherwise stabs might reference an undefined
symbol. */ symbol. */
struct varpool_node *node = varpool_get_node (expr); struct varpool_node *node = varpool_get_node (expr);
if (!node || !node->needed) if (!node || !node->analyzed)
return NULL; return NULL;
} }
/* FALLTHRU */ /* FALLTHRU */
......
...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h" #include "target.h"
#include "tree-iterator.h" #include "tree-iterator.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "pointer-set.h"
/* Look for all functions inlined to NODE and update their inlined_to pointers /* Look for all functions inlined to NODE and update their inlined_to pointers
to INLINED_TO. */ to INLINED_TO. */
...@@ -57,14 +58,15 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined ...@@ -57,14 +58,15 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined
reachable. */ reachable. */
static void static void
enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first) enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first,
struct pointer_set_t *reachable)
{ {
/* Node is still in queue; do nothing. */ /* Node is still in queue; do nothing. */
if (node->symbol.aux && node->symbol.aux != (void *) 2) if (node->symbol.aux && node->symbol.aux != (void *) 2)
return; return;
/* Node was already processed as unreachable, re-enqueue /* Node was already processed as unreachable, re-enqueue
only if it became reachable now. */ only if it became reachable now. */
if (node->symbol.aux == (void *)2 && !node->reachable) if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
return; return;
node->symbol.aux = *first; node->symbol.aux = *first;
*first = node; *first = node;
...@@ -85,7 +87,8 @@ static void ...@@ -85,7 +87,8 @@ static void
process_references (struct ipa_ref_list *list, process_references (struct ipa_ref_list *list,
struct cgraph_node **first, struct cgraph_node **first,
struct varpool_node **first_varpool, struct varpool_node **first_varpool,
bool before_inlining_p) bool before_inlining_p,
struct pointer_set_t *reachable)
{ {
int i; int i;
struct ipa_ref *ref; struct ipa_ref *ref;
...@@ -94,22 +97,18 @@ process_references (struct ipa_ref_list *list, ...@@ -94,22 +97,18 @@ process_references (struct ipa_ref_list *list,
if (symtab_function_p (ref->referred)) if (symtab_function_p (ref->referred))
{ {
struct cgraph_node *node = ipa_ref_node (ref); struct cgraph_node *node = ipa_ref_node (ref);
if (!node->reachable if (node->analyzed
&& node->analyzed
&& (!DECL_EXTERNAL (node->symbol.decl) && (!DECL_EXTERNAL (node->symbol.decl)
|| node->alias || node->alias
|| before_inlining_p)) || before_inlining_p))
node->reachable = true; pointer_set_insert (reachable, node);
enqueue_cgraph_node (node, first); enqueue_cgraph_node (node, first, reachable);
} }
else else
{ {
struct varpool_node *node = ipa_ref_varpool_node (ref); struct varpool_node *node = ipa_ref_varpool_node (ref);
if (!node->needed) if (!pointer_set_insert (reachable, node))
{ enqueue_varpool_node (node, first_varpool);
node->needed = true;
enqueue_varpool_node (node, first_varpool);
}
} }
} }
} }
...@@ -175,6 +174,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -175,6 +174,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
struct cgraph_node *node, *next; struct cgraph_node *node, *next;
struct varpool_node *vnode, *vnext; struct varpool_node *vnode, *vnext;
bool changed = false; bool changed = false;
struct pointer_set_t *reachable = pointer_set_create ();
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_symtab (); verify_symtab ();
...@@ -200,14 +200,11 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -200,14 +200,11 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
&& (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))))) && (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
{ {
gcc_assert (!node->global.inlined_to); gcc_assert (!node->global.inlined_to);
enqueue_cgraph_node (node, &first); enqueue_cgraph_node (node, &first, reachable);
node->reachable = true; pointer_set_insert (reachable, node);
} }
else else
{ gcc_assert (!node->symbol.aux);
gcc_assert (!node->symbol.aux);
node->reachable = false;
}
/* Mark variables that are obviously needed. */ /* Mark variables that are obviously needed. */
FOR_EACH_VARIABLE (vnode) FOR_EACH_VARIABLE (vnode)
...@@ -215,11 +212,9 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -215,11 +212,9 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
if ((vnode->analyzed || vnode->symbol.force_output) if ((vnode->analyzed || vnode->symbol.force_output)
&& !varpool_can_remove_if_no_refs (vnode)) && !varpool_can_remove_if_no_refs (vnode))
{ {
vnode->needed = true; pointer_set_insert (reachable, vnode);
enqueue_varpool_node (vnode, &first_varpool); enqueue_varpool_node (vnode, &first_varpool);
} }
else
vnode->needed = false;
} }
/* Perform reachability analysis. As a special case do not consider /* Perform reachability analysis. As a special case do not consider
...@@ -237,44 +232,39 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -237,44 +232,39 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
struct cgraph_edge *e; struct cgraph_edge *e;
node = first; node = first;
first = (struct cgraph_node *) first->symbol.aux; first = (struct cgraph_node *) first->symbol.aux;
if (!node->reachable) if (!pointer_set_contains (reachable, node))
node->symbol.aux = (void *)2; node->symbol.aux = (void *)2;
/* If we found this node reachable, first mark on the callees /* If we found this node reachable, first mark on the callees
reachable too, unless they are direct calls to extern inline functions reachable too, unless they are direct calls to extern inline functions
we decided to not inline. */ we decided to not inline. */
if (node->reachable) else
{ {
for (e = node->callees; e; e = e->next_callee) for (e = node->callees; e; e = e->next_callee)
{ {
if (!e->callee->reachable if (node->analyzed
&& node->analyzed
&& (!e->inline_failed && (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->symbol.decl) || !DECL_EXTERNAL (e->callee->symbol.decl)
|| node->alias || node->alias
|| before_inlining_p)) || before_inlining_p))
e->callee->reachable = true; pointer_set_insert (reachable, e->callee);
enqueue_cgraph_node (e->callee, &first); enqueue_cgraph_node (e->callee, &first, reachable);
} }
process_references (&node->symbol.ref_list, &first, process_references (&node->symbol.ref_list, &first,
&first_varpool, before_inlining_p); &first_varpool, before_inlining_p,
} reachable);
/* If any function in a comdat group is reachable, force /* If any function in a comdat group is reachable, force
all other functions in the same comdat group to be all other functions in the same comdat group to be
also reachable. */ also reachable. */
if (node->symbol.same_comdat_group if (node->symbol.same_comdat_group
&& node->reachable && !node->global.inlined_to)
&& !node->global.inlined_to) {
{ for (next = cgraph (node->symbol.same_comdat_group);
for (next = cgraph (node->symbol.same_comdat_group); next != node;
next != node; next = cgraph (next->symbol.same_comdat_group))
next = cgraph (next->symbol.same_comdat_group)) if (!pointer_set_insert (reachable, next))
if (!next->reachable) enqueue_cgraph_node (next, &first, reachable);
{ }
next->reachable = true;
enqueue_cgraph_node (next, &first);
}
} }
/* We can freely remove inline clones even if they are cloned, however if /* We can freely remove inline clones even if they are cloned, however if
...@@ -286,9 +276,9 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -286,9 +276,9 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
{ {
bool noninline = node->clone_of->symbol.decl != node->symbol.decl; bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
node = node->clone_of; node = node->clone_of;
if (noninline && !node->reachable && !node->symbol.aux) if (noninline && !pointer_set_insert (reachable, node) && !node->symbol.aux)
{ {
enqueue_cgraph_node (node, &first); enqueue_cgraph_node (node, &first, reachable);
break; break;
} }
} }
...@@ -299,7 +289,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -299,7 +289,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
first_varpool = (struct varpool_node *)first_varpool->symbol.aux; first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
vnode->symbol.aux = NULL; vnode->symbol.aux = NULL;
process_references (&vnode->symbol.ref_list, &first, process_references (&vnode->symbol.ref_list, &first,
&first_varpool, before_inlining_p); &first_varpool, before_inlining_p,
reachable);
/* If any function in a comdat group is reachable, force /* If any function in a comdat group is reachable, force
all other functions in the same comdat group to be all other functions in the same comdat group to be
also reachable. */ also reachable. */
...@@ -309,11 +300,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -309,11 +300,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
for (next = varpool (vnode->symbol.same_comdat_group); for (next = varpool (vnode->symbol.same_comdat_group);
next != vnode; next != vnode;
next = varpool (next->symbol.same_comdat_group)) next = varpool (next->symbol.same_comdat_group))
if (!next->needed) if (!pointer_set_insert (reachable, next))
{ enqueue_varpool_node (next, &first_varpool);
next->needed = true;
enqueue_varpool_node (next, &first_varpool);
}
} }
} }
} }
...@@ -330,7 +318,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -330,7 +318,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
for (node = cgraph_first_function (); node; node = next) for (node = cgraph_first_function (); node; node = next)
{ {
next = cgraph_next_function (node); next = cgraph_next_function (node);
if (node->symbol.aux && !node->reachable) if (node->symbol.aux && !pointer_set_contains (reachable, node))
{ {
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->symbol.ref_list); ipa_remove_all_references (&node->symbol.ref_list);
...@@ -348,16 +336,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -348,16 +336,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
fprintf (file, " %s", cgraph_node_name (node)); fprintf (file, " %s", cgraph_node_name (node));
/* See if there is reachable caller. */ /* See if there is reachable caller. */
for (e = node->callers; e && !found; e = e->next_caller) for (e = node->callers; e && !found; e = e->next_caller)
if (e->caller->reachable) if (pointer_set_contains (reachable, e->caller))
found = true; found = true;
for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list, for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
i, ref) i, ref)
&& !found); i++) && !found); i++)
if (symtab_function_p (ref->referring) if (pointer_set_contains (reachable, ref->referring))
&& ipa_ref_referring_node (ref)->reachable)
found = true;
else if (symtab_variable_p (ref->referring)
&& ipa_ref_referring_varpool_node (ref)->needed)
found = true; found = true;
/* If so, we need to keep node in the callgraph. */ /* If so, we need to keep node in the callgraph. */
...@@ -426,7 +410,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -426,7 +410,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
for (vnode = varpool_first_variable (); vnode; vnode = vnext) for (vnode = varpool_first_variable (); vnode; vnode = vnext)
{ {
vnext = varpool_next_variable (vnode); vnext = varpool_next_variable (vnode);
if (!vnode->needed) if (!pointer_set_contains (reachable, vnode))
{ {
if (file) if (file)
fprintf (file, " %s", varpool_node_name (vnode)); fprintf (file, " %s", varpool_node_name (vnode));
...@@ -471,6 +455,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -471,6 +455,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
/* Reclaim alias pairs for functions that have disappeared from the /* Reclaim alias pairs for functions that have disappeared from the
call graph. */ call graph. */
remove_unreachable_alias_pairs (); remove_unreachable_alias_pairs ();
pointer_set_destroy (reachable);
return changed; return changed;
} }
...@@ -1010,14 +995,7 @@ gate_whole_program_function_and_variable_visibility (void) ...@@ -1010,14 +995,7 @@ gate_whole_program_function_and_variable_visibility (void)
static unsigned int static unsigned int
whole_program_function_and_variable_visibility (void) whole_program_function_and_variable_visibility (void)
{ {
struct cgraph_node *node;
function_and_variable_visibility (flag_whole_program); function_and_variable_visibility (flag_whole_program);
FOR_EACH_DEFINED_FUNCTION (node)
if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl))
&& node->local.finalized)
cgraph_mark_reachable_node (node);
if (optimize) if (optimize)
ipa_discover_readonly_nonaddressable_vars (); ipa_discover_readonly_nonaddressable_vars ();
return 0; return 0;
......
...@@ -225,8 +225,6 @@ lto_cgraph_replace_node (struct cgraph_node *node, ...@@ -225,8 +225,6 @@ lto_cgraph_replace_node (struct cgraph_node *node,
/* Merge node flags. */ /* Merge node flags. */
if (node->symbol.force_output) if (node->symbol.force_output)
cgraph_mark_force_output_node (prevailing_node); cgraph_mark_force_output_node (prevailing_node);
if (node->reachable)
cgraph_mark_reachable_node (prevailing_node);
if (node->symbol.address_taken) if (node->symbol.address_taken)
{ {
gcc_assert (!prevailing_node->global.inlined_to); gcc_assert (!prevailing_node->global.inlined_to);
......
...@@ -4779,7 +4779,7 @@ ipa_tm_execute (void) ...@@ -4779,7 +4779,7 @@ ipa_tm_execute (void)
/* For all local reachable functions... */ /* For all local reachable functions... */
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (node->reachable && node->lowered if (node->lowered
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{ {
/* ... marked tm_pure, record that fact for the runtime by /* ... marked tm_pure, record that fact for the runtime by
...@@ -4947,7 +4947,7 @@ ipa_tm_execute (void) ...@@ -4947,7 +4947,7 @@ ipa_tm_execute (void)
/* Now validate all tm_safe functions, and all atomic regions in /* Now validate all tm_safe functions, and all atomic regions in
other functions. */ other functions. */
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (node->reachable && node->lowered if (node->lowered
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{ {
d = get_cg_data (&node, true); d = get_cg_data (&node, true);
...@@ -4995,7 +4995,7 @@ ipa_tm_execute (void) ...@@ -4995,7 +4995,7 @@ ipa_tm_execute (void)
} }
} }
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (node->reachable && node->lowered if (node->lowered
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{ {
d = get_cg_data (&node, true); d = get_cg_data (&node, true);
......
...@@ -791,7 +791,7 @@ ipa_lower_emutls (void) ...@@ -791,7 +791,7 @@ ipa_lower_emutls (void)
/* Adjust all uses of TLS variables within the function bodies. */ /* Adjust all uses of TLS variables within the function bodies. */
FOR_EACH_DEFINED_FUNCTION (func) FOR_EACH_DEFINED_FUNCTION (func)
if (func->reachable && func->lowered) if (func->lowered)
lower_emutls_function_body (func); lower_emutls_function_body (func);
/* Generate the constructor for any COMMON control variables created. */ /* Generate the constructor for any COMMON control variables created. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment