lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.

* lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
	* cgraph.c (cgraph_add_thunk): Use mark_reachable_node.
	(cgraph_remove_node): Update.
	(cgraph_mark_needed_node): Remove.
	(cgraph_mark_force_output_node): New.
	(dump_cgraph_node): Do not dump needed flag.
	(cgraph_node_cannot_be_local_p_1): Update.
	(cgraph_can_remove_if_no_direct_calls_and_refs): Update.
	* cgraph.h (symtab_node_base): Add force_output flag.
	(cgraph_node): Remove needed flag.
	(varpool_node): Remove force_output flag.
	(cgraph_mark_needed_node): Remove.
	(cgraph_mark_force_output_node): New.
	(cgraph_only_called_directly_or_aliased_p,
	varpool_can_remove_if_no_refs, varpool_all_refs_explicit_p): Update.
	* ipa-cp.c (ipcp_generate_summary): Remove out of date assert.
	* cgraphunit.c (cgraph_decide_is_function_needed): rewrite.
	(cgraph_add_new_function); Update.
	(cgraph_mark_if_needed); Update.
	(verify_cgraph_node): Update.
	(cgraph_analyze_function): Alias target is reachable.
	(process_function_and_variable_attributes): Update: externally_visible
	flag makes function reachable.
	(cgraph_analyze_functions): Update dumping.
	* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
	input_overwrite_node, input_varpool_node): Update streaming.
	* lto-streamer-out.c (produce_symtab): Use force_output.
	* ipa.c (process_references): Weakrefs must be processed.
	(cgraph_remove_unreachable_nodes): Likewise; update for new
	force_output flag.
	(varpool_externally_visible_p); Weakrefs are externally visible
	even if they are not.
	(function_and_variable_visibility): Update; when processing alias
	pair force the targets to be output.
	(whole_program_function_and_variable_visility): Use mark_reachable_node.
	* trans-mem.c (ipa_tm_mark_needed_node): Remove
	(ipa_tm_mark_force_output_node): New function.
	(ipa_tm_create_version_alias, ipa_tm_create_version): Update.
	* gimple-fold.c (can_refer_decl_in_current_unit_p): Be lax about aliases.
	* varasm.c (mark_decl_referenced): Update.
	(find_decl_and_mark_needed): Remove.
	(find_decl): New function.
	(weak_finish, finish_aliases_1, assemble_alias): Update; do not mark
	alias targets as needed.
	(dump_tm_clone_pairs): Update.
	* tree-inline.c (copy_bb): Update check.
	* symtab.c (dump_symtab_base): Dump force_output.
	* tree-ssa-structalias.c (ipa_pta_execute): Use force_output.
	* passes.c (execute_todo): Fix dumping.
	* varpool.c (decide_is_variable_needed, varpool_finalize_decl): Update.
	(varpool_analyze_pending_decls): Alias target is reachable.
	(varpool_create_variable_alias): Finalize weakrefs.

	* class.c (make_local_function_alias): Do not mark symbol referenced.

	* objc-acct.c (mark_referenced_methods); Use
	cgraph_mark_force_output_node.

	* gcc-interface/utils.c (gnat_write_global_declarations): Update for new
	force_output placement.

	* lto/lto-partition.c (partition_cgraph_node_p): Use force_output.

From-SVN: r186624
This commit is contained in:
Jan Hubicka 2012-04-20 16:09:11 +02:00 committed by Jan Hubicka
parent 757e8ba242
commit ead84f73b0
25 changed files with 201 additions and 168 deletions

View File

