cgraph.h (symtab_node_base): Add definition, alias and analyzed flags...

* cgraph.h (symtab_node_base): Add definition, alias and analyzed
	flags; reorder rest of fields in more consistent way.
	(varpool_node): Remove analyzed, finalized and alias.
	(cgraph_ndoe): Likewise.
	(symtab_alias_ultimate_target): New function.
	(cgraph_function_node): Move offline.
	(cgraph_reset_node): Declare.
	(cgraph_comdat_can_be_unshared_p): Remove.
	(varpool_remove_initializer): Declare.
	(varpool_first_defined_variable, varpool_next_defined_variable
	cgraph_first_defined_function, cgraph_next_defined_function): Update.
	(cgraph_function_with_gimple_body_p): Update.
	(varpool_all_refs_explicit_p): Update.
	(symtab_alias_target): New function.
	(cgraph_alias_aliased_node, varpool_alias_aliased_node): Rename to ...
	(cgraph_alias_target, varpool_alias_target): .. this one; simplify.
	(cgraph_function_or_thunk_node): Simplify using symtab_alias_ultimate_target.
	(varpool_variable_node): Likewise.
	* cgraph.c (cgraph_create_function_alias): Update.
	(cgraph_add_thunk): Update.
	(cgraph_remove_node): Update.
	(dump_cgraph_node): Do not dump removed flags.
	(cgraph_function_body_availability): Update.
	(cgraph_propagate_frequency): Update.
	(verify_cgraph_node): Check sanity of local flag.
	(cgraph_function_node): Move here from cgraph.h; revamp for
	cgraph_function_or_thunk_node.
	* lto-symtab.c (lto_varpool_replace_node): Update.
	(lto_symtab_resolve_can_prevail_p): Update.
	(lto_symtab_merge_cgraph_nodes): Update.
	* ipa-cp.c (determine_versionability, initialize_node_lattices,
	propagate_constants_accross_call, devirtualization_time_bonus,
	ipcp_propagate_stage): Update.
	* tree-emutls.c (create_emultls_var, ipa_lower_emutls): Update.
	* ipa-inline-transform.c (clone_inlined_nodes, preserve_function_body_p): Update.
	* ipa-reference.c (propagate): Update.
	(write_node_summary_p): Update.
	* toplev.c (wrapup_global_declaration_2): Update.
	* cgraphunit.c (cgraph_analyze_function): Rename to ...
	(analyze_function) ... this one.
	(cgraph_process_new_functions): Update.
	(cgraph_reset_node): Export.
	(cgraph_finalize_function): Update.
	(cgraph_add_new_function): Update.
	(process_function_and_variable_attributes): Update.
	(varpool_finalize_decl): Update.
	(symbol_finalized): Remove.
	(symbol_finalized_and_needed): Rename to ...
	(symbol_defined_and_needed): ... update.
	(cgraph_analyze_functions): Update.
	(handle_alias_pairs): Update.
	(mark_functions_to_output): Update.
	(assemble_thunk): Update.
	(output_in_order): Update.
	(output_weakrefs): Update.
	(finalize_compilation_unit): Update.
	* lto-cgraph.c (reachable_from_other_partition_p, lto_output_node,
	lto_output_varpool_node, compute_ltrans_boundary, input_overwrite_node,
	input_node, input_varpool_node): Update.
	* dbxout.c (dbxout_expand_expr): Update.
	* cgraphclones.c (cgraph_clone_node): Update.
	(cgraph_copy_node_for_versioning): Update.
	(cgraph_materialize_clone): Update.
	(cgraph_materialize_all_clones): Update.
	* ipa-pure-const.c (analyze_function, pure_const_write_summary,
	propagate_pure_const, propagate_nothrow): Update.
	* lto-streamer-out.c (lto_output, write_symbol): Update.
	* ipa-utils.c (ipa_reverse_postorder): Update.
	* ipa-inline.c (can_inline_edge_p): Update.
	(update_caller_keys, ipa_inline): Update.
	* dwarf2out.c (reference_to_unused,
	premark_types_used_by_global_vars_helper): Update.
	* tree-eh.c (tree_could_trap_p): Update.
	* ipa-split.c (consider_split, execute_split_functions): Update.
	* ipa.c (cgraph_non_local_node_p_1, cgraph_local_node_p,
	 has_addr_references_p): Update;
	move ahead in file for better readability.
	(process_references): Simplify.
	(symtab_remove_unreachable_nodes): Update; cleanup way function/var
	bodies are removed.
	(cgraph_comdat_can_be_unshared_p): Make static.
	(cgraph_externally_visible_p): Update.
	(varpool_externally_visible_p): Update.
	(function_and_variable_visibility): Update.
	* trans-mem.c (get_cg_data, ipa_tm_mayenterirr_function,
	ipa_tm_mark_force_output_node): Update.
	* ipa-inline-analysis.c (dump_inline_summary, initialize_inline_failed,
	estimate_edge_devirt_benefit, inline_generate_summary,
	inline_write_summary): Update.
	* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
	* ipa-prop.c (ipa_compute_jump_functions): Update.
	(ipa_print_node_params, ipa_prop_read_section, ipa_update_after_lto_read,
	read_replacements_section): Update.
	* varasm.c (mark_decl_referenced): Update.
	(assemble_alias, dump_tm_clone_pairs): Update.
	* tree-inline.c (copy_bb): Update.
	(estimate_num_insns, optimize_inline_calls, tree_function_versioning):
	Update.
	* symtab.c (dump_symtab_base): Print new flags.
	(verify_symtab_base): Verify new flags.
	(symtab_alias_ultimate_target): New function.
	* tree-ssa-structalias.c (get_constraint_for_ssa_var,
	create_variable_info_for, associate_varinfo_to_alias, ipa_pta_execute):
	Update.
	* passes.c (ipa_write_summaries, ipa_write_optimization_summaries): Update.
	* i386.c (ix86_get_function_versions_dispatcher,
	ix86_generate_version_dispatcher_body): Update.
	(fold_builtin_cpu): Use varpool_add_new_variable.
	* varpool.c (varpool_remove_initializer): Break out from ...
	(varpool_remove_node): ... this one.
	(dump_varpool_node, varpool_node_for_asm,
	cgraph_variable_initializer_availability, varpool_analyze_node,
	varpool_assemble_decl, varpool_remove_unreferenced_decls,
	varpool_finalize_named_section_flags, varpool_create_variable_alias): Update

	* decl.c (java_mark_decl_local): Update for new symtab flags.

	* tree.c (cp_fix_function_decl_p): Update for new symtab flags.
	* decl2.c )var_finalized_p, cp_write_global_declarations): Likewise.

	* lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab
	flags.
	* lto-partition.c (get_symbol_class, lto_balanced_map): Likewise.

From-SVN: r199422
This commit is contained in:
Jan Hubicka 2013-05-29 22:42:50 +02:00 committed by Jan Hubicka
parent 182802adcc
commit e70670cf4d
40 changed files with 676 additions and 486 deletions

View File

@ -1,3 +1,120 @@
2013-05-29 Jan Hubicka <jh@suse.cz>
* cgraph.h (symtab_node_base): Add definition, alias and analyzed
flags; reorder rest of fields in more consistent way.
(varpool_node): Remove analyzed, finalized and alias.
(cgraph_ndoe): Likewise.
(symtab_alias_ultimate_target): New function.
(cgraph_function_node): Move offline.
(cgraph_reset_node): Declare.
(cgraph_comdat_can_be_unshared_p): Remove.
(varpool_remove_initializer): Declare.
(varpool_first_defined_variable, varpool_next_defined_variable
cgraph_first_defined_function, cgraph_next_defined_function): Update.
(cgraph_function_with_gimple_body_p): Update.
(varpool_all_refs_explicit_p): Update.
(symtab_alias_target): New function.
(cgraph_alias_aliased_node, varpool_alias_aliased_node): Rename to ...
(cgraph_alias_target, varpool_alias_target): .. this one; simplify.
(cgraph_function_or_thunk_node): Simplify using symtab_alias_ultimate_target.
(varpool_variable_node): Likewise.
* cgraph.c (cgraph_create_function_alias): Update.
(cgraph_add_thunk): Update.
(cgraph_remove_node): Update.
(dump_cgraph_node): Do not dump removed flags.
(cgraph_function_body_availability): Update.
(cgraph_propagate_frequency): Update.
(verify_cgraph_node): Check sanity of local flag.
(cgraph_function_node): Move here from cgraph.h; revamp for
cgraph_function_or_thunk_node.
* lto-symtab.c (lto_varpool_replace_node): Update.
(lto_symtab_resolve_can_prevail_p): Update.
(lto_symtab_merge_cgraph_nodes): Update.
* ipa-cp.c (determine_versionability, initialize_node_lattices,
propagate_constants_accross_call, devirtualization_time_bonus,
ipcp_propagate_stage): Update.
* tree-emutls.c (create_emultls_var, ipa_lower_emutls): Update.
* ipa-inline-transform.c (clone_inlined_nodes, preserve_function_body_p): Update.
* ipa-reference.c (propagate): Update.
(write_node_summary_p): Update.
* toplev.c (wrapup_global_declaration_2): Update.
* cgraphunit.c (cgraph_analyze_function): Rename to ...
(analyze_function) ... this one.
(cgraph_process_new_functions): Update.
(cgraph_reset_node): Export.
(cgraph_finalize_function): Update.
(cgraph_add_new_function): Update.
(process_function_and_variable_attributes): Update.
(varpool_finalize_decl): Update.
(symbol_finalized): Remove.
(symbol_finalized_and_needed): Rename to ...
(symbol_defined_and_needed): ... update.
(cgraph_analyze_functions): Update.
(handle_alias_pairs): Update.
(mark_functions_to_output): Update.
(assemble_thunk): Update.
(output_in_order): Update.
(output_weakrefs): Update.
(finalize_compilation_unit): Update.
* lto-cgraph.c (reachable_from_other_partition_p, lto_output_node,
lto_output_varpool_node, compute_ltrans_boundary, input_overwrite_node,
input_node, input_varpool_node): Update.
* dbxout.c (dbxout_expand_expr): Update.
* cgraphclones.c (cgraph_clone_node): Update.
(cgraph_copy_node_for_versioning): Update.
(cgraph_materialize_clone): Update.
(cgraph_materialize_all_clones): Update.
* ipa-pure-const.c (analyze_function, pure_const_write_summary,
propagate_pure_const, propagate_nothrow): Update.
* lto-streamer-out.c (lto_output, write_symbol): Update.
* ipa-utils.c (ipa_reverse_postorder): Update.
* ipa-inline.c (can_inline_edge_p): Update.
(update_caller_keys, ipa_inline): Update.
* dwarf2out.c (reference_to_unused,
premark_types_used_by_global_vars_helper): Update.
* tree-eh.c (tree_could_trap_p): Update.
* ipa-split.c (consider_split, execute_split_functions): Update.
* ipa.c (cgraph_non_local_node_p_1, cgraph_local_node_p,
has_addr_references_p): Update;
move ahead in file for better readability.
(process_references): Simplify.
(symtab_remove_unreachable_nodes): Update; cleanup way function/var
bodies are removed.
(cgraph_comdat_can_be_unshared_p): Make static.
(cgraph_externally_visible_p): Update.
(varpool_externally_visible_p): Update.
(function_and_variable_visibility): Update.
* trans-mem.c (get_cg_data, ipa_tm_mayenterirr_function,
ipa_tm_mark_force_output_node): Update.
* ipa-inline-analysis.c (dump_inline_summary, initialize_inline_failed,
estimate_edge_devirt_benefit, inline_generate_summary,
inline_write_summary): Update.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
* ipa-prop.c (ipa_compute_jump_functions): Update.
(ipa_print_node_params, ipa_prop_read_section, ipa_update_after_lto_read,
read_replacements_section): Update.
* varasm.c (mark_decl_referenced): Update.
(assemble_alias, dump_tm_clone_pairs): Update.
* tree-inline.c (copy_bb): Update.
(estimate_num_insns, optimize_inline_calls, tree_function_versioning):
Update.
* symtab.c (dump_symtab_base): Print new flags.
(verify_symtab_base): Verify new flags.
(symtab_alias_ultimate_target): New function.
* tree-ssa-structalias.c (get_constraint_for_ssa_var,
create_variable_info_for, associate_varinfo_to_alias, ipa_pta_execute):
Update.
* passes.c (ipa_write_summaries, ipa_write_optimization_summaries): Update.
* i386.c (ix86_get_function_versions_dispatcher,
ix86_generate_version_dispatcher_body): Update.
(fold_builtin_cpu): Use varpool_add_new_variable.
* varpool.c (varpool_remove_initializer): Break out from ...
(varpool_remove_node): ... this one.
(dump_varpool_node, varpool_node_for_asm,
cgraph_variable_initializer_availability, varpool_analyze_node,
varpool_assemble_decl, varpool_remove_unreferenced_decls,
varpool_finalize_named_section_flags, varpool_create_variable_alias): Update
2013-05-29 Jan Hubicka <jh@suse.cz> 2013-05-29 Jan Hubicka <jh@suse.cz>
* passes.c (init_optimization_passes): Move OMP expansion into lowering. * passes.c (init_optimization_passes): Move OMP expansion into lowering.

View File