@ -1,3 +1,58 @@
2012-04-20 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
* cgraph.c (cgraph_add_thunk): Use mark_reachable_node.
(cgraph_remove_node): Update.
(cgraph_mark_needed_node): Remove.
(cgraph_mark_force_output_node): New.
(dump_cgraph_node): Do not dump needed flag.
(cgraph_node_cannot_be_local_p_1): Update.
(cgraph_can_remove_if_no_direct_calls_and_refs): Update.
* cgraph.h (symtab_node_base): Add force_output flag.
(cgraph_node): Remove needed flag.
(varpool_node): Remove force_output flag.
(cgraph_mark_needed_node): Remove.
(cgraph_mark_force_output_node): New.
(cgraph_only_called_directly_or_aliased_p,
varpool_can_remove_if_no_refs, varpool_all_refs_explicit_p): Update.
* ipa-cp.c (ipcp_generate_summary): Remove out of date assert.
* cgraphunit.c (cgraph_decide_is_function_needed): rewrite.
(cgraph_add_new_function); Update.
(cgraph_mark_if_needed); Update.
(verify_cgraph_node): Update.
(cgraph_analyze_function): Alias target is reachable.
(process_function_and_variable_attributes): Update: externally_visible
flag makes function reachable.
(cgraph_analyze_functions): Update dumping.
* lto-cgraph.c (lto_output_node, lto_output_varpool_node,
input_overwrite_node, input_varpool_node): Update streaming.
* lto-streamer-out.c (produce_symtab): Use force_output.
* ipa.c (process_references): Weakrefs must be processed.
(cgraph_remove_unreachable_nodes): Likewise; update for new
force_output flag.
(varpool_externally_visible_p); Weakrefs are externally visible
even if they are not.
(function_and_variable_visibility): Update; when processing alias
pair force the targets to be output.
(whole_program_function_and_variable_visility): Use mark_reachable_node.
* trans-mem.c (ipa_tm_mark_needed_node): Remove
(ipa_tm_mark_force_output_node): New function.
(ipa_tm_create_version_alias, ipa_tm_create_version): Update.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Be lax about aliases.
* varasm.c (mark_decl_referenced): Update.
(find_decl_and_mark_needed): Remove.
(find_decl): New function.
(weak_finish, finish_aliases_1, assemble_alias): Update; do not mark
alias targets as needed.
(dump_tm_clone_pairs): Update.
* tree-inline.c (copy_bb): Update check.
* symtab.c (dump_symtab_base): Dump force_output.
* tree-ssa-structalias.c (ipa_pta_execute): Use force_output.
* passes.c (execute_todo): Fix dumping.
* varpool.c (decide_is_variable_needed, varpool_finalize_decl): Update.
(varpool_analyze_pending_decls): Alias target is reachable.
(varpool_create_variable_alias): Finalize weakrefs.
2012-04-20 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/53021

View File

@ -1,3 +1,8 @@
2012-04-20 Jan Hubicka <jh@suse.cz>
* gcc-interface/utils.c (gnat_write_global_declarations): Update for new
force_output placement.
2012-04-14 Jan Hubicka <jh@suse.cz>
* gcc-interface/trans.c (finalize_nrv): Update field referenced for new

View File

@ -4859,7 +4859,7 @@ gnat_write_global_declarations (void)
TREE_STATIC (dummy_global) = 1;
TREE_ASM_WRITTEN (dummy_global) = 1;
node = varpool_node (dummy_global);
node->force_output = 1;
node->symbol.force_output = 1;
varpool_mark_needed_node (node);
while (!VEC_empty (tree, types_used_by_cur_var_decl))

View File