@ -563,10 +563,10 @@ cgraph_create_function_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
alias_node = cgraph_get_create_node (alias); alias_node = cgraph_get_create_node (alias);
gcc_assert (!alias_node->local.finalized); gcc_assert (!alias_node->symbol.definition);
alias_node->thunk.alias = decl; alias_node->thunk.alias = decl;
alias_node->local.finalized = true; alias_node->symbol.definition = true;
alias_node->alias = 1; alias_node->symbol.alias = true;
return alias_node; return alias_node;
} }
@ -613,8 +613,8 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
node = cgraph_get_node (alias); node = cgraph_get_node (alias);
if (node) if (node)
{ {
gcc_assert (node->local.finalized); gcc_assert (node->symbol.definition);
gcc_assert (!node->alias); gcc_assert (!node->symbol.alias);
gcc_assert (!node->thunk.thunk_p); gcc_assert (!node->thunk.thunk_p);
cgraph_remove_node (node); cgraph_remove_node (node);
} }
@ -629,7 +629,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED,
node->thunk.virtual_offset_p = virtual_offset != NULL; node->thunk.virtual_offset_p = virtual_offset != NULL;
node->thunk.alias = real_alias; node->thunk.alias = real_alias;
node->thunk.thunk_p = true; node->thunk.thunk_p = true;
node->local.finalized = true; node->symbol.definition = true;
return node; return node;
} }
@ -1384,7 +1384,7 @@ cgraph_remove_node (struct cgraph_node *node)
&& (cgraph_global_info_ready && (cgraph_global_info_ready
&& (TREE_ASM_WRITTEN (n->symbol.decl) && (TREE_ASM_WRITTEN (n->symbol.decl)
|| DECL_EXTERNAL (n->symbol.decl) || DECL_EXTERNAL (n->symbol.decl)
|| !n->analyzed || !n->symbol.analyzed
|| n->symbol.in_other_partition)))) || n->symbol.in_other_partition))))
cgraph_release_function_body (node); cgraph_release_function_body (node);
@ -1521,8 +1521,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
cgraph_availability_names [cgraph_function_body_availability (node)]); cgraph_availability_names [cgraph_function_body_availability (node)]);
fprintf (f, " Function flags:"); fprintf (f, " Function flags:");
if (node->analyzed)
fprintf (f, " analyzed");
if (node->count) if (node->count)
fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x", fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
(HOST_WIDEST_INT)node->count); (HOST_WIDEST_INT)node->count);
@ -1534,16 +1532,12 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " process"); fprintf (f, " process");
if (node->local.local) if (node->local.local)
fprintf (f, " local"); fprintf (f, " local");
if (node->local.finalized)
fprintf (f, " finalized");
if (node->local.redefined_extern_inline) if (node->local.redefined_extern_inline)
fprintf (f, " redefined_extern_inline"); fprintf (f, " redefined_extern_inline");
if (node->only_called_at_startup) if (node->only_called_at_startup)
fprintf (f, " only_called_at_startup"); fprintf (f, " only_called_at_startup");
if (node->only_called_at_exit) if (node->only_called_at_exit)
fprintf (f, " only_called_at_exit"); fprintf (f, " only_called_at_exit");
else if (node->alias)
fprintf (f, " alias");
if (node->tm_clone) if (node->tm_clone)
fprintf (f, " tm_clone"); fprintf (f, " tm_clone");
@ -1559,7 +1553,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
(int)node->thunk.virtual_value, (int)node->thunk.virtual_value,
(int)node->thunk.virtual_offset_p); (int)node->thunk.virtual_offset_p);
} }
if (node->alias && node->thunk.alias && DECL_P (node->thunk.alias)) if (node->symbol.alias && node->thunk.alias
&& DECL_P (node->thunk.alias))
{ {
fprintf (f, " Alias of %s", fprintf (f, " Alias of %s",
lang_hooks.decl_printable_name (node->thunk.alias, 2)); lang_hooks.decl_printable_name (node->thunk.alias, 2));
@ -1676,7 +1671,7 @@ cgraph_function_body_availability (struct cgraph_node *node)
{ {
enum availability avail; enum availability avail;
gcc_assert (cgraph_function_flags_ready); gcc_assert (cgraph_function_flags_ready);
if (!node->analyzed) if (!node->symbol.analyzed)
avail = AVAIL_NOT_AVAILABLE; avail = AVAIL_NOT_AVAILABLE;
else if (node->local.local) else if (node->local.local)
avail = AVAIL_LOCAL; avail = AVAIL_LOCAL;
@ -1983,7 +1978,7 @@ cgraph_propagate_frequency (struct cgraph_node *node)
if (!node->local.local) if (!node->local.local)
return false; return false;
gcc_assert (node->analyzed); gcc_assert (node->symbol.analyzed);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
@ -2342,6 +2337,11 @@ verify_cgraph_node (struct cgraph_node *node)
error ("inline clone in same comdat group list"); error ("inline clone in same comdat group list");
error_found = true; error_found = true;
} }
if (!node->symbol.definition && node->local.local)
{
error ("local symbols must be defined");
error_found = true;
}
if (node->global.inlined_to && node->symbol.externally_visible) if (node->global.inlined_to && node->symbol.externally_visible)
{ {
error ("externally visible inline clone"); error ("externally visible inline clone");
@ -2455,7 +2455,7 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true; error_found = true;
} }
if (node->analyzed && node->alias) if (node->symbol.analyzed && node->symbol.alias)
{ {
bool ref_found = false; bool ref_found = false;
int i; int i;
@ -2486,7 +2486,7 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true; error_found = true;
} }
} }
if (node->analyzed && node->thunk.thunk_p) if (node->symbol.analyzed && node->thunk.thunk_p)
{ {
if (!node->callees) if (!node->callees)
{ {
@ -2504,7 +2504,7 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true; error_found = true;
} }
} }
else if (node->analyzed && gimple_has_body_p (node->symbol.decl) else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl)
&& !TREE_ASM_WRITTEN (node->symbol.decl) && !TREE_ASM_WRITTEN (node->symbol.decl)
&& (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to) && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
&& !flag_wpa) && !flag_wpa)
@ -2653,4 +2653,32 @@ cgraph_get_create_real_symbol_node (tree decl)
node->symbol.order); node->symbol.order);
return node; return node;
} }
/* Given NODE, walk the alias chain to return the function NODE is alias of.
Walk through thunk, too.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
struct cgraph_node *
cgraph_function_node (struct cgraph_node *node, enum availability *availability)
{
do
{
node = cgraph_function_or_thunk_node (node, availability);
if (node->thunk.thunk_p)
{
node = node->callees->callee;
if (availability)
{
enum availability a;
a = cgraph_function_body_availability (node);
if (a < *availability)
*availability = a;
}
node = cgraph_function_or_thunk_node (node, availability);
}
} while (node && node->thunk.thunk_p);
return node;
}
#include "gt-cgraph.h" #include "gt-cgraph.h"

View File

@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-ref.h" #include "ipa-ref.h"
/* Symbol table consists of functions and variables. /* Symbol table consists of functions and variables.
TODO: add labels, constant pool and aliases. */ TODO: add labels and CONST_DECLs. */
enum symtab_type enum symtab_type
{ {
SYMTAB_SYMBOL, SYMTAB_SYMBOL,
@ -48,15 +48,21 @@ struct GTY(()) symtab_node_base
/* The symbols resolution. */ /* The symbols resolution. */
ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8; ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
/* Set when function has address taken. /*** Flags representing the symbol type. ***/
In current implementation it imply needed flag. */
unsigned address_taken : 1; /* True when symbol corresponds to a definition in current unit.
/* Set when variable is used from other LTRANS partition. */ set via cgraph_finalize_function or varpool_finalize_decl */
unsigned used_from_other_partition : 1; unsigned definition : 1;
/* Set when function is available in the other LTRANS partition. /* True when symbol is an alias.
During WPA output it is used to mark nodes that are present in Set by assemble_alias. */
multiple partitions. */ unsigned alias : 1;
unsigned in_other_partition : 1; /* Set once the definition was analyzed. The list of references and
other properties are built during analysis. */
unsigned analyzed : 1;
/*** Visibility and linkage flags. ***/
/* Set when function is visible by other units. */ /* Set when function is visible by other units. */
unsigned externally_visible : 1; unsigned externally_visible : 1;
/* Needed variables might become dead by optimization. This flag /* Needed variables might become dead by optimization. This flag
@ -65,30 +71,57 @@ struct GTY(()) symtab_node_base
/* True when the name is known to be unique and thus it does not need mangling. */ /* True when the name is known to be unique and thus it does not need mangling. */
unsigned unique_name : 1; unsigned unique_name : 1;
/*** WHOPR Partitioning flags.
These flags are used at ltrans stage when only part of the callgraph is
available. ***/
/* Set when variable is used from other LTRANS partition. */
unsigned used_from_other_partition : 1;
/* Set when function is available in the other LTRANS partition.
During WPA output it is used to mark nodes that are present in
multiple partitions. */
unsigned in_other_partition : 1;
/*** other flags. ***/
/* Set when symbol has address taken. */
unsigned address_taken : 1;
/* Ordering of all symtab entries. */ /* Ordering of all symtab entries. */
int order; int order;
/* Declaration representing the symbol. */
tree decl; tree decl;
/* Vectors of referring and referenced entities. */
struct ipa_ref_list ref_list;
/* Circular list of nodes in the same comdat group if non-NULL. */
symtab_node same_comdat_group;
/* File stream where this node is being written to. */
struct lto_file_decl_data * lto_file_data;
/* Linked list of symbol table entries starting with symtab_nodes. */ /* Linked list of symbol table entries starting with symtab_nodes. */
symtab_node next; symtab_node next;
symtab_node previous; symtab_node previous;
/* Linked list of symbols with the same asm name. There may be multiple /* Linked list of symbols with the same asm name. There may be multiple
entries for single symbol name in the case of LTO resolutions, entries for single symbol name during LTO, because symbols are renamed
existence of inline clones, or duplicated declaration. The last case only after partitioning.
is a long standing bug frontends and builtin handling. */
Because inline clones are kept in the assembler name has, they also produce
duplicate entries.
There are also several long standing bugs where frontends and builtin
code produce duplicated decls. */
symtab_node next_sharing_asm_name; symtab_node next_sharing_asm_name;
symtab_node previous_sharing_asm_name; symtab_node previous_sharing_asm_name;
/* Circular list of nodes in the same comdat group if non-NULL. */
symtab_node same_comdat_group;
/* Vectors of referring and referenced entities. */
struct ipa_ref_list ref_list;
/* File stream where this node is being written to. */
struct lto_file_decl_data * lto_file_data;
PTR GTY ((skip)) aux; PTR GTY ((skip)) aux;
}; };
@ -142,9 +175,6 @@ struct GTY(()) cgraph_local_info {
and its address is never taken. */ and its address is never taken. */
unsigned local : 1; unsigned local : 1;
/* Set once it has been finalized so we consider it to be output. */
unsigned finalized : 1;
/* False when there is something makes versioning impossible. */ /* False when there is something makes versioning impossible. */
unsigned versionable : 1; unsigned versionable : 1;
@ -260,11 +290,7 @@ struct GTY(()) cgraph_node {
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
lists created. */ lists created. */
unsigned analyzed : 1;
/* Set when function is scheduled to be processed by local passes. */
unsigned process : 1; unsigned process : 1;
/* Set for aliases once they got through assemble_alias. */
unsigned alias : 1;
/* Set for aliases created as C++ same body aliases. */ /* Set for aliases created as C++ same body aliases. */
unsigned same_body_alias : 1; unsigned same_body_alias : 1;
/* How commonly executed the node is. Initialized during branch /* How commonly executed the node is. Initialized during branch
@ -455,16 +481,8 @@ 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 once the variable has been instantiated and its callee
lists created. */
unsigned analyzed : 1;
/* Set once it has been finalized so we consider it to be output. */
unsigned finalized : 1;
/* Set when variable is scheduled to be assembled. */ /* Set when variable is scheduled to be assembled. */
unsigned output : 1; unsigned output : 1;
/* Set for aliases once they got through assemble_alias. Also set for
extra name aliases in varpool_extra_name_alias. */
unsigned alias : 1;
unsigned extra_name_alias : 1; unsigned extra_name_alias : 1;
}; };
@ -558,6 +576,7 @@ void verify_symtab_node (symtab_node);
bool verify_symtab_base (symtab_node); bool verify_symtab_base (symtab_node);
bool symtab_used_from_object_file_p (symtab_node); bool symtab_used_from_object_file_p (symtab_node);
void symtab_make_decl_local (tree); void symtab_make_decl_local (tree);
symtab_node symtab_alias_ultimate_target (symtab_node, enum availability *);
/* In cgraph.c */ /* In cgraph.c */
void dump_cgraph (FILE *); void dump_cgraph (FILE *);
@ -653,6 +672,7 @@ struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_ho
void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *); void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *); gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
bool cgraph_propagate_frequency (struct cgraph_node *node); bool cgraph_propagate_frequency (struct cgraph_node *node);
struct cgraph_node * cgraph_function_node (struct cgraph_node *, enum availability *);
/* In cgraphunit.c */ /* In cgraphunit.c */
struct asm_node *add_asm_node (tree); struct asm_node *add_asm_node (tree);
@ -663,10 +683,11 @@ void compile (void);
void init_cgraph (void); void init_cgraph (void);
bool cgraph_process_new_functions (void); bool cgraph_process_new_functions (void);
void cgraph_process_same_body_aliases (void); void cgraph_process_same_body_aliases (void);
void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias); void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree);
/* Initialize datastructures so DECL is a function in lowered gimple form. /* Initialize datastructures so DECL is a function in lowered gimple form.
IN_SSA is true if the gimple is in SSA. */ IN_SSA is true if the gimple is in SSA. */
basic_block init_lowered_empty_function (tree decl, bool in_ssa); basic_block init_lowered_empty_function (tree, bool);
void cgraph_reset_node (struct cgraph_node *);
/* In cgraphclones.c */ /* In cgraphclones.c */
@ -728,7 +749,6 @@ void dump_varpool_node_set (FILE *, varpool_node_set);
void debug_varpool_node_set (varpool_node_set); void debug_varpool_node_set (varpool_node_set);
void free_varpool_node_set (varpool_node_set); void free_varpool_node_set (varpool_node_set);
void ipa_discover_readonly_nonaddressable_vars (void); void ipa_discover_readonly_nonaddressable_vars (void);
bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *);
bool varpool_externally_visible_p (struct varpool_node *); bool varpool_externally_visible_p (struct varpool_node *);
/* In predict.c */ /* In predict.c */
@ -765,6 +785,7 @@ bool varpool_for_node_and_aliases (struct varpool_node *,
void varpool_add_new_variable (tree); void varpool_add_new_variable (tree);
void symtab_initialize_asm_name_hash (void); void symtab_initialize_asm_name_hash (void);
void symtab_prevail_in_asm_name_hash (symtab_node node); void symtab_prevail_in_asm_name_hash (symtab_node node);
void varpool_remove_initializer (struct varpool_node *);
/* Return callgraph node for given symbol and check it is a function. */ /* Return callgraph node for given symbol and check it is a function. */
@ -900,7 +921,7 @@ varpool_first_defined_variable (void)
for (node = symtab_nodes; node; node = node->symbol.next) for (node = symtab_nodes; node; node = node->symbol.next)
{ {
varpool_node *vnode = dyn_cast <varpool_node> (node); varpool_node *vnode = dyn_cast <varpool_node> (node);
if (vnode && vnode->analyzed) if (vnode && vnode->symbol.definition)
return vnode; return vnode;
} }
return NULL; return NULL;
@ -914,7 +935,7 @@ varpool_next_defined_variable (struct varpool_node *node)
for (; node1; node1 = node1->symbol.next) for (; node1; node1 = node1->symbol.next)
{ {
varpool_node *vnode1 = dyn_cast <varpool_node> (node1); varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
if (vnode1 && vnode1->analyzed) if (vnode1 && vnode1->symbol.definition)
return vnode1; return vnode1;
} }
return NULL; return NULL;
@ -932,7 +953,7 @@ cgraph_first_defined_function (void)
for (node = symtab_nodes; node; node = node->symbol.next) for (node = symtab_nodes; node; node = node->symbol.next)
{ {
cgraph_node *cn = dyn_cast <cgraph_node> (node); cgraph_node *cn = dyn_cast <cgraph_node> (node);
if (cn && cn->analyzed) if (cn && cn->symbol.definition)
return cn; return cn;
} }
return NULL; return NULL;
@ -946,7 +967,7 @@ cgraph_next_defined_function (struct cgraph_node *node)
for (; node1; node1 = node1->symbol.next) for (; node1; node1 = node1->symbol.next)
{ {
cgraph_node *cn1 = dyn_cast <cgraph_node> (node1); cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
if (cn1 && cn1->analyzed) if (cn1 && cn1->symbol.definition)
return cn1; return cn1;
} }
return NULL; return NULL;
@ -992,7 +1013,7 @@ cgraph_next_function (struct cgraph_node *node)
static inline bool static inline bool
cgraph_function_with_gimple_body_p (struct cgraph_node *node) cgraph_function_with_gimple_body_p (struct cgraph_node *node)
{ {
return node->analyzed && !node->thunk.thunk_p && !node->alias; return node->symbol.definition && !node->thunk.thunk_p && !node->symbol.alias;
} }
/* Return first function with body defined. */ /* Return first function with body defined. */
@ -1197,7 +1218,7 @@ varpool_can_remove_if_no_refs (struct varpool_node *node)
static inline bool static inline bool
varpool_all_refs_explicit_p (struct varpool_node *vnode) varpool_all_refs_explicit_p (struct varpool_node *vnode)
{ {
return (vnode->analyzed return (vnode->symbol.definition
&& !vnode->symbol.externally_visible && !vnode->symbol.externally_visible
&& !vnode->symbol.used_from_other_partition && !vnode->symbol.used_from_other_partition
&& !vnode->symbol.force_output); && !vnode->symbol.force_output);
@ -1211,60 +1232,25 @@ htab_t constant_pool_htab (void);
/* Return node that alias N is aliasing. */ /* Return node that alias N is aliasing. */
static inline struct cgraph_node * static inline symtab_node
cgraph_alias_aliased_node (struct cgraph_node *n) symtab_alias_target (symtab_node n)
{ {
struct ipa_ref *ref; struct ipa_ref *ref;
ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref); ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
gcc_checking_assert (ref->use == IPA_REF_ALIAS); gcc_checking_assert (ref->use == IPA_REF_ALIAS);
if (is_a <cgraph_node> (ref->referred)) return ref->referred;
return ipa_ref_node (ref);
return NULL;
} }
/* Return node that alias N is aliasing. */ static inline struct cgraph_node *
cgraph_alias_target (struct cgraph_node *n)
{
return dyn_cast <cgraph_node> (symtab_alias_target ((symtab_node) n));
}
static inline struct varpool_node * static inline struct varpool_node *
varpool_alias_aliased_node (struct varpool_node *n) varpool_alias_target (struct varpool_node *n)
{ {
struct ipa_ref *ref; return dyn_cast <varpool_node> (symtab_alias_target ((symtab_node) n));
ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
gcc_checking_assert (ref->use == IPA_REF_ALIAS);
if (is_a <varpool_node> (ref->referred))
return ipa_ref_varpool_node (ref);
return NULL;
}
/* Given NODE, walk the alias chain to return the function NODE is alias of.
Walk through thunk, too.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
static inline struct cgraph_node *
cgraph_function_node (struct cgraph_node *node, enum availability *availability)
{
if (availability)
*availability = cgraph_function_body_availability (node);
while (node)
{
if (node->alias && node->analyzed)
node = cgraph_alias_aliased_node (node);
else if (node->thunk.thunk_p)
node = node->callees->callee;
else
return node;
if (node && availability)
{
enum availability a;
a = cgraph_function_body_availability (node);
if (a < *availability)
*availability = a;
}
}
if (availability)
*availability = AVAIL_NOT_AVAILABLE;
return NULL;
} }
/* Given NODE, walk the alias chain to return the function NODE is alias of. /* Given NODE, walk the alias chain to return the function NODE is alias of.
@ -1274,27 +1260,13 @@ cgraph_function_node (struct cgraph_node *node, enum availability *availability)
static inline struct cgraph_node * static inline struct cgraph_node *
cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability) cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
{ {
if (availability) struct cgraph_node *n;
*availability = cgraph_function_body_availability (node);
while (node)
{
if (node->alias && node->analyzed)
node = cgraph_alias_aliased_node (node);
else
return node;
if (node && availability)
{
enum availability a;
a = cgraph_function_body_availability (node);
if (a < *availability)
*availability = a;
}
}
if (availability)
*availability = AVAIL_NOT_AVAILABLE;
return NULL;
}
n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
if (!n)
*availability = AVAIL_NOT_AVAILABLE;
return n;
}
/* Given NODE, walk the alias chain to return the function NODE is alias of. /* Given NODE, walk the alias chain to return the function NODE is alias of.
Do not walk through thunks. Do not walk through thunks.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */ When AVAILABILITY is non-NULL, get minimal availability in the chain. */
@ -1302,25 +1274,12 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *avai
static inline struct varpool_node * static inline struct varpool_node *
varpool_variable_node (struct varpool_node *node, enum availability *availability) varpool_variable_node (struct varpool_node *node, enum availability *availability)
{ {
if (availability) struct varpool_node *n;
*availability = cgraph_variable_initializer_availability (node);
while (node) n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
{ if (!n)
if (node->alias && node->analyzed)
node = varpool_alias_aliased_node (node);
else
return node;
if (node && availability)
{
enum availability a;
a = cgraph_variable_initializer_availability (node);
if (a < *availability)
*availability = a;
}
}
if (availability)
*availability = AVAIL_NOT_AVAILABLE; *availability = AVAIL_NOT_AVAILABLE;
return NULL; return n;
} }
/* Return true when the edge E represents a direct recursion. */ /* Return true when the edge E represents a direct recursion. */
@ -1355,7 +1314,7 @@ cgraph_mark_force_output_node (struct cgraph_node *node)
} }
/* Return true when the symbol is real symbol, i.e. it is not inline clone /* Return true when the symbol is real symbol, i.e. it is not inline clone
or extern function kept around just for inlining. */ or abstract function kept for debug info purposes only. */
static inline bool static inline bool
symtab_real_symbol_p (symtab_node node) symtab_real_symbol_p (symtab_node node)

View File

@ -189,7 +189,8 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
new_node->next_nested = new_node->origin->nested; new_node->next_nested = new_node->origin->nested;
new_node->origin->nested = new_node; new_node->origin->nested = new_node;
} }
new_node->analyzed = n->analyzed; new_node->symbol.analyzed = n->symbol.analyzed;
new_node->symbol.definition = n->symbol.definition;
new_node->local = n->local; new_node->local = n->local;
new_node->symbol.externally_visible = false; new_node->symbol.externally_visible = false;
new_node->local.local = true; new_node->local.local = true;
@ -638,10 +639,11 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
new_version = cgraph_create_node (new_decl); new_version = cgraph_create_node (new_decl);
new_version->analyzed = old_version->analyzed; new_version->symbol.analyzed = old_version->symbol.analyzed;
new_version->symbol.definition = old_version->symbol.definition;
new_version->local = old_version->local; new_version->local = old_version->local;
new_version->symbol.externally_visible = false; new_version->symbol.externally_visible = false;
new_version->local.local = old_version->analyzed; new_version->local.local = new_version->symbol.definition;
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->count = old_version->count; new_version->count = old_version->count;
@ -791,7 +793,7 @@ cgraph_materialize_clone (struct cgraph_node *node)
node->clone_of->clones = node->next_sibling_clone; node->clone_of->clones = node->next_sibling_clone;
node->next_sibling_clone = NULL; node->next_sibling_clone = NULL;
node->prev_sibling_clone = NULL; node->prev_sibling_clone = NULL;
if (!node->clone_of->analyzed && !node->clone_of->clones) if (!node->clone_of->symbol.analyzed && !node->clone_of->clones)
{ {
cgraph_release_function_body (node->clone_of); cgraph_release_function_body (node->clone_of);
cgraph_node_remove_callees (node->clone_of); cgraph_node_remove_callees (node->clone_of);
@ -874,7 +876,7 @@ cgraph_materialize_all_clones (void)
} }
} }
FOR_EACH_FUNCTION (node) FOR_EACH_FUNCTION (node)
if (!node->analyzed && node->callees) if (!node->symbol.analyzed && node->callees)
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
if (cgraph_dump_file) if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Materialization Call site updates done.\n"); fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");

View File

@ -202,7 +202,7 @@ cgraph_node_set cgraph_new_nodes;
static void expand_all_functions (void); static void expand_all_functions (void);
static void mark_functions_to_output (void); static void mark_functions_to_output (void);
static void expand_function (struct cgraph_node *); static void expand_function (struct cgraph_node *);
static void cgraph_analyze_function (struct cgraph_node *); static void analyze_function (struct cgraph_node *);
static void handle_alias_pairs (void); static void handle_alias_pairs (void);
FILE *cgraph_dump_file; FILE *cgraph_dump_file;
@ -309,8 +309,8 @@ cgraph_process_new_functions (void)
cgraph but not on this function. */ cgraph but not on this function. */
gimple_register_cfg_hooks (); gimple_register_cfg_hooks ();
if (!node->analyzed) if (!node->symbol.analyzed)
cgraph_analyze_function (node); analyze_function (node);
push_cfun (DECL_STRUCT_FUNCTION (fndecl)); push_cfun (DECL_STRUCT_FUNCTION (fndecl));
if ((cgraph_state == CGRAPH_STATE_IPA_SSA if ((cgraph_state == CGRAPH_STATE_IPA_SSA
&& !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
@ -354,7 +354,7 @@ cgraph_process_new_functions (void)
??? It may make more sense to use one body for inlining and other ??? It may make more sense to use one body for inlining and other
body for expanding the function but this is difficult to do. */ body for expanding the function but this is difficult to do. */
static void void
cgraph_reset_node (struct cgraph_node *node) cgraph_reset_node (struct cgraph_node *node)
{ {
/* If node->process is set, then we have already begun whole-unit analysis. /* If node->process is set, then we have already begun whole-unit analysis.
@ -368,10 +368,11 @@ cgraph_reset_node (struct cgraph_node *node)
memset (&node->local, 0, sizeof (node->local)); memset (&node->local, 0, sizeof (node->local));
memset (&node->global, 0, sizeof (node->global)); memset (&node->global, 0, sizeof (node->global));
memset (&node->rtl, 0, sizeof (node->rtl)); memset (&node->rtl, 0, sizeof (node->rtl));
node->analyzed = false; node->symbol.analyzed = false;
node->local.finalized = false; node->symbol.definition = false;
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->symbol.ref_list);
} }
/* Return true when there are references to NODE. */ /* Return true when there are references to NODE. */
@ -401,14 +402,14 @@ cgraph_finalize_function (tree decl, bool nested)
{ {
struct cgraph_node *node = cgraph_get_create_node (decl); struct cgraph_node *node = cgraph_get_create_node (decl);
if (node->local.finalized) if (node->symbol.definition)
{ {
cgraph_reset_node (node); cgraph_reset_node (node);
node->local.redefined_extern_inline = true; node->local.redefined_extern_inline = true;
} }
notice_global_symbol (decl); notice_global_symbol (decl);
node->local.finalized = true; node->symbol.definition = true;
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
/* With -fkeep-inline-functions we are keeping all inline functions except /* With -fkeep-inline-functions we are keeping all inline functions except
@ -488,7 +489,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
analyzing and compilation. */ analyzing and compilation. */
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->symbol.definition = true;
node->symbol.force_output = true; node->symbol.force_output = true;
if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION) if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
{ {
@ -515,7 +516,8 @@ cgraph_add_new_function (tree fndecl, bool lowered)
node = cgraph_create_node (fndecl); node = cgraph_create_node (fndecl);
if (lowered) if (lowered)
node->lowered = true; node->lowered = true;
cgraph_analyze_function (node); node->symbol.definition = true;
analyze_function (node);
push_cfun (DECL_STRUCT_FUNCTION (fndecl)); push_cfun (DECL_STRUCT_FUNCTION (fndecl));
gimple_register_cfg_hooks (); gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL); bitmap_obstack_initialize (NULL);
@ -589,23 +591,23 @@ fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alia
/* Analyze the function scheduled to be output. */ /* Analyze the function scheduled to be output. */
static void static void
cgraph_analyze_function (struct cgraph_node *node) analyze_function (struct cgraph_node *node)
{ {
tree decl = node->symbol.decl; tree decl = node->symbol.decl;
location_t saved_loc = input_location; location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl); input_location = DECL_SOURCE_LOCATION (decl);
if (node->alias && node->thunk.alias) if (node->symbol.alias && node->thunk.alias)
{ {
struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias); struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
struct cgraph_node *n; struct cgraph_node *n;
for (n = tgt; n && n->alias; for (n = tgt; n && n->symbol.alias;
n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL) n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
if (n == node) if (n == node)
{ {
error ("function %q+D part of alias cycle", node->symbol.decl); error ("function %q+D part of alias cycle", node->symbol.decl);
node->alias = false; node->symbol.alias = false;
input_location = saved_loc; input_location = saved_loc;
return; return;
} }
@ -622,7 +624,7 @@ cgraph_analyze_function (struct cgraph_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_target (node));
} }
else if (node->thunk.thunk_p) else if (node->thunk.thunk_p)
{ {
@ -677,7 +679,7 @@ cgraph_analyze_function (struct cgraph_node *node)
pop_cfun (); pop_cfun ();
} }
node->analyzed = true; node->symbol.analyzed = true;
input_location = saved_loc; input_location = saved_loc;
} }
@ -766,7 +768,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
" attribute have effect only on public objects"); " attribute have effect only on public objects");
} }
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
&& (node->local.finalized && !node->alias)) && (node->symbol.definition && !node->symbol.alias))
{ {
warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes, warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
"%<weakref%> attribute ignored" "%<weakref%> attribute ignored"
@ -803,7 +805,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
" attribute have effect only on public objects"); " attribute have effect only on public objects");
} }
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
&& vnode->finalized && vnode->symbol.definition
&& DECL_INITIAL (decl)) && DECL_INITIAL (decl))
{ {
warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes, warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
@ -828,10 +830,10 @@ varpool_finalize_decl (tree decl)
gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
if (node->finalized) if (node->symbol.definition)
return; return;
notice_global_symbol (decl); notice_global_symbol (decl);
node->finalized = true; node->symbol.definition = true;
if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
/* Traditionally we do not eliminate static variables when not /* Traditionally we do not eliminate static variables when not
optimizing and when not doing toplevel reoder. */ optimizing and when not doing toplevel reoder. */
@ -855,36 +857,23 @@ varpool_finalize_decl (tree decl)
/* Determine if a symbol NODE is finalized and needed. */ /* Determine if a symbol NODE is finalized and needed. */
inline static bool inline static bool
symbol_finalized_and_needed (symtab_node node) symbol_defined_and_needed (symtab_node node)
{ {
if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
return cnode->local.finalized return cnode->symbol.definition
&& cgraph_decide_is_function_needed (cnode, cnode->symbol.decl); && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
if (varpool_node *vnode = dyn_cast <varpool_node> (node)) if (varpool_node *vnode = dyn_cast <varpool_node> (node))
return vnode->finalized return vnode->symbol.definition
&& !DECL_EXTERNAL (vnode->symbol.decl) && !DECL_EXTERNAL (vnode->symbol.decl)
&& decide_is_variable_needed (vnode, vnode->symbol.decl); && decide_is_variable_needed (vnode, vnode->symbol.decl);
return false; return false;
} }
/* Determine if a symbol NODE is finalized. */
inline static bool
symbol_finalized (symtab_node node)
{
if (cgraph_node *cnode= dyn_cast <cgraph_node> (node))
return cnode->local.finalized;
if (varpool_node *vnode = dyn_cast <varpool_node> (node))
return vnode->finalized;
return false;
}
/* Discover all functions and variables that are trivially needed, analyze /* Discover all functions and variables that are trivially needed, analyze
them as well as all functions and variables referred by them */ them as well as all functions and variables referred by them */
static void static void
cgraph_analyze_functions (void) analyze_functions (void)
{ {
/* Keep track of already processed nodes when called multiple times for /* Keep track of already processed nodes when called multiple times for
intermodule optimization. */ intermodule optimization. */
@ -914,7 +903,7 @@ cgraph_analyze_functions (void)
node != (symtab_node)first_analyzed node != (symtab_node)first_analyzed
&& node != (symtab_node)first_analyzed_var; node = node->symbol.next) && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
{ {
if (symbol_finalized_and_needed (node)) if (symbol_defined_and_needed (node))
{ {
enqueue_node (node); enqueue_node (node);
if (!changed && cgraph_dump_file) if (!changed && cgraph_dump_file)
@ -942,7 +931,7 @@ cgraph_analyze_functions (void)
node = first; node = first;
first = (symtab_node)first->symbol.aux; first = (symtab_node)first->symbol.aux;
cgraph_node *cnode = dyn_cast <cgraph_node> (node); cgraph_node *cnode = dyn_cast <cgraph_node> (node);
if (cnode && cnode->local.finalized) if (cnode && cnode->symbol.definition)
{ {
struct cgraph_edge *edge; struct cgraph_edge *edge;
tree decl = cnode->symbol.decl; tree decl = cnode->symbol.decl;
@ -951,7 +940,7 @@ cgraph_analyze_functions (void)
and later using weak alias attribute to kill its body. and later using weak alias attribute to kill its body.
See gcc.c-torture/compile/20011119-1.c */ See gcc.c-torture/compile/20011119-1.c */
if (!DECL_STRUCT_FUNCTION (decl) if (!DECL_STRUCT_FUNCTION (decl)
&& (!cnode->alias || !cnode->thunk.alias) && (!cnode->symbol.alias || !cnode->thunk.alias)
&& !cnode->thunk.thunk_p && !cnode->thunk.thunk_p
&& !cnode->dispatcher_function) && !cnode->dispatcher_function)
{ {
@ -960,11 +949,11 @@ cgraph_analyze_functions (void)
continue; continue;
} }
if (!cnode->analyzed) if (!cnode->symbol.analyzed)
cgraph_analyze_function (cnode); 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) if (edge->callee->symbol.definition)
enqueue_node ((symtab_node)edge->callee); enqueue_node ((symtab_node)edge->callee);
/* If decl is a clone of an abstract function, /* If decl is a clone of an abstract function,
@ -981,7 +970,7 @@ cgraph_analyze_functions (void)
else else
{ {
varpool_node *vnode = dyn_cast <varpool_node> (node); varpool_node *vnode = dyn_cast <varpool_node> (node);
if (vnode && vnode->finalized) if (vnode && vnode->symbol.definition)
varpool_analyze_node (vnode); varpool_analyze_node (vnode);
} }
@ -994,7 +983,7 @@ cgraph_analyze_functions (void)
enqueue_node (next); enqueue_node (next);
} }
for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
if (symbol_finalized (ref->referred)) if (ref->referred->symbol.definition)
enqueue_node (ref->referred); enqueue_node (ref->referred);
cgraph_process_new_functions (); cgraph_process_new_functions ();
} }
@ -1026,15 +1015,15 @@ cgraph_analyze_functions (void)
{ {
tree decl = node->symbol.decl; tree decl = node->symbol.decl;
if (cnode->local.finalized && !gimple_has_body_p (decl) if (cnode->symbol.definition && !gimple_has_body_p (decl)
&& (!cnode->alias || !cnode->thunk.alias) && (!cnode->symbol.alias || !cnode->thunk.alias)
&& !cnode->thunk.thunk_p) && !cnode->thunk.thunk_p)
cgraph_reset_node (cnode); cgraph_reset_node (cnode);
gcc_assert (!cnode->local.finalized || cnode->thunk.thunk_p gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p
|| cnode->alias || cnode->symbol.alias
|| gimple_has_body_p (decl)); || gimple_has_body_p (decl));
gcc_assert (cnode->analyzed == cnode->local.finalized); gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition);
} }
node->symbol.aux = NULL; node->symbol.aux = NULL;
} }
@ -1071,13 +1060,13 @@ handle_alias_pairs (void)
if (TREE_CODE (p->decl) == FUNCTION_DECL) if (TREE_CODE (p->decl) == FUNCTION_DECL)
{ {
struct cgraph_node *anode = cgraph_get_create_node (p->decl); struct cgraph_node *anode = cgraph_get_create_node (p->decl);
anode->alias = true; anode->symbol.alias = true;
anode->thunk.alias = p->target; anode->thunk.alias = p->target;
} }
else else
{ {
struct varpool_node *anode = varpool_get_node (p->decl); struct varpool_node *anode = varpool_get_node (p->decl);
anode->alias = true; anode->symbol.alias = true;
anode->alias_of = p->target; anode->alias_of = p->target;
} }
DECL_EXTERNAL (p->decl) = 1; DECL_EXTERNAL (p->decl) = 1;
@ -1117,7 +1106,7 @@ handle_alias_pairs (void)
&& target_node && is_a <cgraph_node> (target_node)) && target_node && is_a <cgraph_node> (target_node))
{ {
struct cgraph_node *src_node = cgraph_get_node (p->decl); struct cgraph_node *src_node = cgraph_get_node (p->decl);
if (src_node && src_node->local.finalized) if (src_node && src_node->symbol.definition)
cgraph_reset_node (src_node); cgraph_reset_node (src_node);
cgraph_create_function_alias (p->decl, target_node->symbol.decl); cgraph_create_function_alias (p->decl, target_node->symbol.decl);
alias_pairs->unordered_remove (i); alias_pairs->unordered_remove (i);
@ -1165,9 +1154,9 @@ mark_functions_to_output (void)
/* We need to output all local functions that are used and not /* We need to output all local functions that are used and not
always inlined, as well as those that are reachable from always inlined, as well as those that are reachable from
outside the current compilation unit. */ outside the current compilation unit. */
if (node->analyzed if (node->symbol.analyzed
&& !node->thunk.thunk_p && !node->thunk.thunk_p
&& !node->alias && !node->symbol.alias
&& !node->global.inlined_to && !node->global.inlined_to
&& !TREE_ASM_WRITTEN (decl) && !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl)) && !DECL_EXTERNAL (decl))
@ -1179,7 +1168,7 @@ mark_functions_to_output (void)
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 (!next->thunk.thunk_p && !next->alias) if (!next->thunk.thunk_p && !next->symbol.alias)
next->process = 1; next->process = 1;
} }
} }
@ -1199,7 +1188,7 @@ mark_functions_to_output (void)
are inside partition, we can end up not removing the body since we no longer are inside partition, we can end up not removing the body since we no longer
have analyzed node pointing to it. */ have analyzed node pointing to it. */
&& !node->symbol.in_other_partition && !node->symbol.in_other_partition
&& !node->alias && !node->symbol.alias
&& !node->clones && !node->clones
&& !DECL_EXTERNAL (decl)) && !DECL_EXTERNAL (decl))
{ {
@ -1435,7 +1424,7 @@ assemble_thunk (struct cgraph_node *node)
set_cfun (NULL); set_cfun (NULL);
TREE_ASM_WRITTEN (thunk_fndecl) = 1; TREE_ASM_WRITTEN (thunk_fndecl) = 1;
node->thunk.thunk_p = false; node->thunk.thunk_p = false;
node->analyzed = false; node->symbol.analyzed = false;
} }
else else
{ {
@ -1800,7 +1789,7 @@ output_in_order (void)
FOR_EACH_DEFINED_FUNCTION (pf) FOR_EACH_DEFINED_FUNCTION (pf)
{ {
if (pf->process && !pf->thunk.thunk_p && !pf->alias) if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias)
{ {
i = pf->symbol.order; i = pf->symbol.order;
gcc_assert (nodes[i].kind == ORDER_UNDEFINED); gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
@ -1943,14 +1932,14 @@ output_weakrefs (void)
struct cgraph_node *node; struct cgraph_node *node;
struct varpool_node *vnode; struct varpool_node *vnode;
FOR_EACH_FUNCTION (node) FOR_EACH_FUNCTION (node)
if (node->alias && DECL_EXTERNAL (node->symbol.decl) if (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl)
&& !TREE_ASM_WRITTEN (node->symbol.decl) && !TREE_ASM_WRITTEN (node->symbol.decl)
&& lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
do_assemble_alias (node->symbol.decl, do_assemble_alias (node->symbol.decl,
node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias) node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias)
: get_alias_symbol (node->symbol.decl)); : get_alias_symbol (node->symbol.decl));
FOR_EACH_VARIABLE (vnode) FOR_EACH_VARIABLE (vnode)
if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl) if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl)
&& !TREE_ASM_WRITTEN (vnode->symbol.decl) && !TREE_ASM_WRITTEN (vnode->symbol.decl)
&& lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl))) && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
do_assemble_alias (vnode->symbol.decl, do_assemble_alias (vnode->symbol.decl,
@ -2115,13 +2104,13 @@ finalize_compilation_unit (void)
/* Gimplify and lower all functions, compute reachability and /* Gimplify and lower all functions, compute reachability and
remove unreachable nodes. */ remove unreachable nodes. */
cgraph_analyze_functions (); analyze_functions ();
/* Mark alias targets necessary and emit diagnostics. */ /* Mark alias targets necessary and emit diagnostics. */
handle_alias_pairs (); handle_alias_pairs ();
/* Gimplify and lower thunks. */ /* Gimplify and lower thunks. */
cgraph_analyze_functions (); analyze_functions ();
/* Finally drive the pass manager. */ /* Finally drive the pass manager. */
compile (); compile ();

View File

@ -29468,7 +29468,7 @@ ix86_get_function_versions_dispatcher (void *decl)
dispatcher_version_info dispatcher_version_info
= insert_new_cgraph_node_version (dispatcher_node); = insert_new_cgraph_node_version (dispatcher_node);
dispatcher_version_info->next = default_version_info; dispatcher_version_info->next = default_version_info;
dispatcher_node->local.finalized = 1; dispatcher_node->symbol.definition = 1;
/* Set the dispatcher for all the versions. */ /* Set the dispatcher for all the versions. */
it_v = default_version_info; it_v = default_version_info;
@ -29623,7 +29623,7 @@ ix86_generate_version_dispatcher_body (void *node_p)
default_ver_decl = node_version_info->next->this_node->symbol.decl; default_ver_decl = node_version_info->next->this_node->symbol.decl;
/* node is going to be an alias, so remove the finalized bit. */ /* node is going to be an alias, so remove the finalized bit. */
node->local.finalized = false; node->symbol.definition = false;
resolver_decl = make_resolver_func (default_ver_decl, resolver_decl = make_resolver_func (default_ver_decl,
node->symbol.decl, &empty_bb); node->symbol.decl, &empty_bb);
@ -29817,6 +29817,9 @@ fold_builtin_cpu (tree fndecl, tree *args)
tree __cpu_model_var = make_var_decl (__processor_model_type, tree __cpu_model_var = make_var_decl (__processor_model_type,
"__cpu_model"); "__cpu_model");
varpool_add_new_variable (__cpu_model_var);
gcc_assert ((args != NULL) && (*args != NULL)); gcc_assert ((args != NULL) && (*args != NULL));
param_string_cst = *args; param_string_cst = *args;

View File

@ -1,3 +1,8 @@
2013-05-29 Jan Hubicka <jh@suse.cz>
* tree.c (cp_fix_function_decl_p): Update for new symtab flags.
* decl2.c )var_finalized_p, cp_write_global_declarations): Likewise.
2013-05-25 Paolo Carlini <paolo.carlini@oracle.com> 2013-05-25 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/25666 PR c++/25666