@ -570,7 +570,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
node->local.finalized = true;
if (cgraph_decide_is_function_needed (node, decl))
cgraph_mark_needed_node (node);
cgraph_mark_reachable_node (node);
if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|| (DECL_VIRTUAL_P (decl)
@ -1362,7 +1362,7 @@ cgraph_remove_node (struct cgraph_node *node)
/* Incremental inlining access removed nodes stored in the postorder list.
*/
node->needed = node->reachable = false;
node->symbol.force_output = node->reachable = false;
for (n = node->nested; n; n = n->next_nested)
n->origin = NULL;
node->nested = NULL;
@ -1518,9 +1518,9 @@ cgraph_mark_reachable_node (struct cgraph_node *node)
external means. */
void
cgraph_mark_needed_node (struct cgraph_node *node)
cgraph_mark_force_output_node (struct cgraph_node *node)
{
node->needed = 1;
node->symbol.force_output = 1;
gcc_assert (!node->global.inlined_to);
cgraph_mark_reachable_node (node);
}
@ -1642,8 +1642,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
(HOST_WIDEST_INT)node->count);
if (node->origin)
fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin));
if (node->needed)
fprintf (f, " needed");
else if (node->reachable)
fprintf (f, " reachable");
if (gimple_has_body_p (node->symbol.decl))
@ -2134,7 +2132,7 @@ static bool
cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED)
{
return !(!node->needed
return !(!node->symbol.force_output
&& ((DECL_COMDAT (node->symbol.decl)
&& !node->symbol.same_comdat_group)
|| !node->symbol.externally_visible));
@ -2570,7 +2568,7 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
if (DECL_EXTERNAL (node->symbol.decl))
return true;
/* When function is needed, we can not remove it. */
if (node->needed || node->symbol.used_from_other_partition)
if (node->symbol.force_output || node->symbol.used_from_other_partition)
return false;
if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
|| DECL_STATIC_DESTRUCTOR (node->symbol.decl))

View File

@ -77,6 +77,9 @@ struct GTY(()) symtab_node_base
unsigned in_other_partition : 1;
/* Set when function is visible by other units. */
unsigned externally_visible : 1;
/* Needed variables might become dead by optimization. This flag
forces the variable to be output even if it appears dead otherwise. */
unsigned force_output : 1;
};
enum availability
@ -246,12 +249,6 @@ struct GTY(()) cgraph_node {
/* Unique id of the node. */
int uid;
/* Set when function must be output for some reason. The primary
use of this flag is to mark functions needed to be output for
non-standard reason. Functions that are externally visible
or reachable from functions needed to be output are marked
by specialized flags. */
unsigned needed : 1;
/* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */
unsigned abstract_and_needed : 1;
@ -433,9 +430,6 @@ struct GTY(()) varpool_node {
/* Set when function must be output - it is externally visible
or its address is taken. */
unsigned needed : 1;
/* Needed variables might become dead by optimization. This flag
forces the variable to be output even if it appears dead otherwise. */
unsigned force_output : 1;
/* Set once the variable has been instantiated and its callee
lists created. */
unsigned analyzed : 1;
@ -610,7 +604,7 @@ void cgraph_mark_if_needed (tree);
void cgraph_analyze_function (struct cgraph_node *);
void cgraph_finalize_compilation_unit (void);
void cgraph_optimize (void);
void cgraph_mark_needed_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_reachable_node (struct cgraph_node *);
bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
@ -1118,7 +1112,7 @@ static inline bool
cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
{
gcc_assert (!node->global.inlined_to);
return (!node->needed && !node->symbol.address_taken
return (!node->symbol.force_output && !node->symbol.address_taken
&& !node->symbol.used_from_other_partition
&& !DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
&& !DECL_STATIC_DESTRUCTOR (node->symbol.decl)
@ -1131,9 +1125,10 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
static inline bool
varpool_can_remove_if_no_refs (struct varpool_node *node)
{
return (!node->force_output && !node->symbol.used_from_other_partition
return (!node->symbol.force_output && !node->symbol.used_from_other_partition
&& (DECL_COMDAT (node->symbol.decl)
|| !node->symbol.externally_visible));
|| !node->symbol.externally_visible
|| DECL_EXTERNAL (node->symbol.decl)));
}
/* Return true when all references to VNODE must be visible in ipa_ref_list.
@ -1147,7 +1142,7 @@ varpool_all_refs_explicit_p (struct varpool_node *vnode)
return (vnode->analyzed
&& !vnode->symbol.externally_visible
&& !vnode->symbol.used_from_other_partition
&& !vnode->force_output);
&& !vnode->symbol.force_output);
}
/* Constant pool accessor function. */

View File

@ -156,56 +156,36 @@ FILE *cgraph_dump_file;
/* Used for vtable lookup in thunk adjusting. */
static GTY (()) tree vtable_entry_type;
/* Determine if function DECL is needed. That is, visible to something
either outside this translation unit, something magic in the system
configury. */
/* Determine if function DECL is trivially needed and should stay in the
compilation unit. This is used at the symbol table construction time
and differs from later logic removing unnecesary functions that can
take into account results of analysis, whole program info etc. */
bool
cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
if (node->symbol.externally_visible)
if (node->symbol.force_output)
return true;
/* ??? If the assembler name is set by hand, it is possible to assemble
the name later after finalizing the function and the fact is noticed
in assemble_name then. This is arguably a bug. */
if (DECL_ASSEMBLER_NAME_SET_P (decl)
&& (!node->thunk.thunk_p && !node->same_body_alias)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
return true;
/* Double check that no one output the function into assembly file
early. */
gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
|| (node->thunk.thunk_p || node->same_body_alias)
|| !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
/* With -fkeep-inline-functions we are keeping all inline functions except
for extern inline ones. */
if (flag_keep_inline_functions
&& DECL_DECLARED_INLINE_P (decl)
&& !DECL_EXTERNAL (decl)
&& !DECL_DISREGARD_INLINE_LIMITS (decl))
/* Keep constructors, destructors and virtual functions. */
if (DECL_STATIC_CONSTRUCTOR (decl)
|| DECL_STATIC_DESTRUCTOR (decl)
|| (DECL_VIRTUAL_P (decl)
&& optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
return true;
/* If we decided it was needed before, but at the time we didn't have
the body of the function available, then it's still needed. We have
to go back and re-check its dependencies now. */
if (node->needed)
return true;
/* Externally visible functions must be output. The exception is
COMDAT functions that must be output only when they are needed.
COMDAT functions that must be output only when they are needed. */
When not optimizing, also output the static functions. (see
PR24561), but don't do so for always_inline functions, functions
declared inline and nested functions. These were optimized out
in the original implementation and it is unclear whether we want
to change the behavior here. */
if (((TREE_PUBLIC (decl)
|| (!optimize
&& !node->same_body_alias
&& !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl)
&& !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
&& !flag_whole_program
&& !flag_lto)
if (TREE_PUBLIC (decl)
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
return true;
@ -337,22 +317,29 @@ cgraph_finalize_function (tree decl, bool nested)
node->local.finalized = true;
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
if (cgraph_decide_is_function_needed (node, decl))
cgraph_mark_needed_node (node);
/* With -fkeep-inline-functions we are keeping all inline functions except
for extern inline ones. */
if (flag_keep_inline_functions
&& DECL_DECLARED_INLINE_P (decl)
&& !DECL_EXTERNAL (decl)
&& !DECL_DISREGARD_INLINE_LIMITS (decl))
node->symbol.force_output = 1;
/* Since we reclaim unreachable nodes at the end of every language
level unit, we need to be conservative about possible entry points
there. */
if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|| DECL_STATIC_CONSTRUCTOR (decl)
|| DECL_STATIC_DESTRUCTOR (decl)
/* COMDAT virtual functions may be referenced by vtable from
other compilation unit. Still we want to devirtualize calls
to those so we need to analyze them.
FIXME: We should introduce may edges for this purpose and update
their handling in unreachable function removal and inliner too. */
|| (DECL_VIRTUAL_P (decl)
&& optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
/* When not optimizing, also output the static functions. (see
PR24561), but don't do so for always_inline functions, functions
declared inline and nested functions. These were optimized out
in the original implementation and it is unclear whether we want
to change the behavior here. */
if ((!optimize
&& !node->same_body_alias
&& !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl)
&& !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
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. */
@ -402,7 +389,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
node = cgraph_get_create_node (fndecl);
node->local.local = false;
node->local.finalized = true;
node->reachable = node->needed = true;
node->reachable = node->symbol.force_output = true;
if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
{
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
@ -462,7 +449,7 @@ 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_needed_node (node);
cgraph_mark_reachable_node (node);
}
/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
@ -601,9 +588,9 @@ verify_cgraph_node (struct cgraph_node *node)
error ("inline clone with address taken");
error_found = true;
}
if (node->global.inlined_to && node->needed)
if (node->global.inlined_to && node->symbol.force_output)
{
error ("inline clone is needed");
error ("inline clone is forced to output");
error_found = true;
}
for (e = node->indirect_calls; e; e = e->next_callee)
@ -901,6 +888,7 @@ cgraph_analyze_function (struct cgraph_node *node)
if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
IPA_REF_ALIAS, NULL);
cgraph_mark_reachable_node (tgt);
if (node->same_body_alias)
{
DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
@ -940,7 +928,7 @@ cgraph_analyze_function (struct cgraph_node *node)
if (node->symbol.address_taken)
cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
if (cgraph_decide_is_function_needed (node, node->symbol.decl))
cgraph_mark_needed_node (node);
cgraph_mark_reachable_node (node);
}
else if (node->thunk.thunk_p)
{
@ -1061,13 +1049,13 @@ process_function_and_variable_attributes (struct cgraph_node *first,
{
tree decl = node->symbol.decl;
if (DECL_PRESERVE_P (decl))
cgraph_mark_needed_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_needed_node (node);
cgraph_mark_reachable_node (node);
}
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
{
@ -1076,7 +1064,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
"%<externally_visible%>"
" attribute have effect only on public objects");
else if (node->local.finalized)
cgraph_mark_needed_node (node);
cgraph_mark_reachable_node (node);
}
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
&& (node->local.finalized && !node->alias))
@ -1104,7 +1092,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
tree decl = vnode->symbol.decl;
if (DECL_PRESERVE_P (decl))
{
vnode->force_output = true;
vnode->symbol.force_output = true;
if (vnode->finalized)
varpool_mark_needed_node (vnode);
}
@ -1165,7 +1153,7 @@ cgraph_analyze_functions (void)
fprintf (cgraph_dump_file, "Initial entry points:");
for (node = cgraph_first_function (); node != first_analyzed;
node = cgraph_next_function (node))
if (node->needed)
if (cgraph_decide_is_function_needed (node, node->symbol.decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n");
}
@ -1241,7 +1229,7 @@ cgraph_analyze_functions (void)
fprintf (cgraph_dump_file, "Unit entry points:");
for (node = cgraph_first_function (); node != first_analyzed;
node = cgraph_next_function (node))
if (node->needed)
if (cgraph_decide_is_function_needed (node, node->symbol.decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n\nInitial ");
dump_symtab (cgraph_dump_file);

View File

@ -70,6 +70,7 @@ can_refer_decl_in_current_unit_p (tree decl)
flags incorrectly. Those variables should never
be finalized. */
gcc_checking_assert (!(vnode = varpool_get_node (decl))
|| vnode->alias
|| !vnode->finalized);
return false;
}

View File

@ -2494,8 +2494,6 @@ ipcp_generate_summary (void)
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
{
/* Unreachable nodes should have been eliminated before ipcp. */
gcc_assert (node->needed || node->reachable);
node->local.versionable
= tree_versionable_function_p (node->symbol.decl);
ipa_analyze_node (node);

View File

@ -97,6 +97,7 @@ process_references (struct ipa_ref_list *list,
if (!node->reachable
&& node->analyzed
&& (!DECL_EXTERNAL (node->symbol.decl)
|| node->alias
|| before_inlining_p))
node->reachable = true;
enqueue_cgraph_node (node, first);
@ -214,7 +215,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
{
vnode->next_needed = NULL;
vnode->prev_needed = NULL;
if ((vnode->analyzed || vnode->force_output)
if ((vnode->analyzed || vnode->symbol.force_output)
&& !varpool_can_remove_if_no_refs (vnode))
{
vnode->needed = false;
@ -254,6 +255,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
&& node->analyzed
&& (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->symbol.decl)
|| node->alias
|| before_inlining_p))
e->callee->reachable = true;
enqueue_cgraph_node (e->callee, &first);
@ -659,6 +661,12 @@ cgraph_externally_visible_p (struct cgraph_node *node,
bool
varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
{
/* Do not touch weakrefs; while they are not externally visible,
dropping their DECL_EXTERNAL flags confuse most
of code handling them. */
if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
return true;
if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
return false;
@ -700,7 +708,7 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
is faster for dynamic linking. Also this match logic hidding vtables
from LTO symbol tables. */
if ((in_lto_p || flag_whole_program)
&& !vnode->force_output
&& !vnode->symbol.force_output
&& DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
return false;
@ -776,8 +784,7 @@ function_and_variable_visibility (bool whole_program)
{
if (!node->analyzed)
continue;
cgraph_mark_needed_node (node);
gcc_assert (node->needed);
cgraph_mark_force_output_node (node);
pointer_set_insert (aliased_nodes, node);
if (dump_file)
fprintf (dump_file, " node %s/%i",
@ -786,6 +793,7 @@ function_and_variable_visibility (bool whole_program)
else if ((vnode = varpool_node_for_asm (p->target)) != NULL
&& !DECL_EXTERNAL (vnode->symbol.decl))
{
vnode->symbol.force_output = 1;
varpool_mark_needed_node (vnode);
gcc_assert (vnode->needed);
pointer_set_insert (aliased_vnodes, vnode);
@ -813,9 +821,9 @@ function_and_variable_visibility (bool whole_program)
/* Frontends and alias code marks nodes as needed before parsing is finished.
We may end up marking as node external nodes where this flag is meaningless
strip it. */
if (node->needed
if (node->symbol.force_output
&& (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
node->needed = 0;
node->symbol.force_output = 0;
/* C++ FE on lack of COMDAT support create local COMDAT functions
(that ought to be shared but can not due to object format
@ -1017,7 +1025,7 @@ whole_program_function_and_variable_visibility (void)
FOR_EACH_DEFINED_FUNCTION (node)
if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl))
&& node->local.finalized)
cgraph_mark_needed_node (node);
cgraph_mark_reachable_node (node);
FOR_EACH_DEFINED_VARIABLE (vnode)
if (vnode->symbol.externally_visible && !DECL_COMDAT (vnode->symbol.decl))
varpool_mark_needed_node (vnode);

View File

@ -1,3 +1,7 @@
2012-04-20 Jan Hubicka <jh@suse.cz>
* class.c (make_local_function_alias): Do not mark symbol referenced.
2012-04-11 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* jcf-dump.c (print_constant): Cast JPOOL_USHORT2, JPOOL_USHORT1

View File

@ -1407,7 +1407,6 @@ make_local_function_alias (tree method)
DECL_INITIAL (alias) = error_mark_node;
TREE_ADDRESSABLE (alias) = 1;
TREE_USED (alias) = 1;
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
if (!flag_syntax_only)
assemble_alias (alias, DECL_ASSEMBLER_NAME (method));
return alias;

View File

@ -503,7 +503,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 1);
bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
bp_pack_value (&bp, node->needed, 1);
bp_pack_value (&bp, node->symbol.force_output, 1);
bp_pack_value (&bp, node->symbol.address_taken, 1);
bp_pack_value (&bp, node->abstract_and_needed, 1);
bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node
@ -566,7 +566,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, node->symbol.externally_visible, 1);
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->symbol.force_output, 1);
bp_pack_value (&bp, node->finalized, 1);
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->alias_of != NULL, 1);
@ -911,7 +911,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = bp_unpack_value (bp, 1);
node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
node->needed = bp_unpack_value (bp, 1);
node->symbol.force_output = bp_unpack_value (bp, 1);
node->symbol.address_taken = bp_unpack_value (bp, 1);
node->abstract_and_needed = bp_unpack_value (bp, 1);
node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
@ -1075,7 +1075,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
bp = streamer_read_bitpack (ib);
node->symbol.externally_visible = bp_unpack_value (&bp, 1);
node->force_output = bp_unpack_value (&bp, 1);
node->symbol.force_output = bp_unpack_value (&bp, 1);
node->finalized = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1);
non_null_aliasof = bp_unpack_value (&bp, 1);

View File

@ -1456,7 +1456,7 @@ produce_symtab (struct output_block *ob,
in the LTO symbol table to prevent linker from forcing them
into the output. */
if (DECL_COMDAT (vnode->symbol.decl)
&& !vnode->force_output
&& !vnode->symbol.force_output
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->symbol.decl))
continue;
@ -1470,7 +1470,7 @@ produce_symtab (struct output_block *ob,
if (!DECL_EXTERNAL (vnode->symbol.decl))
continue;
if (DECL_COMDAT (vnode->symbol.decl)
&& !vnode->force_output
&& !vnode->symbol.force_output
&& vnode->finalized
&& DECL_VIRTUAL_P (vnode->symbol.decl))
continue;

View File

@ -223,8 +223,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
}
/* Merge node flags. */
if (node->needed)
cgraph_mark_needed_node (prevailing_node);
if (node->symbol.force_output)
cgraph_mark_force_output_node (prevailing_node);
if (node->reachable)
cgraph_mark_reachable_node (prevailing_node);
if (node->symbol.address_taken)

View File

@ -1,3 +1,7 @@
2012-04-20 Jan Hubicka <jh@suse.cz>
* lto-partition.c (partition_cgraph_node_p): Use force_output.
2012-04-18 Jan Hubicka <jh@suse.cz>
* lto-partition.c (add_references_to_partition, lto_balanced_map):

View File

@ -269,6 +269,7 @@ partition_cgraph_node_p (struct cgraph_node *node)
/* Extern inlines and comdat are always only in partitions they are needed. */
if (DECL_EXTERNAL (node->symbol.decl)
|| (DECL_COMDAT (node->symbol.decl)
&& !node->symbol.force_output
&& !cgraph_used_from_object_file_p (node)))
return false;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
@ -287,7 +288,7 @@ partition_varpool_node_p (struct varpool_node *vnode)
/* Constant pool and comdat are always only in partitions they are needed. */
if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
|| (DECL_COMDAT (vnode->symbol.decl)
&& !vnode->force_output
&& !vnode->symbol.force_output
&& !varpool_used_from_object_file_p (vnode)))
return false;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))

View File

@ -1,3 +1,8 @@
2012-04-20 Jan Hubicka <jh@suse.cz>
* objc-acct.c (mark_referenced_methods); Use
cgraph_mark_force_output_node.
2012-03-21 Steven Bosscher <steven@gcc.gnu.org>
* objc-act (objc_build_ivar_assignment): Do not call assemble_external.

View File

@ -4625,7 +4625,7 @@ mark_referenced_methods (void)
chain = CLASS_CLS_METHODS (impent->imp_context);
while (chain)
{
cgraph_mark_needed_node (
cgraph_mark_force_output_node (
cgraph_get_create_node (METHOD_DEFINITION (chain)));
chain = DECL_CHAIN (chain);
}
@ -4633,7 +4633,7 @@ mark_referenced_methods (void)
chain = CLASS_NST_METHODS (impent->imp_context);
while (chain)
{
cgraph_mark_needed_node (
cgraph_mark_force_output_node (
cgraph_get_create_node (METHOD_DEFINITION (chain)));
chain = DECL_CHAIN (chain);
}

View File

@ -1865,7 +1865,7 @@ execute_todo (unsigned int flags)
if ((flags & TODO_dump_symtab) && dump_file && !current_function_decl)
{
gcc_assert (!cfun);
dump_cgraph (dump_file);
dump_symtab (dump_file);
/* Flush the file. If verification fails, we won't be able to
close the file before aborting. */
fflush (dump_file);

View File

@ -378,6 +378,8 @@ dump_symtab_base (FILE *f, symtab_node node)
fprintf (f, " in_other_partition");
if (node->symbol.used_from_other_partition)
fprintf (f, " used_from_other_partition");
if (node->symbol.force_output)
fprintf (f, " force_output");
if (node->symbol.resolution != LDPR_UNKNOWN)
fprintf (f, " %s",
ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]);

View File

@ -4267,9 +4267,9 @@ tm_mangle (tree old_asm_id)
}
static inline void
ipa_tm_mark_needed_node (struct cgraph_node *node)
ipa_tm_mark_force_output_node (struct cgraph_node *node)
{
cgraph_mark_needed_node (node);
cgraph_mark_force_output_node (node);
/* ??? function_and_variable_visibility will reset
the needed bit, without actually checking. */
node->analyzed = 1;
@ -4328,8 +4328,8 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
record_tm_clone_pair (old_decl, new_decl);
if (info->old_node->needed)
ipa_tm_mark_needed_node (new_node);
if (info->old_node->symbol.force_output)
ipa_tm_mark_force_output_node (new_node);
return false;
}
@ -4381,8 +4381,8 @@ ipa_tm_create_version (struct cgraph_node *old_node)
record_tm_clone_pair (old_decl, new_decl);
cgraph_call_function_insertion_hooks (new_node);
if (old_node->needed)
ipa_tm_mark_needed_node (new_node);
if (old_node->symbol.force_output)
ipa_tm_mark_force_output_node (new_node);
/* Do the same thing, but for any aliases of the original node. */
{

View File

@ -1755,7 +1755,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
producing dead clone (for further cloning). In all
other cases we hit a bug (incorrect node sharing is the
most common reason for missing edges). */
gcc_assert (dest->needed || !dest->analyzed
gcc_assert (!dest->analyzed
|| dest->symbol.address_taken
|| !id->src_node->analyzed
|| !id->dst_node->analyzed);

View File

@ -6928,7 +6928,7 @@ ipa_pta_execute (void)
constraints for parameters. */
if (node->symbol.used_from_other_partition
|| node->symbol.externally_visible
|| node->needed)
|| node->symbol.force_output)
{
intra_create_variable_infos ();

View File

@ -2249,7 +2249,7 @@ mark_decl_referenced (tree decl)
struct cgraph_node *node = cgraph_get_create_node (decl);
if (!DECL_EXTERNAL (decl)
&& !node->local.finalized)
cgraph_mark_needed_node (node);
cgraph_mark_force_output_node (node);
}
else if (TREE_CODE (decl) == VAR_DECL)
{
@ -2257,7 +2257,7 @@ mark_decl_referenced (tree decl)
varpool_mark_needed_node (node);
/* C++ frontend use mark_decl_references to force COMDAT variables
to be output that might appear dead otherwise. */
node->force_output = true;
node->symbol.force_output = true;
}
/* else do nothing - we can get various sorts of CST nodes here,
which do not need to be marked. */
@ -5271,13 +5271,20 @@ weak_finish_1 (tree decl)
#endif
}
/* Fiven an assembly name, find the decl it is associated with. */
static tree
find_decl (tree target)
{
symtab_node node = symtab_node_for_asm (target);
if (node)
return node->symbol.decl;
return NULL_TREE;
}
/* This TREE_LIST contains weakref targets. */
static GTY(()) tree weakref_targets;
/* Forward declaration. */
static tree find_decl_and_mark_needed (tree decl, tree target);
/* Emit any pending weak declarations. */
void
@ -5303,7 +5310,7 @@ weak_finish (void)
# if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
# else
tree decl = find_decl_and_mark_needed (alias_decl, target);
tree decl = find_decl (target);
if (! decl)
{
@ -5406,43 +5413,6 @@ globalize_decl (tree decl)
VEC(alias_pair,gc) *alias_pairs;
/* Given an assembly name, find the decl it is associated with. At the
same time, mark it needed for cgraph. */
static tree
find_decl_and_mark_needed (tree decl, tree target)
{
struct cgraph_node *fnode = NULL;
struct varpool_node *vnode = NULL;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
fnode = cgraph_node_for_asm (target);
if (fnode == NULL)
vnode = varpool_node_for_asm (target);
}
else
{
vnode = varpool_node_for_asm (target);
if (vnode == NULL)
fnode = cgraph_node_for_asm (target);
}
if (fnode)
{
cgraph_mark_needed_node (fnode);
return fnode->symbol.decl;
}
else if (vnode)
{
varpool_mark_needed_node (vnode);
vnode->force_output = 1;
return vnode->symbol.decl;
}
else
return NULL_TREE;
}
/* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF
or ASM_OUTPUT_DEF_FROM_DECLS. The function defines the symbol whose
tree node is DECL to have the value of the tree node TARGET. */
@ -5748,7 +5718,7 @@ finish_aliases_1 (void)
{
tree target_decl;
target_decl = find_decl_and_mark_needed (p->decl, p->target);
target_decl = find_decl (p->target);
if (target_decl == NULL)
{
if (symbol_alias_set_contains (defined, p->target))
@ -5854,7 +5824,7 @@ assemble_alias (tree decl, tree target)
/* If the target has already been emitted, we don't have to queue the
alias. This saves a tad of memory. */
if (cgraph_global_info_ready)
target_decl = find_decl_and_mark_needed (decl, target);
target_decl = find_decl (target);
else
target_decl= NULL;
if (target_decl && TREE_ASM_WRITTEN (target_decl))
@ -5960,12 +5930,12 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
TM_GETTMCLONE. If neither of these are true, we didn't generate
a clone, and we didn't call it indirectly... no sense keeping it
in the clone table. */
if (!dst_n || !dst_n->needed)
if (!dst_n || !dst_n->analyzed)
continue;
/* This covers the case where we have optimized the original
function away, and only access the transactional clone. */
if (!src_n || !src_n->needed)
if (!src_n || !src_n->analyzed)
continue;
if (!switched)

View File

@ -214,7 +214,7 @@ bool
decide_is_variable_needed (struct varpool_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
if (node->force_output)
if (node->symbol.force_output)
return true;
gcc_assert (!DECL_EXTERNAL (decl));
@ -298,7 +298,7 @@ varpool_finalize_decl (tree decl)
optimizing and when not doing toplevel reoder. */
|| (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl)
&& !DECL_ARTIFICIAL (node->symbol.decl)))
node->force_output = true;
node->symbol.force_output = true;
if (decide_is_variable_needed (node, decl))
varpool_mark_needed_node (node);
@ -410,6 +410,7 @@ varpool_analyze_pending_decls (void)
}
}
}
varpool_mark_needed_node (tgt);
}
else if (DECL_INITIAL (decl))
record_references_in_initializer (decl, analyzed);
@ -621,8 +622,7 @@ varpool_create_variable_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (alias) == VAR_DECL);
alias_node = varpool_node (alias);
alias_node->alias = 1;
if (!DECL_EXTERNAL (alias))
alias_node->finalized = 1;
alias_node->finalized = 1;
alias_node->alias_of = decl;
if ((!DECL_EXTERNAL (alias)
&& decide_is_variable_needed (alias_node, alias))