View File

@ -1803,7 +1803,7 @@ import_export_class (tree ctype)
static bool static bool
var_finalized_p (tree var) var_finalized_p (tree var)
{ {
return varpool_node_for_decl (var)->finalized; return varpool_node_for_decl (var)->symbol.definition;
} }
/* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@ -4202,7 +4202,7 @@ cp_write_global_declarations (void)
node = cgraph_get_node (decl); node = cgraph_get_node (decl);
if (node->same_body_alias) if (node->same_body_alias)
node = cgraph_alias_aliased_node (node); node = cgraph_alias_target (node);
cgraph_for_node_and_aliases (node, clear_decl_external, cgraph_for_node_and_aliases (node, clear_decl_external,
NULL, true); NULL, true);
@ -4224,7 +4224,7 @@ cp_write_global_declarations (void)
if (!DECL_EXTERNAL (decl) if (!DECL_EXTERNAL (decl)
&& decl_needed_p (decl) && decl_needed_p (decl)
&& !TREE_ASM_WRITTEN (decl) && !TREE_ASM_WRITTEN (decl)
&& !cgraph_get_node (decl)->local.finalized) && !cgraph_get_node (decl)->symbol.definition)
{ {
/* We will output the function; no longer consider it in this /* We will output the function; no longer consider it in this
loop. */ loop. */

View File

@ -3980,7 +3980,7 @@ cp_fix_function_decl_p (tree decl)
/* Don't fix same_body aliases. Although they don't have their own /* Don't fix same_body aliases. Although they don't have their own
CFG, they share it with what they alias to. */ CFG, they share it with what they alias to. */
if (!node || !node->alias if (!node || !node->symbol.alias
|| !vec_safe_length (node->symbol.ref_list.references)) || !vec_safe_length (node->symbol.ref_list.references))
return true; return true;
} }

View File

@ -2480,7 +2480,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->analyzed) if (!node || !node->symbol.definition)
return NULL; return NULL;
} }
/* FALLTHRU */ /* FALLTHRU */

View File

@ -14919,7 +14919,7 @@ reference_to_unused (tree * tp, int * walk_subtrees,
else if (TREE_CODE (*tp) == VAR_DECL) else if (TREE_CODE (*tp) == VAR_DECL)
{ {
struct varpool_node *node = varpool_get_node (*tp); struct varpool_node *node = varpool_get_node (*tp);
if (!node || !node->analyzed) if (!node || !node->symbol.definition)
return *tp; return *tp;
} }
else if (TREE_CODE (*tp) == FUNCTION_DECL else if (TREE_CODE (*tp) == FUNCTION_DECL
@ -17597,7 +17597,7 @@ premark_types_used_by_global_vars_helper (void **slot,
/* Ask cgraph if the global variable really is to be emitted. /* Ask cgraph if the global variable really is to be emitted.
If yes, then we'll keep the DIE of ENTRY->TYPE. */ If yes, then we'll keep the DIE of ENTRY->TYPE. */
struct varpool_node *node = varpool_get_node (entry->var_decl); struct varpool_node *node = varpool_get_node (entry->var_decl);
if (node && node->analyzed) if (node && node->symbol.definition)
{ {
die->die_perennial_p = 1; die->die_perennial_p = 1;
/* Keep the parent DIEs as well. */ /* Keep the parent DIEs as well. */

View File

@ -114,7 +114,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
The second is important when devirtualization happens during final The second is important when devirtualization happens during final
compilation stage when making a new reference no longer makes callee compilation stage when making a new reference no longer makes callee
to be compiled. */ to be compiled. */
if (!node || !node->analyzed || node->global.inlined_to) if (!node || !node->symbol.definition || node->global.inlined_to)
{ {
gcc_checking_assert (!TREE_ASM_WRITTEN (decl)); gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false; return false;
@ -123,7 +123,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
else if (TREE_CODE (decl) == VAR_DECL) else if (TREE_CODE (decl) == VAR_DECL)
{ {
vnode = varpool_get_node (decl); vnode = varpool_get_node (decl);
if (!vnode || !vnode->analyzed) if (!vnode || !vnode->symbol.definition)
{ {
gcc_checking_assert (!TREE_ASM_WRITTEN (decl)); gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
return false; return false;

View File

@ -440,14 +440,14 @@ determine_versionability (struct cgraph_node *node)
/* There are a number of generic reasons functions cannot be versioned. We /* There are a number of generic reasons functions cannot be versioned. We
also cannot remove parameters if there are type attributes such as fnspec also cannot remove parameters if there are type attributes such as fnspec
present. */ present. */
if (node->alias || node->thunk.thunk_p) if (node->symbol.alias || node->thunk.thunk_p)
reason = "alias or thunk"; reason = "alias or thunk";
else if (!node->local.versionable) else if (!node->local.versionable)
reason = "not a tree_versionable_function"; reason = "not a tree_versionable_function";
else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
reason = "insufficient body availability"; reason = "insufficient body availability";
if (reason && dump_file && !node->alias && !node->thunk.thunk_p) if (reason && dump_file && !node->symbol.alias && !node->thunk.thunk_p)
fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
cgraph_node_name (node), node->symbol.order, reason); cgraph_node_name (node), node->symbol.order, reason);
@ -727,7 +727,7 @@ initialize_node_lattices (struct cgraph_node *node)
set_all_contains_variable (plats); set_all_contains_variable (plats);
} }
if (dump_file && (dump_flags & TDF_DETAILS) if (dump_file && (dump_flags & TDF_DETAILS)
&& !node->alias && !node->thunk.thunk_p) && !node->symbol.alias && !node->thunk.thunk_p)
fprintf (dump_file, "Marking all lattices of %s/%i as %s\n", fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
cgraph_node_name (node), node->symbol.order, cgraph_node_name (node), node->symbol.order,
disable ? "BOTTOM" : "VARIABLE"); disable ? "BOTTOM" : "VARIABLE");
@ -1418,7 +1418,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
int i, args_count, parms_count; int i, args_count, parms_count;
callee = cgraph_function_node (cs->callee, &availability); callee = cgraph_function_node (cs->callee, &availability);
if (!callee->analyzed) if (!callee->symbol.definition)
return false; return false;
gcc_checking_assert (cgraph_function_with_gimple_body_p (callee)); gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
callee_info = IPA_NODE_REF (callee); callee_info = IPA_NODE_REF (callee);
@ -1431,8 +1431,8 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
parameter. However, we might need to uncover a thunk from below a series parameter. However, we might need to uncover a thunk from below a series
of aliases first. */ of aliases first. */
alias_or_thunk = cs->callee; alias_or_thunk = cs->callee;
while (alias_or_thunk->alias) while (alias_or_thunk->symbol.alias)
alias_or_thunk = cgraph_alias_aliased_node (alias_or_thunk); alias_or_thunk = cgraph_alias_target (alias_or_thunk);
if (alias_or_thunk->thunk.thunk_p) if (alias_or_thunk->thunk.thunk_p)
{ {
ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
@ -1601,7 +1601,7 @@ devirtualization_time_bonus (struct cgraph_node *node,
/* Only bare minimum benefit for clearly un-inlineable targets. */ /* Only bare minimum benefit for clearly un-inlineable targets. */
res += 1; res += 1;
callee = cgraph_get_node (target); callee = cgraph_get_node (target);
if (!callee || !callee->analyzed) if (!callee || !callee->symbol.definition)
continue; continue;
isummary = inline_summary (callee); isummary = inline_summary (callee);
if (!isummary->inlinable) if (!isummary->inlinable)
@ -2231,9 +2231,10 @@ ipcp_propagate_stage (struct topo_info *topo)
ipa_get_param_count (info)); ipa_get_param_count (info));
initialize_node_lattices (node); initialize_node_lattices (node);
} }
if (node->symbol.definition && !node->symbol.alias)
overall_size += inline_summary (node)->self_size;
if (node->count > max_count) if (node->count > max_count)
max_count = node->count; max_count = node->count;
overall_size += inline_summary (node)->self_size;
} }
max_new_size = overall_size; max_new_size = overall_size;

View File

@ -1351,7 +1351,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node,
void void
dump_inline_summary (FILE *f, struct cgraph_node *node) dump_inline_summary (FILE *f, struct cgraph_node *node)
{ {
if (node->analyzed) if (node->symbol.definition)
{ {
struct inline_summary *s = inline_summary (node); struct inline_summary *s = inline_summary (node);
size_time_entry *e; size_time_entry *e;
@ -1427,7 +1427,7 @@ initialize_inline_failed (struct cgraph_edge *e)
if (e->indirect_unknown_callee) if (e->indirect_unknown_callee)
e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL; e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
else if (!callee->analyzed) else if (!callee->symbol.definition)
e->inline_failed = CIF_BODY_NOT_AVAILABLE; e->inline_failed = CIF_BODY_NOT_AVAILABLE;
else if (callee->local.redefined_extern_inline) else if (callee->local.redefined_extern_inline)
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE; e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
@ -2765,7 +2765,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
gcc_checking_assert (*size >= 0); gcc_checking_assert (*size >= 0);
callee = cgraph_get_node (target); callee = cgraph_get_node (target);
if (!callee || !callee->analyzed) if (!callee || !callee->symbol.definition)
return false; return false;
isummary = inline_summary (callee); isummary = inline_summary (callee);
return isummary->inlinable; return isummary->inlinable;
@ -3683,7 +3683,7 @@ inline_generate_summary (void)
inline_free_summary (); inline_free_summary ();
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (!node->alias) if (!node->symbol.alias)
inline_analyze_function (node); inline_analyze_function (node);
} }
@ -3917,7 +3917,7 @@ inline_write_summary (void)
{ {
symtab_node snode = lto_symtab_encoder_deref (encoder, i); symtab_node snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode); cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
if (cnode && cnode->analyzed) if (cnode && cnode->symbol.definition && !cnode->symbol.alias)
count++; count++;
} }
streamer_write_uhwi (ob, count); streamer_write_uhwi (ob, count);
@ -3926,7 +3926,7 @@ inline_write_summary (void)
{ {
symtab_node snode = lto_symtab_encoder_deref (encoder, i); symtab_node snode = lto_symtab_encoder_deref (encoder, i);
cgraph_node *cnode = dyn_cast <cgraph_node> (snode); cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
if (cnode && (node = cnode)->analyzed) if (cnode && (node = cnode)->symbol.definition && !node->symbol.alias)
{ {
struct inline_summary *info = inline_summary (node); struct inline_summary *info = inline_summary (node);
struct bitpack_d bp; struct bitpack_d bp;

View File

@ -153,7 +153,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
cgraph_remove_unreachable_functions gets rid of them. */ cgraph_remove_unreachable_functions gets rid of them. */
gcc_assert (!e->callee->global.inlined_to); gcc_assert (!e->callee->global.inlined_to);
symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee); symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->symbol.decl)) if (e->callee->symbol.definition && !DECL_EXTERNAL (e->callee->symbol.decl))
{ {
if (overall_size) if (overall_size)
*overall_size -= inline_summary (e->callee)->size; *overall_size -= inline_summary (e->callee)->size;
@ -236,7 +236,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
if (!alias->callers if (!alias->callers
&& can_remove_node_now_p (alias, e)) && can_remove_node_now_p (alias, e))
{ {
next_alias = cgraph_alias_aliased_node (alias); next_alias = cgraph_alias_target (alias);
cgraph_remove_node (alias); cgraph_remove_node (alias);
alias = next_alias; alias = next_alias;
} }
@ -381,7 +381,7 @@ static bool
preserve_function_body_p (struct cgraph_node *node) preserve_function_body_p (struct cgraph_node *node)
{ {
gcc_assert (cgraph_global_info_ready); gcc_assert (cgraph_global_info_ready);
gcc_assert (!node->alias && !node->thunk.thunk_p); gcc_assert (!node->symbol.alias && !node->thunk.thunk_p);
/* Look if there is any clone around. */ /* Look if there is any clone around. */
if (node->clones) if (node->clones)

View File

@ -253,7 +253,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
gcc_assert (e->inline_failed); gcc_assert (e->inline_failed);
if (!callee || !callee->analyzed) if (!callee || !callee->symbol.definition)
{ {
e->inline_failed = CIF_BODY_NOT_AVAILABLE; e->inline_failed = CIF_BODY_NOT_AVAILABLE;
inlinable = false; inlinable = false;
@ -1100,7 +1100,7 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
int i; int i;
struct ipa_ref *ref; struct ipa_ref *ref;
if ((!node->alias && !inline_summary (node)->inlinable) if ((!node->symbol.alias && !inline_summary (node)->inlinable)
|| cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE || cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
|| node->global.inlined_to) || node->global.inlined_to)
return; return;
@ -1795,6 +1795,9 @@ ipa_inline (void)
} }
inline_small_functions (); inline_small_functions ();
/* Do first after-inlining removal. We want to remove all "stale" extern inline
functions and virtual functions so we really know what is called once. */
symtab_remove_unreachable_nodes (false, dump_file); symtab_remove_unreachable_nodes (false, dump_file);
free (order); free (order);

View File

@ -1521,7 +1521,7 @@ ipa_compute_jump_functions (struct cgraph_node *node,
NULL); NULL);
/* We do not need to bother analyzing calls to unknown /* We do not need to bother analyzing calls to unknown
functions unless they may become known during lto/whopr. */ functions unless they may become known during lto/whopr. */
if (!callee->analyzed && !flag_lto) if (!callee->symbol.definition && !flag_lto)
continue; continue;
ipa_compute_jump_functions_for_edge (parms_ainfo, cs); ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
} }
@ -2978,7 +2978,7 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node)
tree temp; tree temp;
struct ipa_node_params *info; struct ipa_node_params *info;
if (!node->analyzed) if (!node->symbol.definition)
return; return;
info = IPA_NODE_REF (node); info = IPA_NODE_REF (node);
fprintf (f, " function %s/%i parameter descriptors:\n", fprintf (f, " function %s/%i parameter descriptors:\n",
@ -3972,7 +3972,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data,
index = streamer_read_uhwi (&ib_main); index = streamer_read_uhwi (&ib_main);
encoder = file_data->symtab_node_encoder; encoder = file_data->symtab_node_encoder;
node = cgraph (lto_symtab_encoder_deref (encoder, index)); node = cgraph (lto_symtab_encoder_deref (encoder, index));
gcc_assert (node->analyzed); gcc_assert (node->symbol.definition);
ipa_read_node_info (&ib_main, node, data_in); ipa_read_node_info (&ib_main, node, data_in);
} }
lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
@ -4016,7 +4016,6 @@ ipa_update_after_lto_read (void)
ipa_check_create_edge_args (); ipa_check_create_edge_args ();
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (node->analyzed)
ipa_initialize_node_params (node); ipa_initialize_node_params (node);
} }
@ -4154,7 +4153,7 @@ read_replacements_section (struct lto_file_decl_data *file_data,
index = streamer_read_uhwi (&ib_main); index = streamer_read_uhwi (&ib_main);
encoder = file_data->symtab_node_encoder; encoder = file_data->symtab_node_encoder;
node = cgraph (lto_symtab_encoder_deref (encoder, index)); node = cgraph (lto_symtab_encoder_deref (encoder, index));
gcc_assert (node->analyzed); gcc_assert (node->symbol.definition);
read_agg_replacement_chain (&ib_main, node, data_in); read_agg_replacement_chain (&ib_main, node, data_in);
} }
lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,

View File

@ -738,7 +738,7 @@ analyze_function (struct cgraph_node *fn, bool ipa)
flags_from_decl_or_type (fn->symbol.decl), flags_from_decl_or_type (fn->symbol.decl),
cgraph_node_cannot_return (fn)); cgraph_node_cannot_return (fn));
if (fn->thunk.thunk_p || fn->alias) if (fn->thunk.thunk_p || fn->symbol.alias)
{ {
/* Thunk gets propagated through, so nothing interesting happens. */ /* Thunk gets propagated through, so nothing interesting happens. */
gcc_assert (ipa); gcc_assert (ipa);
@ -951,7 +951,7 @@ pure_const_write_summary (void)
lsei_next_function_in_partition (&lsei)) lsei_next_function_in_partition (&lsei))
{ {
node = lsei_cgraph_node (lsei); node = lsei_cgraph_node (lsei);
if (node->analyzed && has_function_state (node)) if (node->symbol.definition && has_function_state (node))
count++; count++;
} }
@ -962,7 +962,7 @@ pure_const_write_summary (void)
lsei_next_function_in_partition (&lsei)) lsei_next_function_in_partition (&lsei))
{ {
node = lsei_cgraph_node (lsei); node = lsei_cgraph_node (lsei);
if (node->analyzed && has_function_state (node)) if (node->symbol.definition && has_function_state (node))
{ {
struct bitpack_d bp; struct bitpack_d bp;
funct_state fs; funct_state fs;
@ -1124,7 +1124,7 @@ propagate_pure_const (void)
int count = 0; int count = 0;
node = order[i]; node = order[i];
if (node->alias) if (node->symbol.alias)
continue; continue;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
@ -1394,7 +1394,7 @@ propagate_nothrow (void)
bool can_throw = false; bool can_throw = false;
node = order[i]; node = order[i];
if (node->alias) if (node->symbol.alias)
continue; continue;
/* Find the worst state for any node in the cycle. */ /* Find the worst state for any node in the cycle. */

View File

@ -684,7 +684,7 @@ propagate (void)
|| TREE_ADDRESSABLE (vnode->symbol.decl) || TREE_ADDRESSABLE (vnode->symbol.decl)
|| TREE_READONLY (vnode->symbol.decl) || TREE_READONLY (vnode->symbol.decl)
|| !is_proper_for_analysis (vnode->symbol.decl) || !is_proper_for_analysis (vnode->symbol.decl)
|| !vnode->analyzed) || !vnode->symbol.definition)
bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl)); bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
/* Forget info we collected "just for fun" on variables that turned out to be /* Forget info we collected "just for fun" on variables that turned out to be
@ -716,7 +716,7 @@ propagate (void)
bool write_all = false; bool write_all = false;
node = order[i]; node = order[i];
if (node->alias) if (node->symbol.alias)
continue; continue;
node_info = get_reference_vars_info (node); node_info = get_reference_vars_info (node);
@ -794,7 +794,7 @@ propagate (void)
struct cgraph_node *w; struct cgraph_node *w;
node = order[i]; node = order[i];
if (node->alias) if (node->symbol.alias)
continue; continue;
fprintf (dump_file, fprintf (dump_file,
@ -835,7 +835,7 @@ propagate (void)
ipa_reference_optimization_summary_t opt; ipa_reference_optimization_summary_t opt;
node_info = get_reference_vars_info (node); node_info = get_reference_vars_info (node);
if (!node->alias if (!node->symbol.alias
&& (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
|| (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF))) || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
{ {
@ -894,7 +894,7 @@ write_node_summary_p (struct cgraph_node *node,
ipa_reference_optimization_summary_t info; ipa_reference_optimization_summary_t info;
/* See if we have (non-empty) info. */ /* See if we have (non-empty) info. */
if (!node->analyzed || node->global.inlined_to) if (!node->symbol.definition || node->global.inlined_to)
return false; return false;
info = get_reference_optimization_summary (node); info = get_reference_optimization_summary (node);
if (!info || (bitmap_empty_p (info->statics_not_read) if (!info || (bitmap_empty_p (info->statics_not_read)

View File

@ -367,24 +367,47 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
unsigned int i; unsigned int i;
int incoming_freq = 0; int incoming_freq = 0;
tree retval; tree retval;
bool back_edge = false;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
dump_split_point (dump_file, current); dump_split_point (dump_file, current);
FOR_EACH_EDGE (e, ei, current->entry_bb->preds) FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
{
if (e->flags & EDGE_DFS_BACK)
back_edge = true;
if (!bitmap_bit_p (current->split_bbs, e->src->index)) if (!bitmap_bit_p (current->split_bbs, e->src->index))
incoming_freq += EDGE_FREQUENCY (e); incoming_freq += EDGE_FREQUENCY (e);
}
/* Do not split when we would end up calling function anyway. */ /* Do not split when we would end up calling function anyway. */
if (incoming_freq if (incoming_freq
>= (ENTRY_BLOCK_PTR->frequency >= (ENTRY_BLOCK_PTR->frequency
* PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100)) * PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100))
{
/* When profile is guessed, we can not expect it to give us
realistic estimate on likelyness of function taking the
complex path. As a special case, when tail of the function is
a loop, enable splitting since inlining code skipping the loop
is likely noticeable win. */
if (back_edge
&& profile_status != PROFILE_READ
&& incoming_freq < ENTRY_BLOCK_PTR->frequency)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
" Split before loop, accepting despite low frequencies %i %i.\n",
incoming_freq,
ENTRY_BLOCK_PTR->frequency);
}
else
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, fprintf (dump_file,
" Refused: incoming frequency is too large.\n"); " Refused: incoming frequency is too large.\n");
return; return;
} }
}
if (!current->header_size) if (!current->header_size)
{ {
@ -1533,6 +1556,11 @@ execute_split_functions (void)
return 0; return 0;
} }
/* We enforce splitting after loop headers when profile info is not
available. */
if (profile_status != PROFILE_READ)
mark_dfs_back_edges ();
/* Initialize bitmap to track forbidden calls. */ /* Initialize bitmap to track forbidden calls. */
forbidden_dominators = BITMAP_ALLOC (NULL); forbidden_dominators = BITMAP_ALLOC (NULL);
calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_DOMINATORS);

View File

@ -287,7 +287,7 @@ ipa_reverse_postorder (struct cgraph_node **order)
&& (pass && (pass
|| (!node->symbol.address_taken || (!node->symbol.address_taken
&& !node->global.inlined_to && !node->global.inlined_to
&& !node->alias && !node->thunk.thunk_p && !node->symbol.alias && !node->thunk.thunk_p
&& !cgraph_only_called_directly_p (node)))) && !cgraph_only_called_directly_p (node))))
{ {
stack_size = 0; stack_size = 0;

173
gcc/ipa.c
View File

@ -39,6 +39,53 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h" #include "lto-streamer.h"
#include "data-streamer.h" #include "data-streamer.h"
/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
static bool
cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
/* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
return !(cgraph_only_called_directly_or_aliased_p (node)
&& !ipa_ref_has_aliases_p (&node->symbol.ref_list)
&& node->symbol.definition
&& !DECL_EXTERNAL (node->symbol.decl)
&& !node->symbol.externally_visible
&& !node->symbol.used_from_other_partition
&& !node->symbol.in_other_partition);
}
/* Return true when function can be marked local. */
static bool
cgraph_local_node_p (struct cgraph_node *node)
{
struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
/* FIXME: thunks can be considered local, but we need prevent i386
from attempting to change calling convention of them. */
if (n->thunk.thunk_p)
return false;
return !cgraph_for_node_and_aliases (n,
cgraph_non_local_node_p_1, NULL, true);
}
/* Return true when NODE has ADDR reference. */
static bool
has_addr_references_p (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED)
{
int i;
struct ipa_ref *ref;
for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ADDR)
return true;
return false;
}
/* 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. */
@ -89,79 +136,23 @@ process_references (struct ipa_ref_list *list,
struct ipa_ref *ref; struct ipa_ref *ref;
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
{ {
if (is_a <cgraph_node> (ref->referred)) symtab_node node = ref->referred;
{
struct cgraph_node *node = ipa_ref_node (ref);
if (node->analyzed if (node->symbol.definition
&& (!DECL_EXTERNAL (node->symbol.decl) && (!DECL_EXTERNAL (node->symbol.decl)
|| node->alias || node->symbol.alias
|| before_inlining_p)) || (before_inlining_p
/* We use variable constructors during late complation for
constant folding. Keep references alive so partitioning
knows about potential references. */
|| (TREE_CODE (node->symbol.decl) == VAR_DECL
&& flag_wpa && const_value_known_p (node->symbol.decl)))))
pointer_set_insert (reachable, node); pointer_set_insert (reachable, node);
enqueue_node ((symtab_node) node, first, reachable); enqueue_node ((symtab_node) node, first, reachable);
} }
else
{
struct varpool_node *node = ipa_ref_varpool_node (ref);
if (node->analyzed
&& (!DECL_EXTERNAL (node->symbol.decl)
|| node->alias
|| before_inlining_p))
pointer_set_insert (reachable, node);
enqueue_node ((symtab_node) node, first, reachable);
}
}
} }
/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
static bool
cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
/* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
return !(cgraph_only_called_directly_or_aliased_p (node)
&& !ipa_ref_has_aliases_p (&node->symbol.ref_list)
&& node->analyzed
&& !DECL_EXTERNAL (node->symbol.decl)
&& !node->symbol.externally_visible
&& !node->symbol.used_from_other_partition
&& !node->symbol.in_other_partition);
}
/* Return true when function can be marked local. */
static bool
cgraph_local_node_p (struct cgraph_node *node)
{
struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
/* FIXME: thunks can be considered local, but we need prevent i386
from attempting to change calling convention of them. */
if (n->thunk.thunk_p)
return false;
return !cgraph_for_node_and_aliases (n,
cgraph_non_local_node_p_1, NULL, true);
}
/* Return true when NODE has ADDR reference. */
static bool
has_addr_references_p (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED)
{
int i;
struct ipa_ref *ref;
for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ADDR)
return true;
return false;
}
/* Perform reachability analysis and reclaim all unreachable nodes. /* Perform reachability analysis and reclaim all unreachable nodes.
The algorithm is basically mark&sweep but with some extra refinements: The algorithm is basically mark&sweep but with some extra refinements:
@ -303,10 +294,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
struct cgraph_edge *e; struct cgraph_edge *e;
for (e = cnode->callees; e; e = e->next_callee) for (e = cnode->callees; e; e = e->next_callee)
{ {
if (e->callee->analyzed if (e->callee->symbol.definition
&& (!e->inline_failed && (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->symbol.decl) || !DECL_EXTERNAL (e->callee->symbol.decl)
|| cnode->alias || cnode->symbol.alias
|| before_inlining_p)) || before_inlining_p))
pointer_set_insert (reachable, e->callee); pointer_set_insert (reachable, e->callee);
enqueue_node ((symtab_node) e->callee, &first, reachable); enqueue_node ((symtab_node) e->callee, &first, reachable);
@ -314,7 +305,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
/* When inline clone exists, mark body to be preserved so when removing /* When inline clone exists, mark body to be preserved so when removing
offline copy of the function we don't kill it. */ offline copy of the function we don't kill it. */
if (!cnode->alias && cnode->global.inlined_to) if (!cnode->symbol.alias && cnode->global.inlined_to)
pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl); pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
} }
@ -339,7 +330,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
varpool_node *vnode = dyn_cast <varpool_node> (node); varpool_node *vnode = dyn_cast <varpool_node> (node);
if (vnode if (vnode
&& DECL_EXTERNAL (node->symbol.decl) && DECL_EXTERNAL (node->symbol.decl)
&& !vnode->alias && !vnode->symbol.alias
&& in_boundary_p) && in_boundary_p)
{ {
struct ipa_ref *ref; struct ipa_ref *ref;
@ -352,6 +343,8 @@ symtab_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 is not needed at all, remove it. */
if (!node->symbol.aux) if (!node->symbol.aux)
{ {
if (file) if (file)
@ -359,20 +352,18 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
cgraph_remove_node (node); cgraph_remove_node (node);
changed = true; changed = true;
} }
/* If node is unreachable, remove its body. */
else if (!pointer_set_contains (reachable, node)) else if (!pointer_set_contains (reachable, node))
{ {
if (node->analyzed) if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
cgraph_release_function_body (node);
if (node->symbol.definition)
{ {
if (file) if (file)
fprintf (file, " %s", cgraph_node_name (node)); fprintf (file, " %s", cgraph_node_name (node));
cgraph_node_remove_callees (node); cgraph_reset_node (node);
ipa_remove_all_references (&node->symbol.ref_list);
changed = true; changed = true;
} }
if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
&& (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
cgraph_release_function_body (node);
node->analyzed = false;
} }
} }
@ -406,14 +397,20 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
} }
else if (!pointer_set_contains (reachable, vnode)) else if (!pointer_set_contains (reachable, vnode))
{ {
if (vnode->analyzed) if (vnode->symbol.definition)
{ {
if (file) if (file)
fprintf (file, " %s", varpool_node_name (vnode)); fprintf (file, " %s", varpool_node_name (vnode));
changed = true; changed = true;
} }
vnode->analyzed = false; vnode->symbol.definition = false;
vnode->symbol.analyzed = false;
vnode->symbol.aux = NULL; vnode->symbol.aux = NULL;
/* Keep body if it may be useful for constant folding. */
if (!const_value_known_p (vnode->symbol.decl))
varpool_remove_initializer (vnode);
ipa_remove_all_references (&vnode->symbol.ref_list);
} }
else else
vnode->symbol.aux = NULL; vnode->symbol.aux = NULL;
@ -474,7 +471,7 @@ ipa_discover_readonly_nonaddressable_vars (void)
if (dump_file) if (dump_file)
fprintf (dump_file, "Clearing variable flags:"); fprintf (dump_file, "Clearing variable flags:");
FOR_EACH_VARIABLE (vnode) FOR_EACH_VARIABLE (vnode)
if (vnode->finalized && varpool_all_refs_explicit_p (vnode) if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode)
&& (TREE_ADDRESSABLE (vnode->symbol.decl) && (TREE_ADDRESSABLE (vnode->symbol.decl)
|| !TREE_READONLY (vnode->symbol.decl))) || !TREE_READONLY (vnode->symbol.decl)))
{ {
@ -546,12 +543,12 @@ cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
Virtual functions do have their addresses taken from the vtables, Virtual functions do have their addresses taken from the vtables,
but in C++ there is no way to compare their addresses for equality. */ but in C++ there is no way to compare their addresses for equality. */
bool static bool
cgraph_comdat_can_be_unshared_p (struct cgraph_node *node) cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
{ {
if ((cgraph_address_taken_from_non_vtable_p (node) if ((cgraph_address_taken_from_non_vtable_p (node)
&& !DECL_VIRTUAL_P (node->symbol.decl)) && !DECL_VIRTUAL_P (node->symbol.decl))
|| !node->analyzed) || !node->symbol.definition)
return false; return false;
if (node->symbol.same_comdat_group) if (node->symbol.same_comdat_group)
{ {
@ -575,7 +572,7 @@ static bool
cgraph_externally_visible_p (struct cgraph_node *node, cgraph_externally_visible_p (struct cgraph_node *node,
bool whole_program) bool whole_program)
{ {
if (!node->local.finalized) if (!node->symbol.definition)
return false; return false;
if (!DECL_COMDAT (node->symbol.decl) if (!DECL_COMDAT (node->symbol.decl)
&& (!TREE_PUBLIC (node->symbol.decl) && (!TREE_PUBLIC (node->symbol.decl)
@ -619,7 +616,7 @@ cgraph_externally_visible_p (struct cgraph_node *node,
|| DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL) || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
/* Be sure that node is defined in IR file, not in other object /* Be sure that node is defined in IR file, not in other object
file. In that case we don't set used_from_other_object_file. */ file. In that case we don't set used_from_other_object_file. */
&& node->analyzed) && node->symbol.definition)
; ;
else if (!whole_program) else if (!whole_program)
return true; return true;
@ -638,7 +635,7 @@ varpool_externally_visible_p (struct varpool_node *vnode)
/* Do not touch weakrefs; while they are not externally visible, /* Do not touch weakrefs; while they are not externally visible,
dropping their DECL_EXTERNAL flags confuse most dropping their DECL_EXTERNAL flags confuse most
of code handling them. */ of code handling them. */
if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)) if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl))
return true; return true;
if (DECL_EXTERNAL (vnode->symbol.decl)) if (DECL_EXTERNAL (vnode->symbol.decl))
@ -690,7 +687,7 @@ varpool_externally_visible_p (struct varpool_node *vnode)
|| DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL) || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
/* Be sure that node is defined in IR file, not in other object /* Be sure that node is defined in IR file, not in other object
file. In that case we don't set used_from_other_object_file. */ file. In that case we don't set used_from_other_object_file. */
&& vnode->finalized) && vnode->symbol.definition)
; ;
else if (!flag_whole_program) else if (!flag_whole_program)
return true; return true;
@ -744,7 +741,7 @@ function_and_variable_visibility (bool whole_program)
We may end up marking as node external nodes where this flag is meaningless We may end up marking as node external nodes where this flag is meaningless
strip it. */ strip it. */
if (node->symbol.force_output if (node->symbol.force_output
&& (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed)) && (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition))
node->symbol.force_output = 0; node->symbol.force_output = 0;
/* C++ FE on lack of COMDAT support create local COMDAT functions /* C++ FE on lack of COMDAT support create local COMDAT functions
@ -781,7 +778,7 @@ function_and_variable_visibility (bool whole_program)
} }
else else
node->symbol.externally_visible = false; node->symbol.externally_visible = false;
if (!node->symbol.externally_visible && node->analyzed if (!node->symbol.externally_visible && node->symbol.definition
&& !DECL_EXTERNAL (node->symbol.decl)) && !DECL_EXTERNAL (node->symbol.decl))
{ {
gcc_assert (whole_program || in_lto_p gcc_assert (whole_program || in_lto_p
@ -854,7 +851,7 @@ function_and_variable_visibility (bool whole_program)
} }
FOR_EACH_DEFINED_VARIABLE (vnode) FOR_EACH_DEFINED_VARIABLE (vnode)
{ {
if (!vnode->finalized) if (!vnode->symbol.definition)
continue; continue;
if (varpool_externally_visible_p (vnode)) if (varpool_externally_visible_p (vnode))
vnode->symbol.externally_visible = true; vnode->symbol.externally_visible = true;

View File

@ -1,3 +1,7 @@
2013-05-29 Jan Hubicka <jh@suse.cz>
* decl.c (java_mark_decl_local): Update for new symtab flags.
2013-05-22 Matthias Klose <doko@ubuntu.com> 2013-05-22 Matthias Klose <doko@ubuntu.com>
* jvspec.c (jvgenmain_spec): Add %I to cc1 call. * jvspec.c (jvgenmain_spec): Add %I to cc1 call.

View File

@ -1904,7 +1904,7 @@ java_mark_decl_local (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
{ {
struct cgraph_node *node = cgraph_get_node (decl); struct cgraph_node *node = cgraph_get_node (decl);
gcc_assert (!node || !node->local.finalized); gcc_assert (!node || !node->symbol.definition);
} }
#endif #endif
gcc_assert (!DECL_RTL_SET_P (decl)); gcc_assert (!DECL_RTL_SET_P (decl));

View File

@ -320,7 +320,7 @@ bool
reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder) reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
{ {
struct cgraph_edge *e; struct cgraph_edge *e;
if (!node->analyzed) if (!node->symbol.definition)
return false; return false;
if (node->global.inlined_to) if (node->global.inlined_to)
return false; return false;
@ -380,7 +380,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
if (node->analyzed && !boundary_p) if (node->symbol.analyzed && !boundary_p)
tag = LTO_symtab_analyzed_node; tag = LTO_symtab_analyzed_node;
else else
tag = LTO_symtab_unavail_node; tag = LTO_symtab_unavail_node;
@ -399,7 +399,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
Cherry-picked nodes: These are nodes we pulled from other Cherry-picked nodes: These are nodes we pulled from other
translation units into SET during IPA-inlining. We make them as translation units into SET during IPA-inlining. We make them as
local static nodes to prevent clashes with other local statics. */ local static nodes to prevent clashes with other local statics. */
if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl)) if (boundary_p && node->symbol.analyzed && !DECL_EXTERNAL (node->symbol.decl))
{ {
/* Inline clones can not be part of boundary. /* Inline clones can not be part of boundary.
gcc_assert (!node->global.inlined_to); gcc_assert (!node->global.inlined_to);
@ -463,7 +463,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp = bitpack_create (ob->main_stream); bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, node->local.local, 1); bp_pack_value (&bp, node->local.local, 1);
bp_pack_value (&bp, node->symbol.externally_visible, 1); bp_pack_value (&bp, node->symbol.externally_visible, 1);
bp_pack_value (&bp, node->local.finalized, 1); bp_pack_value (&bp, node->symbol.definition, 1);
bp_pack_value (&bp, node->local.versionable, 1); bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 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->local.redefined_extern_inline, 1);
@ -485,7 +485,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
defined in other unit, we may use the info on aliases to resolve defined in other unit, we may use the info on aliases to resolve
symbol1 != symbol2 type tests that we can do only for locally defined objects symbol1 != symbol2 type tests that we can do only for locally defined objects
otherwise. */ otherwise. */
bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1); bp_pack_value (&bp, node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
bp_pack_value (&bp, node->frequency, 2); bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1); bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1); bp_pack_value (&bp, node->only_called_at_exit, 1);
@ -504,8 +504,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset); streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value); streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
} }
if ((node->alias || node->thunk.thunk_p) if ((node->symbol.alias || node->thunk.thunk_p)
&& (!boundary_p || (node->alias && DECL_EXTERNAL (node->symbol.decl)))) && (!boundary_p || (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl))))
{ {
streamer_write_hwi_in_range (ob->main_stream, 0, 1, streamer_write_hwi_in_range (ob->main_stream, 0, 1,
node->thunk.alias != NULL); node->thunk.alias != NULL);
@ -522,7 +522,7 @@ static void
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node, lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
lto_symtab_encoder_t encoder) lto_symtab_encoder_t encoder)
{ {
bool boundary_p = (node->analyzed bool boundary_p = (node->symbol.definition
&& !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node)); && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
struct bitpack_d bp; struct bitpack_d bp;
int ref; int ref;
@ -535,10 +535,10 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
bp_pack_value (&bp, node->symbol.externally_visible, 1); bp_pack_value (&bp, node->symbol.externally_visible, 1);
bp_pack_value (&bp, node->symbol.force_output, 1); bp_pack_value (&bp, node->symbol.force_output, 1);
bp_pack_value (&bp, node->symbol.unique_name, 1); bp_pack_value (&bp, node->symbol.unique_name, 1);
bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->symbol.definition, 1);
bp_pack_value (&bp, node->alias, 1); bp_pack_value (&bp, node->symbol.alias, 1);
bp_pack_value (&bp, node->alias_of != NULL, 1); bp_pack_value (&bp, node->alias_of != NULL, 1);
gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->symbol.definition || !node->symbol.analyzed);
/* Constant pool initializers can be de-unified into individual ltrans units. /* Constant pool initializers can be de-unified into individual ltrans units.
FIXME: Alternatively at -Os we may want to avoid generating for them the local FIXME: Alternatively at -Os we may want to avoid generating for them the local
labels and share them across LTRANS partitions. */ labels and share them across LTRANS partitions. */
@ -551,7 +551,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
} }
else else
{ {
bp_pack_value (&bp, node->analyzed bp_pack_value (&bp, node->symbol.definition
&& referenced_from_other_partition_p (&node->symbol.ref_list, && referenced_from_other_partition_p (&node->symbol.ref_list,
encoder), 1); encoder), 1);
bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1); bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
@ -756,7 +756,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
!lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei)) !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
{ {
struct varpool_node *vnode = lsei_varpool_node (lsei); struct varpool_node *vnode = lsei_varpool_node (lsei);
gcc_assert (!vnode->alias || vnode->alias_of); gcc_assert (!vnode->symbol.alias || vnode->alias_of);
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
lto_set_symtab_encoder_encode_initializer (encoder, vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode);
add_references (encoder, &vnode->symbol.ref_list); add_references (encoder, &vnode->symbol.ref_list);
@ -883,7 +883,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->local.local = bp_unpack_value (bp, 1); node->local.local = bp_unpack_value (bp, 1);
node->symbol.externally_visible = bp_unpack_value (bp, 1); node->symbol.externally_visible = bp_unpack_value (bp, 1);
node->local.finalized = bp_unpack_value (bp, 1); node->symbol.definition = bp_unpack_value (bp, 1);
node->local.versionable = bp_unpack_value (bp, 1); node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = 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->local.redefined_extern_inline = bp_unpack_value (bp, 1);
@ -893,7 +893,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->abstract_and_needed = 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); node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
node->lowered = bp_unpack_value (bp, 1); node->lowered = bp_unpack_value (bp, 1);
node->analyzed = tag == LTO_symtab_analyzed_node; node->symbol.analyzed = tag == LTO_symtab_analyzed_node;
node->symbol.in_other_partition = bp_unpack_value (bp, 1); node->symbol.in_other_partition = bp_unpack_value (bp, 1);
if (node->symbol.in_other_partition if (node->symbol.in_other_partition
/* Avoid updating decl when we are seeing just inline clone. /* Avoid updating decl when we are seeing just inline clone.
@ -909,7 +909,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
DECL_EXTERNAL (node->symbol.decl) = 1; DECL_EXTERNAL (node->symbol.decl) = 1;
TREE_STATIC (node->symbol.decl) = 0; TREE_STATIC (node->symbol.decl) = 0;
} }
node->alias = bp_unpack_value (bp, 1); node->symbol.alias = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2); node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1); node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1); node->only_called_at_exit = bp_unpack_value (bp, 1);
@ -1004,7 +1004,7 @@ input_node (struct lto_file_decl_data *file_data,
node->thunk.virtual_value = virtual_value; node->thunk.virtual_value = virtual_value;
node->thunk.virtual_offset_p = (type & 4); node->thunk.virtual_offset_p = (type & 4);
} }
if (node->thunk.thunk_p || node->alias) if (node->thunk.thunk_p || node->symbol.alias)
{ {
if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1)) if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
{ {
@ -1044,12 +1044,12 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->symbol.externally_visible = bp_unpack_value (&bp, 1); node->symbol.externally_visible = bp_unpack_value (&bp, 1);
node->symbol.force_output = bp_unpack_value (&bp, 1); node->symbol.force_output = bp_unpack_value (&bp, 1);
node->symbol.unique_name = bp_unpack_value (&bp, 1); node->symbol.unique_name = bp_unpack_value (&bp, 1);
node->finalized = bp_unpack_value (&bp, 1); node->symbol.definition = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1); node->symbol.alias = bp_unpack_value (&bp, 1);
non_null_aliasof = bp_unpack_value (&bp, 1); non_null_aliasof = bp_unpack_value (&bp, 1);
node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1); node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
node->symbol.in_other_partition = bp_unpack_value (&bp, 1); node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
node->analyzed = (node->finalized && (!node->alias || !node->symbol.in_other_partition)); node->symbol.analyzed = (node->symbol.definition && (!node->symbol.alias || !node->symbol.in_other_partition));
if (node->symbol.in_other_partition) if (node->symbol.in_other_partition)
{ {
DECL_EXTERNAL (node->symbol.decl) = 1; DECL_EXTERNAL (node->symbol.decl) = 1;

View File

@ -1013,7 +1013,7 @@ lto_output (void)
cgraph_node *node = dyn_cast <cgraph_node> (snode); cgraph_node *node = dyn_cast <cgraph_node> (snode);
if (node if (node
&& lto_symtab_encoder_encode_body_p (encoder, node) && lto_symtab_encoder_encode_body_p (encoder, node)
&& !node->alias && !node->symbol.alias
&& !node->thunk.thunk_p) && !node->thunk.thunk_p)
{ {
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
@ -1243,10 +1243,10 @@ write_symbol (struct streamer_tree_cache_d *cache,
/* When something is defined, it should have node attached. */ /* When something is defined, it should have node attached. */
gcc_assert (alias || TREE_CODE (t) != VAR_DECL gcc_assert (alias || TREE_CODE (t) != VAR_DECL
|| varpool_get_node (t)->finalized); || varpool_get_node (t)->symbol.definition);
gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
|| (cgraph_get_node (t) || (cgraph_get_node (t)
&& cgraph_get_node (t)->analyzed)); && cgraph_get_node (t)->symbol.definition));
} }
/* Imitate what default_elf_asm_output_external do. /* Imitate what default_elf_asm_output_external do.

View File

@ -91,8 +91,8 @@ static void
lto_varpool_replace_node (struct varpool_node *vnode, lto_varpool_replace_node (struct varpool_node *vnode,
struct varpool_node *prevailing_node) struct varpool_node *prevailing_node)
{ {
gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition);
gcc_assert (!vnode->analyzed || prevailing_node->analyzed); gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed);
ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list); ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
@ -255,14 +255,7 @@ lto_symtab_resolve_can_prevail_p (symtab_node e)
if (DECL_EXTERNAL (e->symbol.decl)) if (DECL_EXTERNAL (e->symbol.decl))
return false; return false;
/* For functions we need a non-discarded body. */ return e->symbol.definition;
if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
return (cgraph (e)->analyzed);
else if (TREE_CODE (e->symbol.decl) == VAR_DECL)
return varpool (e)->finalized;
gcc_unreachable ();
} }
/* Resolve the symbol with the candidates in the chain *SLOT and store /* Resolve the symbol with the candidates in the chain *SLOT and store
@ -594,33 +587,33 @@ lto_symtab_merge_cgraph_nodes (void)
FOR_EACH_FUNCTION (cnode) FOR_EACH_FUNCTION (cnode)
{ {
/* Resolve weakrefs to symbol defined in other unit. */ /* Resolve weakrefs to symbol defined in other unit. */
if (!cnode->analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias)) if (!cnode->symbol.analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias))
{ {
symtab_node node = symtab_node_for_asm (cnode->thunk.alias); symtab_node node = symtab_node_for_asm (cnode->thunk.alias);
if (node && is_a <cgraph_node> (node)) if (node && is_a <cgraph_node> (node))
{ {
struct cgraph_node *n; struct cgraph_node *n;
for (n = cgraph (node); n && n->alias; for (n = cgraph (node); n && n->symbol.alias;
n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL) n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
if (n == cnode) if (n == cnode)
{ {
error ("function %q+D part of alias cycle", cnode->symbol.decl); error ("function %q+D part of alias cycle", cnode->symbol.decl);
cnode->alias = false; cnode->symbol.alias = false;
break; break;
} }
if (cnode->alias) if (cnode->symbol.alias)
{ {
cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl); cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl);
ipa_record_reference ((symtab_node)cnode, (symtab_node)node, ipa_record_reference ((symtab_node)cnode, (symtab_node)node,
IPA_REF_ALIAS, NULL); IPA_REF_ALIAS, NULL);
cnode->analyzed = true; cnode->symbol.analyzed = true;
} }
} }
else if (node) else if (node)
error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl); error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl);
} }
if ((cnode->thunk.thunk_p || cnode->alias) if ((cnode->thunk.thunk_p || cnode->symbol.alias)
&& cnode->thunk.alias && DECL_P (cnode->thunk.alias)) && cnode->thunk.alias && DECL_P (cnode->thunk.alias))
cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias); cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
cnode->symbol.aux = NULL; cnode->symbol.aux = NULL;
@ -628,33 +621,33 @@ lto_symtab_merge_cgraph_nodes (void)
FOR_EACH_VARIABLE (vnode) FOR_EACH_VARIABLE (vnode)
{ {
/* Resolve weakrefs to symbol defined in other unit. */ /* Resolve weakrefs to symbol defined in other unit. */
if (!vnode->analyzed && vnode->alias_of && !DECL_P (vnode->alias_of)) if (!vnode->symbol.analyzed && vnode->alias_of && !DECL_P (vnode->alias_of))
{ {
symtab_node node = symtab_node_for_asm (vnode->alias_of); symtab_node node = symtab_node_for_asm (vnode->alias_of);
if (node && is_a <cgraph_node> (node)) if (node && is_a <cgraph_node> (node))
{ {
struct varpool_node *n; struct varpool_node *n;
for (n = varpool (node); n && n->alias; for (n = varpool (node); n && n->symbol.alias;
n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
if (n == vnode) if (n == vnode)
{ {
error ("function %q+D part of alias cycle", vnode->symbol.decl); error ("function %q+D part of alias cycle", vnode->symbol.decl);
vnode->alias = false; vnode->symbol.alias = false;
break; break;
} }
if (vnode->alias) if (vnode->symbol.alias)
{ {
varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl); varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl);
ipa_record_reference ((symtab_node)vnode, (symtab_node)node, ipa_record_reference ((symtab_node)vnode, (symtab_node)node,
IPA_REF_ALIAS, NULL); IPA_REF_ALIAS, NULL);
vnode->analyzed = true; vnode->symbol.analyzed = true;
} }
} }
else if (node) else if (node)
error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl); error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl);
} }
if (vnode->alias_of) if (vnode->symbol.alias && DECL_P (vnode->alias_of))
vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of); vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
vnode->symbol.aux = NULL; vnode->symbol.aux = NULL;
} }

View File

@ -1,3 +1,9 @@
2013-05-29 Jan Hubicka <jh@suse.cz>
* lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab
flags.
* lto-partition.c (get_symbol_class, lto_balanced_map): Likewise.
2013-05-15 Jan Hubicka <jh@suse.cz> 2013-05-15 Jan Hubicka <jh@suse.cz>
* lto-partition.c (privatize_symbol_name): Return true when * lto-partition.c (privatize_symbol_name): Return true when

View File

@ -74,13 +74,13 @@ get_symbol_class (symtab_node node)
objects that can not be duplicated across partitions. */ objects that can not be duplicated across partitions. */
if (DECL_IN_CONSTANT_POOL (node->symbol.decl)) if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
return SYMBOL_DUPLICATE; return SYMBOL_DUPLICATE;
gcc_checking_assert (vnode->analyzed); gcc_checking_assert (vnode->symbol.definition);
} }
/* Functions that are cloned may stay in callgraph even if they are unused. /* Functions that are cloned may stay in callgraph even if they are unused.
Handle them as external; compute_ltrans_boundary take care to make Handle them as external; compute_ltrans_boundary take care to make
proper things to happen (i.e. to make them appear in the boundary but proper things to happen (i.e. to make them appear in the boundary but
with body streamed, so clone can me materialized). */ with body streamed, so clone can me materialized). */
else if (!cgraph (node)->analyzed) else if (!cgraph (node)->symbol.definition)
return SYMBOL_EXTERNAL; return SYMBOL_EXTERNAL;
/* Comdats are duplicated to every use unless they are keyed. /* Comdats are duplicated to every use unless they are keyed.
@ -561,12 +561,12 @@ lto_balanced_map (void)
last_visited_node++; last_visited_node++;
gcc_assert (node->analyzed gcc_assert (node->symbol.definition
|| lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))); || lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)));
/* Compute boundary cost of callgraph edges. */ /* Compute boundary cost of callgraph edges. */
for (edge = node->callees; edge; edge = edge->next_callee) for (edge = node->callees; edge; edge = edge->next_callee)
if (edge->callee->analyzed) if (edge->callee->symbol.definition)
{ {
int edge_cost = edge->frequency; int edge_cost = edge->frequency;
int index; int index;
@ -587,7 +587,7 @@ lto_balanced_map (void)
int edge_cost = edge->frequency; int edge_cost = edge->frequency;
int index; int index;
gcc_assert (edge->caller->analyzed); gcc_assert (edge->caller->symbol.definition);
if (!edge_cost) if (!edge_cost)
edge_cost = 1; edge_cost = 1;
gcc_assert (edge_cost > 0); gcc_assert (edge_cost > 0);
@ -614,7 +614,7 @@ lto_balanced_map (void)
int index; int index;
vnode = ipa_ref_varpool_node (ref); vnode = ipa_ref_varpool_node (ref);
if (!vnode->finalized) if (!vnode->symbol.definition)
continue; continue;
if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
&& get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
@ -632,7 +632,7 @@ lto_balanced_map (void)
int index; int index;
node = ipa_ref_node (ref); node = ipa_ref_node (ref);
if (!node->analyzed) if (!node->symbol.definition)
continue; continue;
index = lto_symtab_encoder_lookup (partition->encoder, index = lto_symtab_encoder_lookup (partition->encoder,
(symtab_node)node); (symtab_node)node);
@ -648,7 +648,7 @@ lto_balanced_map (void)
int index; int index;
vnode = ipa_ref_referring_varpool_node (ref); vnode = ipa_ref_referring_varpool_node (ref);
gcc_assert (vnode->finalized); gcc_assert (vnode->symbol.definition);
if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
&& get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
add_symbol_to_partition (partition, (symtab_node) vnode); add_symbol_to_partition (partition, (symtab_node) vnode);
@ -665,7 +665,7 @@ lto_balanced_map (void)
int index; int index;
node = ipa_ref_referring_node (ref); node = ipa_ref_referring_node (ref);
gcc_assert (node->analyzed); gcc_assert (node->symbol.definition);
index = lto_symtab_encoder_lookup (partition->encoder, index = lto_symtab_encoder_lookup (partition->encoder,
(symtab_node)node); (symtab_node)node);
if (index != LCC_NOT_FOUND if (index != LCC_NOT_FOUND

View File

@ -166,7 +166,7 @@ has_analyzed_clone_p (struct cgraph_node *node)
if (node) if (node)
while (node != orig) while (node != orig)
{ {
if (node->analyzed) if (node->symbol.analyzed)
return true; return true;
if (node->clones) if (node->clones)
node = node->clones; node = node->clones;
@ -196,7 +196,8 @@ lto_materialize_function (struct cgraph_node *node)
decl = node->symbol.decl; decl = node->symbol.decl;
/* Read in functions with body (analyzed nodes) /* Read in functions with body (analyzed nodes)
and also functions that are needed to produce virtual clones. */ and also functions that are needed to produce virtual clones. */
if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node)) if ((cgraph_function_with_gimple_body_p (node) && node->symbol.analyzed)
|| has_analyzed_clone_p (node))
{ {
/* Clones don't need to be read. */ /* Clones don't need to be read. */
if (node->clone_of) if (node->clone_of)

View File

@ -2492,12 +2492,12 @@ ipa_write_summaries (void)
renumber_gimple_stmt_uids (); renumber_gimple_stmt_uids ();
pop_cfun (); pop_cfun ();
} }
if (node->analyzed) if (node->symbol.definition)
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
} }
FOR_EACH_DEFINED_VARIABLE (vnode) FOR_EACH_DEFINED_VARIABLE (vnode)
if ((!vnode->alias || vnode->alias_of)) if ((!vnode->symbol.alias || vnode->alias_of))
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
ipa_write_summaries_1 (compute_ltrans_boundary (encoder)); ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
@ -2564,7 +2564,7 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
For functions newly born at WPA stage we need to initialize For functions newly born at WPA stage we need to initialize
the uids here. */ the uids here. */
if (node->analyzed if (node->symbol.definition
&& gimple_has_body_p (node->symbol.decl)) && gimple_has_body_p (node->symbol.decl))
{ {
push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));

View File

@ -473,9 +473,15 @@ dump_symtab_base (FILE *f, symtab_node node)
node->symbol.order, node->symbol.order,
symtab_node_name (node)); symtab_node_name (node));
dump_addr (f, " @", (void *)node); dump_addr (f, " @", (void *)node);
fprintf (f, "\n Type: %s\n", symtab_type_names[node->symbol.type]); fprintf (f, "\n Type: %s", symtab_type_names[node->symbol.type]);
fprintf (f, " Visibility:");
if (node->symbol.definition)
fprintf (f, " definition");
if (node->symbol.analyzed)
fprintf (f, " analyzed");
if (node->symbol.alias)
fprintf (f, " alias");
fprintf (f, "\n Visibility:");
if (node->symbol.in_other_partition) if (node->symbol.in_other_partition)
fprintf (f, " in_other_partition"); fprintf (f, " in_other_partition");
if (node->symbol.used_from_other_partition) if (node->symbol.used_from_other_partition)
@ -653,6 +659,12 @@ verify_symtab_base (symtab_node node)
&& node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node) && node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node)
{ {
error ("double linked list of assembler names corrupted"); error ("double linked list of assembler names corrupted");
error_found = true;
}
if (node->symbol.analyzed && !node->symbol.definition)
{
error ("node is analyzed byt it is not a definition");
error_found = true;
} }
if (node->symbol.same_comdat_group) if (node->symbol.same_comdat_group)
{ {
@ -783,4 +795,40 @@ symtab_make_decl_local (tree decl)
SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl); SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
} }
/* Given NODE, walk the alias chain to return the symbol NODE is alias of.
If NODE is not an alias, return NODE.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
symtab_node
symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
{
if (availability)
{
if (is_a <cgraph_node> (node))
*availability = cgraph_function_body_availability (cgraph (node));
else
*availability = cgraph_variable_initializer_availability (varpool (node));
}
while (node)
{
if (node->symbol.alias && node->symbol.analyzed)
node = symtab_alias_target (node);
else
return node;
if (node && availability)
{
enum availability a;
if (is_a <cgraph_node> (node))
a = cgraph_function_body_availability (cgraph (node));
else
a = cgraph_variable_initializer_availability (varpool (node));
if (a < *availability)
*availability = a;
}
}
if (availability)
*availability = AVAIL_NOT_AVAILABLE;
return NULL;
}
#include "gt-symtab.h" #include "gt-symtab.h"

View File

@ -393,15 +393,15 @@ wrapup_global_declaration_2 (tree decl)
if (!node && flag_ltrans) if (!node && flag_ltrans)
needed = false; needed = false;
else if (node && node->finalized) else if (node && node->symbol.definition)
needed = false; needed = false;
else if (node && node->alias) else if (node && node->symbol.alias)
needed = false; needed = false;
else if (!cgraph_global_info_ready else if (!cgraph_global_info_ready
&& (TREE_USED (decl) && (TREE_USED (decl)
|| TREE_USED (DECL_ASSEMBLER_NAME (decl)))) || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
/* needed */; /* needed */;
else if (node && node->analyzed) else if (node && node->symbol.analyzed)
/* needed */; /* needed */;
else if (DECL_COMDAT (decl)) else if (DECL_COMDAT (decl))
needed = false; needed = false;

View File

@ -3932,7 +3932,7 @@ get_cg_data (struct cgraph_node **node, bool traverse_aliases)
{ {
struct tm_ipa_cg_data *d; struct tm_ipa_cg_data *d;
if (traverse_aliases && (*node)->alias) if (traverse_aliases && (*node)->symbol.alias)
*node = cgraph_get_node ((*node)->thunk.alias); *node = cgraph_get_node ((*node)->thunk.alias);
d = (struct tm_ipa_cg_data *) (*node)->symbol.aux; d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
@ -4518,7 +4518,7 @@ ipa_tm_mayenterirr_function (struct cgraph_node *node)
/* Recurse on the main body for aliases. In general, this will /* Recurse on the main body for aliases. In general, this will
result in one of the bits above being set so that we will not result in one of the bits above being set so that we will not
have to recurse next time. */ have to recurse next time. */
if (node->alias) if (node->symbol.alias)
return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias)); return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
/* What remains is unmarked local functions without items that force /* What remains is unmarked local functions without items that force
@ -4678,9 +4678,7 @@ static inline void
ipa_tm_mark_force_output_node (struct cgraph_node *node) ipa_tm_mark_force_output_node (struct cgraph_node *node)
{ {
cgraph_mark_force_output_node (node); cgraph_mark_force_output_node (node);
/* ??? function_and_variable_visibility will reset node->symbol.analyzed = true;
the needed bit, without actually checking. */
node->analyzed = 1;
} }
/* Callback data for ipa_tm_create_version_alias. */ /* Callback data for ipa_tm_create_version_alias. */
@ -5250,7 +5248,7 @@ ipa_tm_execute (void)
{ {
/* If this is an alias, make sure its base is queued as well. /* If this is an alias, make sure its base is queued as well.
we need not scan the callees now, as the base will do. */ we need not scan the callees now, as the base will do. */
if (node->alias) if (node->symbol.alias)
{ {
node = cgraph_get_node (node->thunk.alias); node = cgraph_get_node (node->thunk.alias);
d = get_cg_data (&node, true); d = get_cg_data (&node, true);
@ -5393,7 +5391,7 @@ ipa_tm_execute (void)
for (i = 0; i < tm_callees.length (); ++i) for (i = 0; i < tm_callees.length (); ++i)
{ {
node = tm_callees[i]; node = tm_callees[i];
if (node->analyzed) if (node->symbol.analyzed)
{ {
d = get_cg_data (&node, true); d = get_cg_data (&node, true);
if (d->clone) if (d->clone)

View File

@ -2580,7 +2580,7 @@ tree_could_trap_p (tree expr)
/* Assume that accesses to weak functions may trap, unless we know /* Assume that accesses to weak functions may trap, unless we know
they are certainly defined in current TU or in some other they are certainly defined in current TU or in some other
LTO partition. */ LTO partition. */
if (DECL_WEAK (expr)) if (DECL_WEAK (expr) && !DECL_COMDAT (expr))
{ {
struct cgraph_node *node; struct cgraph_node *node;
if (!DECL_EXTERNAL (expr)) if (!DECL_EXTERNAL (expr))
@ -2596,7 +2596,7 @@ tree_could_trap_p (tree expr)
/* Assume that accesses to weak vars may trap, unless we know /* Assume that accesses to weak vars may trap, unless we know
they are certainly defined in current TU or in some other they are certainly defined in current TU or in some other
LTO partition. */ LTO partition. */
if (DECL_WEAK (expr)) if (DECL_WEAK (expr) && !DECL_COMDAT (expr))
{ {
struct varpool_node *node; struct varpool_node *node;
if (!DECL_EXTERNAL (expr)) if (!DECL_EXTERNAL (expr))

View File

@ -704,15 +704,15 @@ create_emultls_var (struct varpool_node *var, void *data)
cvar = varpool_get_node (cdecl); cvar = varpool_get_node (cdecl);
control_vars.quick_push (cvar); control_vars.quick_push (cvar);
if (!var->alias) if (!var->symbol.alias)
{ {
/* Make sure the COMMON block control variable gets initialized. /* Make sure the COMMON block control variable gets initialized.
Note that there's no point in doing this for aliases; we only Note that there's no point in doing this for aliases; we only
need to do this once for the main variable. */ need to do this once for the main variable. */
emutls_common_1 (var->symbol.decl, cdecl, (tree *)data); emutls_common_1 (var->symbol.decl, cdecl, (tree *)data);
} }
if (var->alias && !var->alias_of) if (var->symbol.alias && !var->alias_of)
cvar->alias = true; cvar->symbol.alias = true;
/* Indicate that the value of the TLS variable may be found elsewhere, /* Indicate that the value of the TLS variable may be found elsewhere,
preventing the variable from re-appearing in the GIMPLE. We cheat preventing the variable from re-appearing in the GIMPLE. We cheat
@ -743,7 +743,7 @@ ipa_lower_emutls (void)
gcc_checking_assert (TREE_STATIC (var->symbol.decl) gcc_checking_assert (TREE_STATIC (var->symbol.decl)
|| DECL_EXTERNAL (var->symbol.decl)); || DECL_EXTERNAL (var->symbol.decl));
varpool_node_set_add (tls_vars, var); varpool_node_set_add (tls_vars, var);
if (var->alias && var->analyzed) if (var->symbol.alias && var->symbol.definition)
varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL)); varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL));
} }
@ -767,9 +767,9 @@ ipa_lower_emutls (void)
{ {
var = tls_vars->nodes[i]; var = tls_vars->nodes[i];
if (var->alias && !var->alias_of) if (var->symbol.alias && !var->alias_of)
any_aliases = true; any_aliases = true;
else if (!var->alias) else if (!var->symbol.alias)
varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true); varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true);
} }

View File

@ -1726,7 +1726,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
if ((!edge if ((!edge
|| (edge->indirect_inlining_edge || (edge->indirect_inlining_edge
&& id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)) && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
&& id->dst_node->analyzed && id->dst_node->symbol.definition
&& (fn = gimple_call_fndecl (stmt)) != NULL) && (fn = gimple_call_fndecl (stmt)) != NULL)
{ {
struct cgraph_node *dest = cgraph_get_node (fn); struct cgraph_node *dest = cgraph_get_node (fn);
@ -1737,10 +1737,10 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
producing dead clone (for further cloning). In all producing dead clone (for further cloning). In all
other cases we hit a bug (incorrect node sharing is the other cases we hit a bug (incorrect node sharing is the
most common reason for missing edges). */ most common reason for missing edges). */
gcc_assert (!dest->analyzed gcc_assert (!dest->symbol.definition
|| dest->symbol.address_taken || dest->symbol.address_taken
|| !id->src_node->analyzed || !id->src_node->symbol.definition
|| !id->dst_node->analyzed); || !id->dst_node->symbol.definition);
if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES) if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
cgraph_create_edge_including_clones cgraph_create_edge_including_clones
(id->dst_node, dest, orig_stmt, stmt, bb->count, (id->dst_node, dest, orig_stmt, stmt, bb->count,
@ -3611,7 +3611,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
/* Do not special case builtins where we see the body. /* Do not special case builtins where we see the body.
This just confuse inliner. */ This just confuse inliner. */
if (!decl || !(node = cgraph_get_node (decl)) || node->analyzed) if (!decl || !(node = cgraph_get_node (decl)) || node->symbol.definition)
; ;
/* For buitins that are likely expanded to nothing or /* For buitins that are likely expanded to nothing or
inlined do not account operand costs. */ inlined do not account operand costs. */
@ -4344,7 +4344,7 @@ optimize_inline_calls (tree fn)
memset (&id, 0, sizeof (id)); memset (&id, 0, sizeof (id));
id.src_node = id.dst_node = cgraph_get_node (fn); id.src_node = id.dst_node = cgraph_get_node (fn);
gcc_assert (id.dst_node->analyzed); gcc_assert (id.dst_node->symbol.definition);
id.dst_fn = fn; id.dst_fn = fn;
/* Or any functions that aren't finished yet. */ /* Or any functions that aren't finished yet. */
if (current_function_decl) if (current_function_decl)
@ -5238,7 +5238,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
pointer_set_destroy (id.statements_to_fold); pointer_set_destroy (id.statements_to_fold);
fold_cond_expr_cond (); fold_cond_expr_cond ();
delete_unreachable_blocks_update_callgraph (&id); delete_unreachable_blocks_update_callgraph (&id);
if (id.dst_node->analyzed) if (id.dst_node->symbol.definition)
cgraph_rebuild_references (); cgraph_rebuild_references ();
update_ssa (TODO_update_ssa); update_ssa (TODO_update_ssa);

View File

@ -2874,7 +2874,7 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p)
&& (TREE_STATIC (t) || DECL_EXTERNAL (t))) && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
{ {
struct varpool_node *node = varpool_get_node (t); struct varpool_node *node = varpool_get_node (t);
if (node && node->alias) if (node && node->symbol.alias && node->symbol.analyzed)
{ {
node = varpool_variable_node (node, NULL); node = varpool_variable_node (node, NULL);
t = node->symbol.decl; t = node->symbol.decl;
@ -5751,7 +5751,7 @@ create_variable_info_for (tree decl, const char *name)
/* If this is a global variable with an initializer and we are in /* If this is a global variable with an initializer and we are in
IPA mode generate constraints for it. */ IPA mode generate constraints for it. */
if (DECL_INITIAL (decl) if (DECL_INITIAL (decl)
&& vnode->analyzed) && vnode->symbol.definition)
{ {
vec<ce_s> rhsc = vNULL; vec<ce_s> rhsc = vNULL;
struct constraint_expr lhs, *rhsp; struct constraint_expr lhs, *rhsp;
@ -7023,7 +7023,8 @@ struct pt_solution ipa_escaped_pt
static bool static bool
associate_varinfo_to_alias (struct cgraph_node *node, void *data) associate_varinfo_to_alias (struct cgraph_node *node, void *data)
{ {
if (node->alias || node->thunk.thunk_p) if ((node->symbol.alias || node->thunk.thunk_p)
&& node->symbol.analyzed)
insert_vi_for_tree (node->symbol.decl, (varinfo_t)data); insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
return false; return false;
} }
@ -7066,7 +7067,7 @@ ipa_pta_execute (void)
/* Create constraints for global variables and their initializers. */ /* Create constraints for global variables and their initializers. */
FOR_EACH_VARIABLE (var) FOR_EACH_VARIABLE (var)
{ {
if (var->alias) if (var->symbol.alias && var->symbol.analyzed)
continue; continue;
get_vi_for_tree (var->symbol.decl); get_vi_for_tree (var->symbol.decl);

View File

@ -2256,7 +2256,7 @@ mark_decl_referenced (tree decl)
definition. */ definition. */
struct cgraph_node *node = cgraph_get_create_node (decl); struct cgraph_node *node = cgraph_get_create_node (decl);
if (!DECL_EXTERNAL (decl) if (!DECL_EXTERNAL (decl)
&& !node->local.finalized) && !node->symbol.definition)
cgraph_mark_force_output_node (node); cgraph_mark_force_output_node (node);
} }
else if (TREE_CODE (decl) == VAR_DECL) else if (TREE_CODE (decl) == VAR_DECL)
@ -5595,9 +5595,9 @@ assemble_alias (tree decl, tree target)
/* Allow aliases to aliases. */ /* Allow aliases to aliases. */
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
cgraph_get_create_node (decl)->alias = true; cgraph_get_create_node (decl)->symbol.alias = true;
else else
varpool_node_for_decl (decl)->alias = true; varpool_node_for_decl (decl)->symbol.alias = true;
/* If the target has already been emitted, we don't have to queue the /* If the target has already been emitted, we don't have to queue the
alias. This saves a tad of memory. */ alias. This saves a tad of memory. */
@ -5700,12 +5700,12 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
TM_GETTMCLONE. If neither of these are true, we didn't generate 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 a clone, and we didn't call it indirectly... no sense keeping it
in the clone table. */ in the clone table. */
if (!dst_n || !dst_n->analyzed) if (!dst_n || !dst_n->symbol.definition)
continue; continue;
/* This covers the case where we have optimized the original /* This covers the case where we have optimized the original
function away, and only access the transactional clone. */ function away, and only access the transactional clone. */
if (!src_n || !src_n->analyzed) if (!src_n || !src_n->symbol.definition)
continue; continue;
if (!switched) if (!switched)

View File

@ -58,6 +58,19 @@ void
varpool_remove_node (struct varpool_node *node) varpool_remove_node (struct varpool_node *node)
{ {
symtab_unregister_node ((symtab_node)node); symtab_unregister_node ((symtab_node)node);
/* Because we remove references from external functions before final compilation,
we may end up removing useful constructors.
FIXME: We probably want to trace boundaries better. */
if (!const_value_known_p (node->symbol.decl))
varpool_remove_initializer (node);
ggc_free (node);
}
/* Renove node initializer when it is no longer needed. */
void
varpool_remove_initializer (struct varpool_node *node)
{
if (DECL_INITIAL (node->symbol.decl) if (DECL_INITIAL (node->symbol.decl)
&& !DECL_IN_CONSTANT_POOL (node->symbol.decl) && !DECL_IN_CONSTANT_POOL (node->symbol.decl)
/* Keep vtables for BINFO folding. */ /* Keep vtables for BINFO folding. */
@ -65,7 +78,6 @@ varpool_remove_node (struct varpool_node *node)
/* FIXME: http://gcc.gnu.org/PR55395 */ /* FIXME: http://gcc.gnu.org/PR55395 */
&& debug_info_level == DINFO_LEVEL_NONE) && debug_info_level == DINFO_LEVEL_NONE)
DECL_INITIAL (node->symbol.decl) = error_mark_node; DECL_INITIAL (node->symbol.decl) = error_mark_node;
ggc_free (node);
} }
/* Dump given cgraph node. */ /* Dump given cgraph node. */
@ -80,10 +92,6 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
fprintf (f, " Varpool flags:"); fprintf (f, " Varpool flags:");
if (DECL_INITIAL (node->symbol.decl)) if (DECL_INITIAL (node->symbol.decl))
fprintf (f, " initialized"); fprintf (f, " initialized");
if (node->analyzed)
fprintf (f, " analyzed");
if (node->finalized)
fprintf (f, " finalized");
if (node->output) if (node->output)
fprintf (f, " output"); fprintf (f, " output");
if (TREE_READONLY (node->symbol.decl)) if (TREE_READONLY (node->symbol.decl))
@ -117,8 +125,8 @@ struct varpool_node *
varpool_node_for_asm (tree asmname) varpool_node_for_asm (tree asmname)
{ {
if (symtab_node node = symtab_node_for_asm (asmname)) if (symtab_node node = symtab_node_for_asm (asmname))
if (varpool_node *vnode = dyn_cast <varpool_node> (node)) return dyn_cast <varpool_node> (node);
return vnode; else
return NULL; return NULL;
} }
@ -205,12 +213,12 @@ enum availability
cgraph_variable_initializer_availability (struct varpool_node *node) cgraph_variable_initializer_availability (struct varpool_node *node)
{ {
gcc_assert (cgraph_function_flags_ready); gcc_assert (cgraph_function_flags_ready);
if (!node->finalized) if (!node->symbol.definition)
return AVAIL_NOT_AVAILABLE; return AVAIL_NOT_AVAILABLE;
if (!TREE_PUBLIC (node->symbol.decl)) if (!TREE_PUBLIC (node->symbol.decl))
return AVAIL_AVAILABLE; return AVAIL_AVAILABLE;
/* If the variable can be overwritten, return OVERWRITABLE. Takes /* If the variable can be overwritten, return OVERWRITABLE. Takes
care of at least two notable extensions - the COMDAT variables care of at least one notable extension - the COMDAT variables
used to share template instantiations in C++. */ used to share template instantiations in C++. */
if (!decl_replaceable_p (node->symbol.decl)) if (!decl_replaceable_p (node->symbol.decl))
return AVAIL_OVERWRITABLE; return AVAIL_OVERWRITABLE;
@ -225,24 +233,24 @@ varpool_analyze_node (struct varpool_node *node)
/* When reading back varpool at LTO time, we re-construct the queue in order /* When reading back varpool at LTO time, we re-construct the queue in order
to have "needed" list right by inserting all needed nodes into varpool. to have "needed" list right by inserting all needed nodes into varpool.
We however don't want to re-analyze already analyzed nodes. */ We however don't want to re-analyze already analyzed nodes. */
if (!node->analyzed) if (!node->symbol.analyzed)
{ {
gcc_assert (!in_lto_p || cgraph_function_flags_ready); gcc_assert (!in_lto_p || cgraph_function_flags_ready);
/* Compute the alignment early so function body expanders are /* Compute the alignment early so function body expanders are
already informed about increased alignment. */ already informed about increased alignment. */
align_variable (decl, 0); align_variable (decl, 0);
} }
if (node->alias && node->alias_of) if (node->symbol.alias && node->alias_of)
{ {
struct varpool_node *tgt = varpool_node_for_decl (node->alias_of); struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
struct varpool_node *n; struct varpool_node *n;
for (n = tgt; n && n->alias; for (n = tgt; n && n->symbol.alias;
n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
if (n == node) if (n == node)
{ {
error ("variable %q+D part of alias cycle", node->symbol.decl); error ("variable %q+D part of alias cycle", node->symbol.decl);
node->alias = false; node->symbol.alias = false;
continue; continue;
} }
if (!vec_safe_length (node->symbol.ref_list.references)) if (!vec_safe_length (node->symbol.ref_list.references))
@ -257,8 +265,8 @@ varpool_analyze_node (struct varpool_node *node)
} }
} }
else if (DECL_INITIAL (decl)) else if (DECL_INITIAL (decl))
record_references_in_initializer (decl, node->analyzed); record_references_in_initializer (decl, node->symbol.analyzed);
node->analyzed = true; node->symbol.analyzed = true;
} }
/* Assemble thunks and aliases associated to NODE. */ /* Assemble thunks and aliases associated to NODE. */
@ -287,7 +295,7 @@ varpool_assemble_decl (struct varpool_node *node)
/* Aliases are outout when their target is produced or by /* Aliases are outout when their target is produced or by
output_weakrefs. */ output_weakrefs. */
if (node->alias) if (node->symbol.alias)
return false; return false;
/* Constant pool is output from RTL land when the reference /* Constant pool is output from RTL land when the reference
@ -316,7 +324,7 @@ varpool_assemble_decl (struct varpool_node *node)
{ {
assemble_variable (decl, 0, 1, 0); assemble_variable (decl, 0, 1, 0);
gcc_assert (TREE_ASM_WRITTEN (decl)); gcc_assert (TREE_ASM_WRITTEN (decl));
node->finalized = 1; node->symbol.definition = true;
assemble_aliases (node); assemble_aliases (node);
return true; return true;
} }
@ -357,7 +365,7 @@ varpool_remove_unreferenced_decls (void)
fprintf (cgraph_dump_file, "Trivially needed variables:"); fprintf (cgraph_dump_file, "Trivially needed variables:");
FOR_EACH_DEFINED_VARIABLE (node) FOR_EACH_DEFINED_VARIABLE (node)
{ {
if (node->analyzed if (node->symbol.analyzed
&& (!varpool_can_remove_if_no_refs (node) && (!varpool_can_remove_if_no_refs (node)
/* We just expanded all function bodies. See if any of /* We just expanded all function bodies. See if any of
them needed the variable. */ them needed the variable. */
@ -381,7 +389,7 @@ varpool_remove_unreferenced_decls (void)
next = next->symbol.same_comdat_group) next = next->symbol.same_comdat_group)
{ {
varpool_node *vnext = dyn_cast <varpool_node> (next); varpool_node *vnext = dyn_cast <varpool_node> (next);
if (vnext && vnext->analyzed) if (vnext && vnext->symbol.analyzed)
enqueue_node (vnext, &first); enqueue_node (vnext, &first);
} }
} }
@ -390,8 +398,8 @@ varpool_remove_unreferenced_decls (void)
varpool_node *vnode = dyn_cast <varpool_node> (ref->referred); varpool_node *vnode = dyn_cast <varpool_node> (ref->referred);
if (vnode if (vnode
&& (!DECL_EXTERNAL (ref->referred->symbol.decl) && (!DECL_EXTERNAL (ref->referred->symbol.decl)
|| vnode->alias) || vnode->symbol.alias)
&& vnode->analyzed) && vnode->symbol.analyzed)
enqueue_node (vnode, &first); enqueue_node (vnode, &first);
} }
} }
@ -419,7 +427,7 @@ void
varpool_finalize_named_section_flags (struct varpool_node *node) varpool_finalize_named_section_flags (struct varpool_node *node)
{ {
if (!TREE_ASM_WRITTEN (node->symbol.decl) if (!TREE_ASM_WRITTEN (node->symbol.decl)
&& !node->alias && !node->symbol.alias
&& !node->symbol.in_other_partition && !node->symbol.in_other_partition
&& !DECL_EXTERNAL (node->symbol.decl) && !DECL_EXTERNAL (node->symbol.decl)
&& TREE_CODE (node->symbol.decl) == VAR_DECL && TREE_CODE (node->symbol.decl) == VAR_DECL
@ -484,8 +492,8 @@ varpool_create_variable_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (decl) == VAR_DECL);
gcc_assert (TREE_CODE (alias) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL);
alias_node = varpool_node_for_decl (alias); alias_node = varpool_node_for_decl (alias);
alias_node->alias = 1; alias_node->symbol.alias = true;
alias_node->finalized = 1; alias_node->symbol.definition = true;
alias_node->alias_of = decl; alias_node->alias_of = decl;
/* Extra name alias mechanizm creates aliases really late /* Extra name alias mechanizm creates aliases really late