diff options
author | Jan Hubicka <jh@suse.cz> | 2012-04-22 23:28:07 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2012-04-22 21:28:07 +0000 |
commit | 660584689a4397f18cda03b458703bbbf909dd12 (patch) | |
tree | a4cd93cef18f73580dc0226c3ce10cbae70f9f08 | |
parent | f04e40afc115bcf2143f541baa9e4cccef19922a (diff) | |
download | gcc-660584689a4397f18cda03b458703bbbf909dd12.zip gcc-660584689a4397f18cda03b458703bbbf909dd12.tar.gz gcc-660584689a4397f18cda03b458703bbbf909dd12.tar.bz2 |
lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags.
* lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags.
* cgraphbuild.c (record_reference, record_type_list, mark_address,
mark_load, mark_store): Do not mark varpool nodes as needed.
* cgraph.c (cgraph_new_nodes): Remove.
(cgraph_create_function_alias): Do not mark nodes as reachable.
(cgraph_add_thunk): Likewise.
(cgraph_mark_reachable_node): Do not manage the queue.
* cgraph.h (cgraph_node): Remove next_needed.
(varpool_nodes_queue): Remove next_needed and prev_needed.
(x_cgraph_nodes_queue, x_cgraph_nodes_queue, cgraph_new_nodes): Remove.
(cgraph_new_nodes): Declare.
(x_varpool_nodes_queue, varpool_nodes_queue); Remove.
(varpool_analyze_pending_decls): Remove.
(varpool_analyze_node): New.
(varpool_mark_needed_node): Remove.
(varpool_first_variable, varpool_next_variable): New inlines.
(varpool_first_static_initializer, varpool_next_static_initializer): Update.
(FOR_EACH_STATIC_VARIABLE): Remove unused walker.
(varpool_first_defined_variable): New inline.
(varpool_next_defined_variable): New inline
(FOR_EACH_VARIABLE): Reimplement.
(FOR_EACH_DEFINED_VARIABLE): Reimplement.
* toplev.c (wrapup_global_declaration_2): Use analyzed instead of
needed flag.
* cgraphunit.c (cgraph_new_nodes): Declare here.
(enqueue_node): New function.
(cgraph_process_new_functions): update for new
node set; when constructing cgraph enqueue node for processing.
(cgraph_add_new_function): Use new node set.
(process_function_and_variable_attributes): Do not set varpool needed
flags.
(referred_to_p): New function.
(varpool_finalize_decl): Move here from varpool.c; enqueue needed node
when varpool is in construction.
(cgraph_analyze_functions): Rewrite.
(cgraph_expand_all_functions): Update.
(cgraph_output_in_order): Do not analyze pending decls; do not set needed flags.
(cgraph_optimize): Do not analyze pending decls.
* lto-cgraph.c (input_varpool_node): Clear analyzed flag for objects in other
partition; do not mark node as needed.
* dwarf2out.c (reference_to_unused): Use analyzed flag.
(premark_types_used_by_global_vars_helper): Likewise.
* ipa.c (process_references): Do not call varpool_mark_needed_node.
(cgraph_remove_unreachable_nodes): Do not rely on varpool and
cgrpah queues.
(function_and_variable_visibility): Do not mark node as needed.
(whole_program_function_and_variable_visibility): Likewise.
* Makefile.in (gt-varpool.h): No longer needed.
* passes.c (execute_one_pass, execute_ipa_pass_list): Update.
(ipa_write_summaries): Do not use needed flag.
* varpool.c: Do not include gt-varpool.h
(x_varpool_nodes_queue, x_varpool_last_needed_node,
x_varpool_last_needed_node, x_varpool_first_unanalyzed_node,
x_varpool_first_unanalyzed_node, varpool_assembled_nodes_queue):
Remove.
(varpool_remove_node): Do not update the lists.
(dump_varpool_node): Do not dump needed flag.
(varpool_enqueue_needed_node): Remove.
(varpool_mark_needed_node): Remove.
(varpool_reset_queue): Remove.
(varpool_finalize_decl): Move to cgraphunit.c
(varpool_analyze_node): New functions based on former
varpool_analyze_pending_decls.
(varpool_analyze_pending_decls): Remove.
(varpool_assemble_decl): Do not update the lists.
(enqueue_node): New function.
(varpool_remove_unreferenced_decls): Rewrite.
(varpool_empty_needed_queue): Remove.
(add_new_static_var): Do not mark node as needed.
(varpool_create_variable_alias): Handle expansion state
creation.
* except.c (output_ttype): Do not mark node as needed.
* varasm.c (mark_decl_referenced): Do not use mark_needed_node.
* tree-profile.c (init_ic_make_global_vars, init_ic_make_global_vars):
Likewise.
* tree-switch-conversion.c (build_one_array): Likewise.
* class.c (build_utf8_ref): Do not mark varpool node as needed.
* gcc-interface/utils.c (gnat_write_global_declarations): Do not mark
needed node.
* lto-partition.c (partition_varpool_node_p): Do not use needed flag.
* decl2.c (maybe_make_one_only): Mark keyed COMDATs as USED so they
gets finalized.
From-SVN: r186687
-rw-r--r-- | gcc/ChangeLog | 79 | ||||
-rw-r--r-- | gcc/Makefile.in | 3 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 1 | ||||
-rw-r--r-- | gcc/cgraph.c | 25 | ||||
-rw-r--r-- | gcc/cgraph.h | 97 | ||||
-rw-r--r-- | gcc/cgraphbuild.c | 5 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 365 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 1 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 4 | ||||
-rw-r--r-- | gcc/except.c | 9 | ||||
-rw-r--r-- | gcc/ipa.c | 31 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/java/class.c | 1 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 7 | ||||
-rw-r--r-- | gcc/lto-symtab.c | 6 | ||||
-rw-r--r-- | gcc/lto/lto-partition.c | 2 | ||||
-rw-r--r-- | gcc/passes.c | 4 | ||||
-rw-r--r-- | gcc/symtab.c | 5 | ||||
-rw-r--r-- | gcc/toplev.c | 3 | ||||
-rw-r--r-- | gcc/tree-profile.c | 2 | ||||
-rw-r--r-- | gcc/tree-switch-conversion.c | 1 | ||||
-rw-r--r-- | gcc/varasm.c | 1 | ||||
-rw-r--r-- | gcc/varpool.c | 393 |
25 files changed, 524 insertions, 535 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1e80ca5..88968a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,82 @@ +2012-04-22 Jan Hubicka <jh@suse.cz> + + * lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags. + * cgraphbuild.c (record_reference, record_type_list, mark_address, + mark_load, mark_store): Do not mark varpool nodes as needed. + * cgraph.c (cgraph_new_nodes): Remove. + (cgraph_create_function_alias): Do not mark nodes as reachable. + (cgraph_add_thunk): Likewise. + (cgraph_mark_reachable_node): Do not manage the queue. + * cgraph.h (cgraph_node): Remove next_needed. + (varpool_nodes_queue): Remove next_needed and prev_needed. + (x_cgraph_nodes_queue, x_cgraph_nodes_queue, cgraph_new_nodes): Remove. + (cgraph_new_nodes): Declare. + (x_varpool_nodes_queue, varpool_nodes_queue); Remove. + (varpool_analyze_pending_decls): Remove. + (varpool_analyze_node): New. + (varpool_mark_needed_node): Remove. + (varpool_first_variable, varpool_next_variable): New inlines. + (varpool_first_static_initializer, varpool_next_static_initializer): Update. + (FOR_EACH_STATIC_VARIABLE): Remove unused walker. + (varpool_first_defined_variable): New inline. + (varpool_next_defined_variable): New inline + (FOR_EACH_VARIABLE): Reimplement. + (FOR_EACH_DEFINED_VARIABLE): Reimplement. + * toplev.c (wrapup_global_declaration_2): Use analyzed instead of + needed flag. + * cgraphunit.c (cgraph_new_nodes): Declare here. + (enqueue_node): New function. + (cgraph_process_new_functions): update for new + node set; when constructing cgraph enqueue node for processing. + (cgraph_add_new_function): Use new node set. + (process_function_and_variable_attributes): Do not set varpool needed + flags. + (referred_to_p): New function. + (varpool_finalize_decl): Move here from varpool.c; enqueue needed node + when varpool is in construction. + (cgraph_analyze_functions): Rewrite. + (cgraph_expand_all_functions): Update. + (cgraph_output_in_order): Do not analyze pending decls; do not set needed flags. + (cgraph_optimize): Do not analyze pending decls. + * lto-cgraph.c (input_varpool_node): Clear analyzed flag for objects in other + partition; do not mark node as needed. + * dwarf2out.c (reference_to_unused): Use analyzed flag. + (premark_types_used_by_global_vars_helper): Likewise. + * ipa.c (process_references): Do not call varpool_mark_needed_node. + (cgraph_remove_unreachable_nodes): Do not rely on varpool and + cgrpah queues. + (function_and_variable_visibility): Do not mark node as needed. + (whole_program_function_and_variable_visibility): Likewise. + * Makefile.in (gt-varpool.h): No longer needed. + * passes.c (execute_one_pass, execute_ipa_pass_list): Update. + (ipa_write_summaries): Do not use needed flag. + * varpool.c: Do not include gt-varpool.h + (x_varpool_nodes_queue, x_varpool_last_needed_node, + x_varpool_last_needed_node, x_varpool_first_unanalyzed_node, + x_varpool_first_unanalyzed_node, varpool_assembled_nodes_queue): + Remove. + (varpool_remove_node): Do not update the lists. + (dump_varpool_node): Do not dump needed flag. + (varpool_enqueue_needed_node): Remove. + (varpool_mark_needed_node): Remove. + (varpool_reset_queue): Remove. + (varpool_finalize_decl): Move to cgraphunit.c + (varpool_analyze_node): New functions based on former + varpool_analyze_pending_decls. + (varpool_analyze_pending_decls): Remove. + (varpool_assemble_decl): Do not update the lists. + (enqueue_node): New function. + (varpool_remove_unreferenced_decls): Rewrite. + (varpool_empty_needed_queue): Remove. + (add_new_static_var): Do not mark node as needed. + (varpool_create_variable_alias): Handle expansion state + creation. + * except.c (output_ttype): Do not mark node as needed. + * varasm.c (mark_decl_referenced): Do not use mark_needed_node. + * tree-profile.c (init_ic_make_global_vars, init_ic_make_global_vars): + Likewise. + * tree-switch-conversion.c (build_one_array): Likewise. + 2012-04-22 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c/44774 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 0070cea..97c8973 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2934,7 +2934,7 @@ cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) \ $(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \ - $(TREE_FLOW_H) gt-varpool.h + $(TREE_FLOW_H) ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) \ $(TREE_PASS_H) $(TIMEVAR_H) $(GIMPLE_H) $(GGC_H) pointer-set.h \ $(IPA_UTILS_H) @@ -3719,7 +3719,6 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/tree-scalar-evolution.c \ $(srcdir)/tree-ssa-operands.h \ $(srcdir)/tree-profile.c $(srcdir)/tree-nested.c \ - $(srcdir)/varpool.c \ $(srcdir)/tree-parloops.c \ $(srcdir)/omp-low.c \ $(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c $(srcdir)/cgraphunit.c \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8fd284a..3414491 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2012-04-22 Jan Hubicka <jh@suse.cz> + + * gcc-interface/utils.c (gnat_write_global_declarations): Do not mark + needed node. + 2012-04-20 Jan Hubicka <jh@suse.cz> * gcc-interface/utils.c (gnat_write_global_declarations): Update for new diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index e95e967..41f83bf 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -4860,7 +4860,6 @@ gnat_write_global_declarations (void) TREE_ASM_WRITTEN (dummy_global) = 1; node = varpool_node (dummy_global); node->symbol.force_output = 1; - varpool_mark_needed_node (node); while (!VEC_empty (tree, types_used_by_cur_var_decl)) { diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 4588249..ed4cdf6 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -123,11 +123,6 @@ static inline void cgraph_edge_remove_callee (struct cgraph_edge *e); symtab_node x_cgraph_nodes_queue; #define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue) -/* Queue of cgraph nodes scheduled to be added into cgraph. This is a - secondary queue used during optimization to accommodate passes that - may generate new functions that need to be optimized and expanded. */ -struct cgraph_node *cgraph_new_nodes; - /* Number of nodes in existence. */ int cgraph_n_nodes; @@ -141,7 +136,7 @@ int cgraph_edge_max_uid; bool cgraph_global_info_ready = false; /* What state callgraph is in right now. */ -enum cgraph_state cgraph_state = CGRAPH_STATE_CONSTRUCTION; +enum cgraph_state cgraph_state = CGRAPH_STATE_PARSING; /* Set when the cgraph is fully build and the basic flags are computed. */ bool cgraph_function_flags_ready = false; @@ -499,11 +494,6 @@ cgraph_create_function_alias (tree alias, tree decl) alias_node->thunk.alias = decl; alias_node->local.finalized = true; alias_node->alias = 1; - - if ((TREE_PUBLIC (alias) && !DECL_COMDAT (alias) && !DECL_EXTERNAL (alias)) - || (DECL_VIRTUAL_P (alias) - && (DECL_COMDAT (alias) || DECL_EXTERNAL (alias)))) - cgraph_mark_reachable_node (alias_node); return alias_node; } @@ -539,7 +529,7 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali struct cgraph_node * cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, - tree alias, tree decl, + tree alias, tree decl ATTRIBUTE_UNUSED, bool this_adjusting, HOST_WIDE_INT fixed_offset, HOST_WIDE_INT virtual_value, tree virtual_offset, @@ -569,14 +559,6 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node->thunk.thunk_p = true; node->local.finalized = true; - if (cgraph_decide_is_function_needed (node, decl)) - cgraph_mark_reachable_node (node); - - if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) - || (DECL_VIRTUAL_P (decl) - && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl)))) - cgraph_mark_reachable_node (node); - return node; } @@ -1508,9 +1490,6 @@ cgraph_mark_reachable_node (struct cgraph_node *node) else notice_global_symbol (node->symbol.decl); node->reachable = 1; - - node->next_needed = cgraph_nodes_queue; - x_cgraph_nodes_queue = (symtab_node)node; } } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 5915a14..8e06fc1 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -215,10 +215,6 @@ struct GTY(()) cgraph_node { struct cgraph_node * GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h"))) next_nested; - /* Pointer to the next function in cgraph_nodes_queue. */ - struct cgraph_node * - GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h"))) - next_needed; /* Pointer to the next clone. */ struct cgraph_node *next_sibling_clone; struct cgraph_node *prev_sibling_clone; @@ -419,13 +415,6 @@ struct GTY(()) varpool_node { struct symtab_node_base symbol; /* For aliases points to declaration DECL is alias of. */ tree alias_of; - /* Pointer to the next function in varpool_nodes_queue. */ - struct varpool_node * - GTY ((nested_ptr (union symtab_node_def, "(struct varpool_node *)(%h)", "(symtab_node)%h"))) - next_needed; - struct varpool_node * - GTY ((nested_ptr (union symtab_node_def, "(struct varpool_node *)(%h)", "(symtab_node)%h"))) - prev_needed; /* Set when function must be output - it is externally visible or its address is taken. */ @@ -471,6 +460,8 @@ extern GTY(()) int cgraph_edge_max_uid; extern bool cgraph_global_info_ready; enum cgraph_state { + /* Frontend is parsing and finalizing functions. */ + CGRAPH_STATE_PARSING, /* Callgraph is being constructed. It is safe to add new functions. */ CGRAPH_STATE_CONSTRUCTION, /* Callgraph is built and IPA passes are being run. */ @@ -484,9 +475,7 @@ enum cgraph_state }; extern enum cgraph_state cgraph_state; extern bool cgraph_function_flags_ready; -extern GTY(()) symtab_node x_cgraph_nodes_queue; -#define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue) -extern GTY(()) struct cgraph_node *cgraph_new_nodes; +extern cgraph_node_set cgraph_new_nodes; extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes; extern GTY(()) int symtab_order; @@ -687,9 +676,6 @@ bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e); bool cgraph_optimize_for_size_p (struct cgraph_node *); /* In varpool.c */ -extern GTY(()) symtab_node x_varpool_nodes_queue; -#define varpool_nodes_queue ((struct varpool_node *)x_varpool_nodes_queue) - struct varpool_node *varpool_node (tree); struct varpool_node *varpool_node_for_asm (tree asmname); void varpool_mark_needed_node (struct varpool_node *); @@ -709,9 +695,8 @@ void varpool_remove_node (struct varpool_node *node); void varpool_finalize_named_section_flags (struct varpool_node *node); bool varpool_assemble_pending_decls (void); bool varpool_assemble_decl (struct varpool_node *node); -bool varpool_analyze_pending_decls (void); +void varpool_analyze_node (struct varpool_node *); void varpool_remove_unreferenced_decls (void); -void varpool_empty_needed_queue (void); struct varpool_node * varpool_extra_name_alias (tree, tree); struct varpool_node * varpool_create_variable_alias (tree, tree); void varpool_reset_queue (void); @@ -799,16 +784,48 @@ varpool_node_name(struct varpool_node *node) #define FOR_EACH_SYMBOL(node) \ for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next) + +/* Return first variable. */ +static inline struct varpool_node * +varpool_first_variable (void) +{ + symtab_node node; + for (node = symtab_nodes; node; node = node->symbol.next) + { + if (symtab_variable_p (node)) + return varpool (node); + } + return NULL; +} + +/* Return next variable after NODE. */ +static inline struct varpool_node * +varpool_next_variable (struct varpool_node *node) +{ + symtab_node node1 = (symtab_node) node->symbol.next; + for (; node1; node1 = node1->symbol.next) + { + if (symtab_variable_p (node1)) + return varpool (node1); + } + return NULL; +} +/* Walk all variables. */ +#define FOR_EACH_VARIABLE(node) \ + for ((node) = varpool_first_variable (); \ + (node); \ + (node) = varpool_next_variable ((node))) + /* Return first reachable static variable with initializer. */ static inline struct varpool_node * varpool_first_static_initializer (void) { - struct varpool_node *node; - for (node = varpool_nodes_queue; node; node = node->next_needed) + symtab_node node; + for (node = symtab_nodes; node; node = node->symbol.next) { - gcc_checking_assert (TREE_CODE (node->symbol.decl) == VAR_DECL); - if (DECL_INITIAL (node->symbol.decl)) - return node; + if (symtab_variable_p (node) + && DECL_INITIAL (node->symbol.decl)) + return varpool (node); } return NULL; } @@ -817,56 +834,50 @@ varpool_first_static_initializer (void) static inline struct varpool_node * varpool_next_static_initializer (struct varpool_node *node) { - for (node = node->next_needed; node; node = node->next_needed) + symtab_node node1 = (symtab_node) node->symbol.next; + for (; node1; node1 = node1->symbol.next) { - gcc_checking_assert (TREE_CODE (node->symbol.decl) == VAR_DECL); - if (DECL_INITIAL (node->symbol.decl)) - return node; + if (symtab_variable_p (node1) + && DECL_INITIAL (node1->symbol.decl)) + return varpool (node1); } return NULL; } -/* Walk all reachable static variables. */ -#define FOR_EACH_STATIC_VARIABLE(node) \ - for ((node) = varpool_nodes_queue; (node); (node) = (node)->next_needed) /* Walk all static variables with initializer set. */ #define FOR_EACH_STATIC_INITIALIZER(node) \ for ((node) = varpool_first_static_initializer (); (node); \ (node) = varpool_next_static_initializer (node)) -/* Return first variable. */ +/* Return first reachable static variable with initializer. */ static inline struct varpool_node * -varpool_first_variable (void) +varpool_first_defined_variable (void) { symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) { - if (symtab_variable_p (node)) + if (symtab_variable_p (node) && varpool (node)->analyzed) return varpool (node); } return NULL; } -/* Return next variable after NODE. */ +/* Return next reachable static variable with initializer after NODE. */ static inline struct varpool_node * -varpool_next_variable (struct varpool_node *node) +varpool_next_defined_variable (struct varpool_node *node) { symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) { - if (symtab_variable_p (node1)) + if (symtab_variable_p (node1) && varpool (node1)->analyzed) return varpool (node1); } return NULL; } -/* Walk all variables. */ -#define FOR_EACH_VARIABLE(node) \ - for ((node) = varpool_first_variable (); \ - (node); \ - (node) = varpool_next_variable ((node))) /* Walk all variables with definitions in current unit. */ #define FOR_EACH_DEFINED_VARIABLE(node) \ - for ((node) = varpool_nodes_queue; (node); (node) = (node)->next_needed) + for ((node) = varpool_first_defined_variable (); (node); \ + (node) = varpool_next_defined_variable (node)) /* Return first function with body defined. */ static inline struct cgraph_node * diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 37059a2..445a392 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -87,7 +87,6 @@ record_reference (tree *tp, int *walk_subtrees, void *data) struct varpool_node *vnode = varpool_node (decl); if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); - varpool_mark_needed_node (vnode); ipa_record_reference ((symtab_node)ctx->varpool_node, (symtab_node)vnode, IPA_REF_ADDR, NULL); @@ -130,7 +129,6 @@ record_type_list (struct cgraph_node *node, tree list) if (TREE_CODE (type) == VAR_DECL) { struct varpool_node *vnode = varpool_node (type); - varpool_mark_needed_node (vnode); ipa_record_reference ((symtab_node)node, (symtab_node)vnode, IPA_REF_ADDR, NULL); @@ -245,7 +243,6 @@ mark_address (gimple stmt, tree addr, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); - varpool_mark_needed_node (vnode); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, IPA_REF_ADDR, stmt); @@ -278,7 +275,6 @@ mark_load (gimple stmt, tree t, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); - varpool_mark_needed_node (vnode); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, IPA_REF_LOAD, stmt); @@ -300,7 +296,6 @@ mark_store (gimple stmt, tree t, void *data) if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); - varpool_mark_needed_node (vnode); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, IPA_REF_STORE, stmt); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 3e07e50..409afa1 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -145,6 +145,11 @@ along with GCC; see the file COPYING3. If not see #include "except.h" #include "regset.h" /* FIXME: For reg_obstack. */ +/* Queue of cgraph nodes scheduled to be added into cgraph. This is a + secondary queue used during optimization to accommodate passes that + may generate new functions that need to be optimized and expanded. */ +cgraph_node_set cgraph_new_nodes; + static void cgraph_expand_all_functions (void); static void cgraph_mark_functions_to_output (void); static void cgraph_expand_function (struct cgraph_node *); @@ -192,6 +197,23 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl) return false; } +/* Head of the queue of nodes to be processed while building callgraph */ + +static symtab_node first = (symtab_node)(void *)1; + +/* Add NODE to queue starting at FIRST. + The queue is linked via AUX pointers and terminated by pointer to 1. */ + +static void +enqueue_node (symtab_node node) +{ + if (node->symbol.aux) + return; + gcc_checking_assert (first); + node->symbol.aux = first; + first = node; +} + /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these functions into callgraph in a way so they look like ordinary reachable functions inserted into callgraph already at construction time. */ @@ -202,26 +224,26 @@ cgraph_process_new_functions (void) bool output = false; tree fndecl; struct cgraph_node *node; + cgraph_node_set_iterator csi; - varpool_analyze_pending_decls (); + if (!cgraph_new_nodes) + return false; /* Note that this queue may grow as its being processed, as the new functions may generate new ones. */ - while (cgraph_new_nodes) + for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi)) { - node = cgraph_new_nodes; + node = csi_node (csi); fndecl = node->symbol.decl; - cgraph_new_nodes = cgraph_new_nodes->next_needed; switch (cgraph_state) { case CGRAPH_STATE_CONSTRUCTION: /* At construction time we just need to finalize function and move it into reachable functions list. */ - node->next_needed = NULL; cgraph_finalize_function (fndecl, false); - cgraph_mark_reachable_node (node); output = true; cgraph_call_function_insertion_hooks (node); + enqueue_node ((symtab_node) node); break; case CGRAPH_STATE_IPA: @@ -262,8 +284,9 @@ cgraph_process_new_functions (void) gcc_unreachable (); break; } - varpool_analyze_pending_decls (); } + free_cgraph_node_set (cgraph_new_nodes); + cgraph_new_nodes = NULL; return output; } @@ -372,13 +395,17 @@ cgraph_add_new_function (tree fndecl, bool lowered) struct cgraph_node *node; switch (cgraph_state) { + case CGRAPH_STATE_PARSING: + cgraph_finalize_function (fndecl, false); + break; case CGRAPH_STATE_CONSTRUCTION: /* Just enqueue function to be processed at nearest occurrence. */ node = cgraph_create_node (fndecl); - node->next_needed = cgraph_new_nodes; if (lowered) node->lowered = true; - cgraph_new_nodes = node; + if (!cgraph_new_nodes) + cgraph_new_nodes = cgraph_node_set_new (); + cgraph_node_set_add (cgraph_new_nodes, node); break; case CGRAPH_STATE_IPA: @@ -406,8 +433,9 @@ cgraph_add_new_function (tree fndecl, bool lowered) } if (lowered) node->lowered = true; - node->next_needed = cgraph_new_nodes; - cgraph_new_nodes = node; + if (!cgraph_new_nodes) + cgraph_new_nodes = cgraph_node_set_new (); + cgraph_node_set_add (cgraph_new_nodes, node); break; case CGRAPH_STATE_FINISHED: @@ -1091,26 +1119,13 @@ process_function_and_variable_attributes (struct cgraph_node *first, { tree decl = vnode->symbol.decl; if (DECL_PRESERVE_P (decl)) - { - vnode->symbol.force_output = true; - if (vnode->finalized) - varpool_mark_needed_node (vnode); - } - if (TARGET_DLLIMPORT_DECL_ATTRIBUTES - && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) - && TREE_PUBLIC (vnode->symbol.decl)) - { - if (vnode->finalized) - varpool_mark_needed_node (vnode); - } + vnode->symbol.force_output = true; else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) { if (! TREE_PUBLIC (vnode->symbol.decl)) warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes, "%<externally_visible%>" " attribute have effect only on public objects"); - else if (vnode->finalized) - varpool_mark_needed_node (vnode); } if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) && vnode->finalized @@ -1127,10 +1142,54 @@ process_function_and_variable_attributes (struct cgraph_node *first, } } -/* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively - each reachable functions) and build cgraph. - The function can be called multiple times after inserting new nodes - into beginning of queue. Just the new part of queue is re-scanned then. */ +/* Return true when there are references to NODE. */ + +static bool +referred_to_p (symtab_node node) +{ + int i; + struct ipa_ref *ref; + + for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); + i++) + return true; + if (symtab_function_p (node) && cgraph (node)->callers) + return true; + return false; +} + +/* Mark DECL as finalized. By finalizing the declaration, frontend instruct the + middle end to output the variable to asm file, if needed or externally + visible. */ + +void +varpool_finalize_decl (tree decl) +{ + struct varpool_node *node = varpool_node (decl); + + gcc_assert (TREE_STATIC (decl)); + + if (node->finalized) + return; + notice_global_symbol (decl); + node->finalized = true; + if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) + /* Traditionally we do not eliminate static variables when not + optimizing and when not doing toplevel reoder. */ + || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl) + && !DECL_ARTIFICIAL (node->symbol.decl))) + node->symbol.force_output = true; + + if (cgraph_state == CGRAPH_STATE_CONSTRUCTION + && (decide_is_variable_needed (node, decl) + || referred_to_p ((symtab_node)node))) + enqueue_node ((symtab_node)node); + if (cgraph_state >= CGRAPH_STATE_IPA_SSA) + varpool_analyze_node (node); +} + +/* Discover all functions and variables that are trivially needed, analyze + them as well as all functions and variables referred by them */ static void cgraph_analyze_functions (void) @@ -1138,140 +1197,176 @@ cgraph_analyze_functions (void) /* Keep track of already processed nodes when called multiple times for intermodule optimization. */ static struct cgraph_node *first_analyzed; - struct cgraph_node *first_processed = first_analyzed; + struct cgraph_node *first_handled = first_analyzed; static struct varpool_node *first_analyzed_var; - struct cgraph_node *node, *next; + struct varpool_node *first_handled_var = first_analyzed_var; + + symtab_node node, next; + int i; + struct ipa_ref *ref; + bool changed = true; bitmap_obstack_initialize (NULL); - process_function_and_variable_attributes (first_processed, - first_analyzed_var); - first_processed = cgraph_first_function (); - first_analyzed_var = varpool_first_variable (); - varpool_analyze_pending_decls (); - if (cgraph_dump_file) + cgraph_state = CGRAPH_STATE_CONSTRUCTION; + + /* Analysis adds static variables that in turn adds references to new functions. + So we need to iterate the process until it stabilize. */ + while (changed) { - fprintf (cgraph_dump_file, "Initial entry points:"); - for (node = cgraph_first_function (); node != first_analyzed; - node = cgraph_next_function (node)) - if (cgraph_decide_is_function_needed (node, node->symbol.decl)) - fprintf (cgraph_dump_file, " %s", cgraph_node_name (node)); - fprintf (cgraph_dump_file, "\n"); - } - cgraph_process_new_functions (); + changed = false; + process_function_and_variable_attributes (first_analyzed, + first_analyzed_var); - /* Propagate reachability flag and lower representation of all reachable - functions. In the future, lowering will introduce new functions and - new entry points on the way (by template instantiation and virtual - method table generation for instance). */ - while (cgraph_nodes_queue) - { - struct cgraph_edge *edge; - tree decl = cgraph_nodes_queue->symbol.decl; - - node = cgraph_nodes_queue; - x_cgraph_nodes_queue = (symtab_node)cgraph_nodes_queue->next_needed; - node->next_needed = NULL; - - /* ??? It is possible to create extern inline function and later using - weak alias attribute to kill its body. See - gcc.c-torture/compile/20011119-1.c */ - if (!DECL_STRUCT_FUNCTION (decl) - && (!node->alias || !node->thunk.alias) - && !node->thunk.thunk_p) + /* First identify the trivially needed symbols. */ + for (node = symtab_nodes; + node != (symtab_node)first_analyzed + && node != (symtab_node)first_analyzed_var; node = node->symbol.next) { - cgraph_reset_node (node); - node->local.redefined_extern_inline = true; - continue; + if ((symtab_function_p (node) + && cgraph (node)->local.finalized + && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl)) + || (symtab_variable_p (node) + && varpool (node)->finalized + && !DECL_EXTERNAL (node->symbol.decl) + && decide_is_variable_needed (varpool (node), node->symbol.decl))) + { + enqueue_node (node); + if (!changed && cgraph_dump_file) + fprintf (cgraph_dump_file, "Trivially needed symbols:"); + changed = true; + if (cgraph_dump_file) + fprintf (cgraph_dump_file, " %s", symtab_node_asm_name (node)); + } + if (node == (symtab_node)first_analyzed + || node == (symtab_node)first_analyzed_var) + break; } + cgraph_process_new_functions (); + first_analyzed_var = varpool_first_variable (); + first_analyzed = cgraph_first_function (); - if (!node->analyzed) - cgraph_analyze_function (node); - - for (edge = node->callees; edge; edge = edge->next_callee) - if (!edge->callee->reachable) - cgraph_mark_reachable_node (edge->callee); - for (edge = node->callers; edge; edge = edge->next_caller) - if (!edge->caller->reachable && edge->caller->thunk.thunk_p) - cgraph_mark_reachable_node (edge->caller); + if (changed && dump_file) + fprintf (cgraph_dump_file, "\n"); - if (node->symbol.same_comdat_group) + /* Lower representation, build callgraph edges and references for all trivially + needed symbols and all symbols referred by them. */ + while (first != (symtab_node)(void *)1) { - for (next = cgraph (node->symbol.same_comdat_group); - next != node; - next = cgraph (next->symbol.same_comdat_group)) - cgraph_mark_reachable_node (next); - } + changed = true; + node = first; + first = (symtab_node)first->symbol.aux; + if (symtab_function_p (node) && cgraph (node)->local.finalized) + { + struct cgraph_edge *edge; + struct cgraph_node *cnode; + tree decl; + + cnode = cgraph (node); + decl = cnode->symbol.decl; + + /* ??? It is possible to create extern inline function and later using + weak alias attribute to kill its body. See + gcc.c-torture/compile/20011119-1.c */ + if (!DECL_STRUCT_FUNCTION (decl) + && (!cnode->alias || !cnode->thunk.alias) + && !cnode->thunk.thunk_p) + { + cgraph_reset_node (cnode); + cnode->local.redefined_extern_inline = true; + continue; + } - /* If decl is a clone of an abstract function, mark that abstract - function so that we don't release its body. The DECL_INITIAL() of that - abstract function declaration will be later needed to output debug - info. */ - if (DECL_ABSTRACT_ORIGIN (decl)) - { - struct cgraph_node *origin_node; - origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl)); - origin_node->abstract_and_needed = true; - } + if (!cnode->analyzed) + cgraph_analyze_function (cnode); - /* We finalize local static variables during constructing callgraph - edges. Process their attributes too. */ - process_function_and_variable_attributes (first_processed, - first_analyzed_var); - first_processed = cgraph_first_function (); - first_analyzed_var = varpool_first_variable (); - varpool_analyze_pending_decls (); - cgraph_process_new_functions (); + for (edge = cnode->callees; edge; edge = edge->next_callee) + { + cgraph_mark_reachable_node (edge->callee); + if (edge->callee->local.finalized) + enqueue_node ((symtab_node)edge->callee); + } + + /* If decl is a clone of an abstract function, mark that abstract + function so that we don't release its body. The DECL_INITIAL() of that + abstract function declaration will be later needed to output debug + info. */ + if (DECL_ABSTRACT_ORIGIN (decl)) + { + struct cgraph_node *origin_node; + origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl)); + origin_node->abstract_and_needed = true; + } + + } + else if (symtab_variable_p (node) + && varpool (node)->finalized) + { + varpool_analyze_node (varpool (node)); + } + + if (node->symbol.same_comdat_group) + { + symtab_node next; + for (next = node->symbol.same_comdat_group; + next != node; + next = next->symbol.same_comdat_group) + enqueue_node (next); + } + for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + if ((symtab_function_p (ref->referred) && cgraph (ref->referred)->local.finalized) + || (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized)) + enqueue_node (ref->referred); + cgraph_process_new_functions (); + } } /* Collect entry points to the unit. */ if (cgraph_dump_file) { - fprintf (cgraph_dump_file, "Unit entry points:"); - for (node = cgraph_first_function (); node != first_analyzed; - node = cgraph_next_function (node)) - if (cgraph_decide_is_function_needed (node, node->symbol.decl)) - fprintf (cgraph_dump_file, " %s", cgraph_node_name (node)); fprintf (cgraph_dump_file, "\n\nInitial "); dump_symtab (cgraph_dump_file); } if (cgraph_dump_file) - fprintf (cgraph_dump_file, "\nReclaiming functions:"); + fprintf (cgraph_dump_file, "\nRemoving unused symbols:"); - for (node = cgraph_first_function (); node != first_analyzed; - node = next) + for (node = symtab_nodes; + node != (symtab_node)first_handled + && node != (symtab_node)first_handled_var; node = next) { - tree decl = node->symbol.decl; - next = cgraph_next_function (node); - - if (node->local.finalized && !gimple_has_body_p (decl) - && (!node->alias || !node->thunk.alias) - && !node->thunk.thunk_p) - cgraph_reset_node (node); - - if (!node->reachable - && (gimple_has_body_p (decl) || node->thunk.thunk_p - || (node->alias && node->thunk.alias))) + next = node->symbol.next; + if (!node->symbol.aux && !referred_to_p (node)) { if (cgraph_dump_file) - fprintf (cgraph_dump_file, " %s", cgraph_node_name (node)); - cgraph_remove_node (node); + fprintf (cgraph_dump_file, " %s", symtab_node_name (node)); + symtab_remove_node (node); continue; } - else - node->next_needed = NULL; - gcc_assert (!node->local.finalized || node->thunk.thunk_p - || node->alias - || gimple_has_body_p (decl)); - gcc_assert (node->analyzed == node->local.finalized); + if (symtab_function_p (node)) + { + tree decl = node->symbol.decl; + struct cgraph_node *cnode = cgraph (node); + + if (cnode->local.finalized && !gimple_has_body_p (decl) + && (!cnode->alias || !cnode->thunk.alias) + && !cnode->thunk.thunk_p) + cgraph_reset_node (cnode); + + gcc_assert (!cnode->local.finalized || cnode->thunk.thunk_p + || cnode->alias + || gimple_has_body_p (decl)); + gcc_assert (cnode->analyzed == cnode->local.finalized); + } + node->symbol.aux = NULL; } + first_analyzed = cgraph_first_function (); + first_analyzed_var = varpool_first_variable (); if (cgraph_dump_file) { fprintf (cgraph_dump_file, "\n\nReclaimed "); dump_symtab (cgraph_dump_file); } bitmap_obstack_release (NULL); - first_analyzed = cgraph_first_function (); ggc_collect (); } @@ -2041,8 +2136,6 @@ cgraph_output_in_order (void) max = symtab_order; nodes = XCNEWVEC (struct cgraph_order_sort, max); - varpool_analyze_pending_decls (); - FOR_EACH_DEFINED_FUNCTION (pf) { if (pf->process && !pf->thunk.thunk_p && !pf->alias) @@ -2071,14 +2164,6 @@ cgraph_output_in_order (void) } /* In toplevel reorder mode we output all statics; mark them as needed. */ - for (i = 0; i < max; ++i) - { - if (nodes[i].kind == ORDER_VAR) - { - varpool_mark_needed_node (nodes[i].u.v); - } - } - varpool_empty_needed_queue (); for (i = 0; i < max; ++i) if (nodes[i].kind == ORDER_VAR) @@ -2614,10 +2699,6 @@ cgraph_optimize (void) verify_symtab (); #endif - /* Frontend may output common variables after the unit has been finalized. - It is safe to deal with them here as they are always zero initialized. */ - varpool_analyze_pending_decls (); - timevar_push (TV_CGRAPHOPT); if (pre_ipa_mem_report) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 825d2bc..69c5916 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2012-04-22 Jan Hubicka <jh@suse.cz> + + * decl2.c (maybe_make_one_only): Mark keyed COMDATs as USED so they + gets finalized. + 2012-04-22 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c/44774 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 23b98f5..34c969c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1677,6 +1677,7 @@ maybe_make_one_only (tree decl) DECL_COMDAT (decl) = 1; /* Mark it needed so we don't forget to emit it. */ mark_decl_referenced (decl); + TREE_USED (decl) = 1; } } } diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 7e2ce58..1240ddb 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -14572,7 +14572,7 @@ reference_to_unused (tree * tp, int * walk_subtrees, else if (TREE_CODE (*tp) == VAR_DECL) { struct varpool_node *node = varpool_get_node (*tp); - if (!node || !node->needed) + if (!node || !node->analyzed) return *tp; } else if (TREE_CODE (*tp) == FUNCTION_DECL @@ -17057,7 +17057,7 @@ premark_types_used_by_global_vars_helper (void **slot, /* Ask cgraph if the global variable really is to be emitted. If yes, then we'll keep the DIE of ENTRY->TYPE. */ struct varpool_node *node = varpool_get_node (entry->var_decl); - if (node && node->needed) + if (node && node->analyzed) { die->die_perennial_p = 1; /* Keep the parent DIEs as well. */ diff --git a/gcc/except.c b/gcc/except.c index e6e7794..254dd8c 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -2814,8 +2814,6 @@ output_ttype (tree type, int tt_format, int tt_format_size) value = const0_rtx; else { - struct varpool_node *node; - /* FIXME lto. pass_ipa_free_lang_data changes all types to runtime types so TYPE should already be a runtime type reference. When pass_ipa_free_lang data is made a default @@ -2834,12 +2832,7 @@ output_ttype (tree type, int tt_format, int tt_format_size) { type = TREE_OPERAND (type, 0); if (TREE_CODE (type) == VAR_DECL) - { - node = varpool_node (type); - if (node) - varpool_mark_needed_node (node); - is_public = TREE_PUBLIC (type); - } + is_public = TREE_PUBLIC (type); } else gcc_assert (TREE_CODE (type) == INTEGER_CST); @@ -107,7 +107,7 @@ process_references (struct ipa_ref_list *list, struct varpool_node *node = ipa_ref_varpool_node (ref); if (!node->needed) { - varpool_mark_needed_node (node); + node->needed = true; enqueue_varpool_node (node, first_varpool); } } @@ -187,7 +187,6 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) FOR_EACH_VARIABLE (vnode) gcc_assert (!vnode->symbol.aux); #endif - varpool_reset_queue (); /* Mark functions whose bodies are obviously needed. This is mostly when they can be referenced externally. Inline clones are special since their declarations are shared with master clone and thus @@ -213,13 +212,10 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) /* Mark variables that are obviously needed. */ FOR_EACH_VARIABLE (vnode) { - vnode->next_needed = NULL; - vnode->prev_needed = NULL; if ((vnode->analyzed || vnode->symbol.force_output) && !varpool_can_remove_if_no_refs (vnode)) { - vnode->needed = false; - varpool_mark_needed_node (vnode); + vnode->needed = true; enqueue_varpool_node (vnode, &first_varpool); } else @@ -315,7 +311,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) next = varpool (next->symbol.same_comdat_group)) if (!next->needed) { - varpool_mark_needed_node (next); + next->needed = true; enqueue_varpool_node (next, &first_varpool); } } @@ -794,8 +790,6 @@ function_and_variable_visibility (bool whole_program) && !DECL_EXTERNAL (vnode->symbol.decl)) { vnode->symbol.force_output = 1; - varpool_mark_needed_node (vnode); - gcc_assert (vnode->needed); pointer_set_insert (aliased_vnodes, vnode); if (dump_file) fprintf (dump_file, " varpool node %s", @@ -933,10 +927,9 @@ function_and_variable_visibility (bool whole_program) { if (!vnode->finalized) continue; - if (vnode->needed - && varpool_externally_visible_p - (vnode, - pointer_set_contains (aliased_vnodes, vnode))) + if (varpool_externally_visible_p + (vnode, + pointer_set_contains (aliased_vnodes, vnode))) vnode->symbol.externally_visible = true; else vnode->symbol.externally_visible = false; @@ -1018,7 +1011,6 @@ static unsigned int whole_program_function_and_variable_visibility (void) { struct cgraph_node *node; - struct varpool_node *vnode; function_and_variable_visibility (flag_whole_program); @@ -1026,17 +1018,6 @@ whole_program_function_and_variable_visibility (void) if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl)) && node->local.finalized) cgraph_mark_reachable_node (node); - FOR_EACH_DEFINED_VARIABLE (vnode) - if (vnode->symbol.externally_visible && !DECL_COMDAT (vnode->symbol.decl)) - varpool_mark_needed_node (vnode); - if (dump_file) - { - fprintf (dump_file, "\nNeeded variables:"); - FOR_EACH_DEFINED_VARIABLE (vnode) - if (vnode->needed) - fprintf (dump_file, " %s", varpool_node_name (vnode)); - fprintf (dump_file, "\n\n"); - } if (optimize) ipa_discover_readonly_nonaddressable_vars (); return 0; diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 14eb423..532a6bf 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,7 @@ +2012-04-22 Jan Hubicka <jh@suse.cz> + + * class.c (build_utf8_ref): Do not mark varpool node as needed. + 2012-04-20 Jan Hubicka <jh@suse.cz> * class.c (make_local_function_alias): Do not mark symbol referenced. diff --git a/gcc/java/class.c b/gcc/java/class.c index 145bb63..33a3999 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1001,7 +1001,6 @@ build_utf8_ref (tree name) DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (ctype); pushdecl (decl); rest_of_decl_compilation (decl, global_bindings_p (), 0); - varpool_mark_needed_node (varpool_node (decl)); ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); IDENTIFIER_UTF8_REF (name) = ref; return ref; diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index c0398b4..2563489 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -571,7 +571,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node bp_pack_value (&bp, node->alias, 1); bp_pack_value (&bp, node->alias_of != NULL, 1); gcc_assert (node->finalized || !node->analyzed); - gcc_assert (node->needed); /* 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 labels and share them across LTRANS partitions. */ @@ -1079,16 +1078,14 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->finalized = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); non_null_aliasof = bp_unpack_value (&bp, 1); - node->analyzed = node->finalized; node->symbol.used_from_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)); if (node->symbol.in_other_partition) { DECL_EXTERNAL (node->symbol.decl) = 1; TREE_STATIC (node->symbol.decl) = 0; } - if (node->finalized) - varpool_mark_needed_node (node); if (non_null_aliasof) { decl_index = streamer_read_uhwi (ib); @@ -1457,6 +1454,8 @@ input_cgraph (void) unsigned int j = 0; struct cgraph_node *node; + cgraph_state = CGRAPH_STATE_IPA_SSA; + while ((file_data = file_data_vec[j++])) { const char *data; diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index ed8a651..f142444 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -262,12 +262,6 @@ static void lto_varpool_replace_node (struct varpool_node *vnode, struct varpool_node *prevailing_node) { - /* Merge node flags. */ - if (vnode->needed) - { - gcc_assert (!vnode->analyzed || prevailing_node->analyzed); - varpool_mark_needed_node (prevailing_node); - } gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->analyzed || prevailing_node->analyzed); diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 8287f8f..e2aa595 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -283,7 +283,7 @@ partition_cgraph_node_p (struct cgraph_node *node) static bool partition_varpool_node_p (struct varpool_node *vnode) { - if (vnode->alias || !vnode->needed) + if (vnode->alias || !vnode->analyzed) return false; /* Constant pool and comdat are always only in partitions they are needed. */ if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl) diff --git a/gcc/passes.c b/gcc/passes.c index ed5da15..4724f80 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -2342,8 +2342,8 @@ ipa_write_summaries (void) } vset = varpool_node_set_new (); - FOR_EACH_VARIABLE (vnode) - if (vnode->needed && (!vnode->alias || vnode->alias_of)) + FOR_EACH_DEFINED_VARIABLE (vnode) + if ((!vnode->alias || vnode->alias_of)) varpool_node_set_add (vset, vnode); ipa_write_summaries_1 (set, vset); diff --git a/gcc/symtab.c b/gcc/symtab.c index 75078b0..975fdef 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -429,6 +429,11 @@ dump_symtab_base (FILE *f, symtab_node node) if (node->symbol.address_taken) fprintf (f, " Address is taken.\n"); + if (node->symbol.aux) + { + fprintf (f, " Aux:"); + dump_addr (f, " @", (void *)node->symbol.aux); + } fprintf (f, " References: "); ipa_dump_references (f, &node->symbol.ref_list); diff --git a/gcc/toplev.c b/gcc/toplev.c index 51d52e1..574af3b 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -413,7 +413,7 @@ wrapup_global_declaration_2 (tree decl) && (TREE_USED (decl) || TREE_USED (DECL_ASSEMBLER_NAME (decl)))) /* needed */; - else if (node && node->needed) + else if (node && node->analyzed) /* needed */; else if (DECL_COMDAT (decl)) needed = false; @@ -581,6 +581,7 @@ compile_file (void) basically finished. */ if (in_lto_p || !flag_lto || flag_fat_lto_objects) { + varpool_remove_unreferenced_decls (); varpool_assemble_pending_decls (); finish_aliases_2 (); diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index 52d953c..55ea0fa 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -87,7 +87,6 @@ init_ic_make_global_vars (void) decl_default_tls_model (ic_void_ptr_var); varpool_finalize_decl (ic_void_ptr_var); - varpool_mark_needed_node (varpool_node (ic_void_ptr_var)); gcov_type_ptr = build_pointer_type (get_gcov_type ()); ic_gcov_type_ptr_var @@ -103,7 +102,6 @@ init_ic_make_global_vars (void) decl_default_tls_model (ic_gcov_type_ptr_var); varpool_finalize_decl (ic_gcov_type_ptr_var); - varpool_mark_needed_node (varpool_node (ic_gcov_type_ptr_var)); } void diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index aa7b6c7..95c8bd8 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -625,7 +625,6 @@ build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, TREE_CONSTANT (decl) = 1; TREE_READONLY (decl) = 1; add_referenced_var (decl); - varpool_mark_needed_node (varpool_node (decl)); varpool_finalize_decl (decl); fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, diff --git a/gcc/varasm.c b/gcc/varasm.c index d506b31..c3d289e 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2254,7 +2254,6 @@ mark_decl_referenced (tree decl) else if (TREE_CODE (decl) == VAR_DECL) { struct varpool_node *node = varpool_node (decl); - varpool_mark_needed_node (node); /* C++ frontend use mark_decl_references to force COMDAT variables to be output that might appear dead otherwise. */ node->symbol.force_output = true; diff --git a/gcc/varpool.c b/gcc/varpool.c index 2423ee8..7c8d1fd 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -1,5 +1,5 @@ /* Callgraph handling code. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -48,32 +48,6 @@ along with GCC; see the file COPYING3. If not see All variables supposed to be output into final file needs to be explicitly marked by frontend via VARPOOL_FINALIZE_DECL function. */ -/* Queue of cgraph nodes scheduled to be lowered and output. - The queue is maintained via mark_needed_node, linked via node->next_needed - pointer. - - LAST_NEEDED_NODE points to the end of queue, so it can be - maintained in forward order. GTY is needed to make it friendly to - PCH. - - During compilation we construct the queue of needed variables - twice: first time it is during cgraph construction, second time it is at the - end of compilation in VARPOOL_REMOVE_UNREFERENCED_DECLS so we can avoid - optimized out variables being output. - - Each variable is thus first analyzed and then later possibly output. - FIRST_UNANALYZED_NODE points to first node in queue that was not analyzed - yet and is moved via VARPOOL_ANALYZE_PENDING_DECLS. */ - -symtab_node x_varpool_nodes_queue; -static GTY(()) symtab_node x_varpool_last_needed_node; -#define varpool_last_needed_node ((struct varpool_node *)x_varpool_last_needed_node) -static GTY(()) symtab_node x_varpool_first_unanalyzed_node; -#define varpool_first_unanalyzed_node ((struct varpool_node *)x_varpool_first_unanalyzed_node) - -/* Lists all assembled variables to be sent to debugger output later on. */ -static GTY(()) struct varpool_node *varpool_assembled_nodes_queue; - /* Return varpool node assigned to DECL. Create new one when needed. */ struct varpool_node * varpool_node (tree decl) @@ -95,24 +69,7 @@ varpool_node (tree decl) void varpool_remove_node (struct varpool_node *node) { - gcc_assert (!varpool_assembled_nodes_queue); symtab_unregister_node ((symtab_node)node); - if (varpool_first_unanalyzed_node == node) - x_varpool_first_unanalyzed_node = (symtab_node)node->next_needed; - if (node->next_needed) - node->next_needed->prev_needed = node->prev_needed; - else if (node->prev_needed) - { - gcc_assert (varpool_last_needed_node); - x_varpool_last_needed_node = (symtab_node)node->prev_needed; - } - if (node->prev_needed) - node->prev_needed->next_needed = node->next_needed; - else if (node->next_needed) - { - gcc_assert (varpool_nodes_queue == node); - x_varpool_nodes_queue = (symtab_node)node->next_needed; - } ggc_free (node); } @@ -128,8 +85,6 @@ dump_varpool_node (FILE *f, struct varpool_node *node) fprintf (f, " Varpool flags:"); if (DECL_INITIAL (node->symbol.decl)) fprintf (f, " initialized"); - if (node->needed) - fprintf (f, " needed"); if (node->analyzed) fprintf (f, " analyzed"); if (node->finalized) @@ -168,45 +123,6 @@ varpool_node_for_asm (tree asmname) return NULL; } -/* Helper function for finalization code - add node into lists so it will - be analyzed and compiled. */ -static void -varpool_enqueue_needed_node (struct varpool_node *node) -{ - if (varpool_last_needed_node) - { - varpool_last_needed_node->next_needed = node; - node->prev_needed = varpool_last_needed_node; - } - x_varpool_last_needed_node = (symtab_node)node; - node->next_needed = NULL; - if (!varpool_nodes_queue) - x_varpool_nodes_queue = (symtab_node)node; - if (!varpool_first_unanalyzed_node) - x_varpool_first_unanalyzed_node = (symtab_node)node; - notice_global_symbol (node->symbol.decl); -} - -/* Notify finalize_compilation_unit that given node is reachable - or needed. */ -void -varpool_mark_needed_node (struct varpool_node *node) -{ - if (!node->needed && node->finalized - && !TREE_ASM_WRITTEN (node->symbol.decl)) - varpool_enqueue_needed_node (node); - node->needed = 1; -} - -/* Reset the queue of needed nodes. */ -void -varpool_reset_queue (void) -{ - x_varpool_last_needed_node = NULL; - x_varpool_nodes_queue = NULL; - x_varpool_first_unanalyzed_node = NULL; -} - /* Determine if variable DECL is needed. That is, visible to something either outside this translation unit, something magic in the system configury */ @@ -270,42 +186,6 @@ const_value_known_p (tree decl) return true; } -/* Mark DECL as finalized. By finalizing the declaration, frontend instruct the - middle end to output the variable to asm file, if needed or externally - visible. */ -void -varpool_finalize_decl (tree decl) -{ - struct varpool_node *node = varpool_node (decl); - - gcc_assert (TREE_STATIC (decl)); - - /* The first declaration of a variable that comes through this function - decides whether it is global (in C, has external linkage) - or local (in C, has internal linkage). So do nothing more - if this function has already run. */ - if (node->finalized) - { - if (cgraph_global_info_ready) - varpool_assemble_pending_decls (); - return; - } - if (node->needed) - varpool_enqueue_needed_node (node); - node->finalized = true; - if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) - /* Traditionally we do not eliminate static variables when not - optimizing and when not doing toplevel reoder. */ - || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl) - && !DECL_ARTIFICIAL (node->symbol.decl))) - node->symbol.force_output = true; - - if (decide_is_variable_needed (node, decl)) - varpool_mark_needed_node (node); - if (cgraph_global_info_ready) - varpool_assemble_pending_decls (); -} - /* Add the variable DECL to the varpool. Unlike varpool_finalize_decl function is intended to be used by middle end and allows insertion of new variable at arbitrary point @@ -338,93 +218,69 @@ cgraph_variable_initializer_availability (struct varpool_node *node) return AVAIL_AVAILABLE; } -/* Walk the decls we marked as necessary and see if they reference new - variables or functions and add them into the worklists. */ -bool -varpool_analyze_pending_decls (void) +void +varpool_analyze_node (struct varpool_node *node) { - bool changed = false; + tree decl = node->symbol.decl; - timevar_push (TV_VARPOOL); - while (varpool_first_unanalyzed_node) + /* 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. + We however don't want to re-analyze already analyzed nodes. */ + if (!node->analyzed) { - struct varpool_node *node = varpool_first_unanalyzed_node, *next; - tree decl = node->symbol.decl; - bool analyzed = node->analyzed; - - varpool_first_unanalyzed_node->analyzed = true; - - x_varpool_first_unanalyzed_node = (symtab_node)varpool_first_unanalyzed_node->next_needed; - - /* 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. - We however don't want to re-analyze already analyzed nodes. */ - if (!analyzed) - { - gcc_assert (!in_lto_p || cgraph_function_flags_ready); - /* Compute the alignment early so function body expanders are - already informed about increased alignment. */ - align_variable (decl, 0); - } - if (node->alias && node->alias_of) + gcc_assert (!in_lto_p || cgraph_function_flags_ready); + /* Compute the alignment early so function body expanders are + already informed about increased alignment. */ + align_variable (decl, 0); + } + if (node->alias && node->alias_of) + { + struct varpool_node *tgt = varpool_node (node->alias_of); + struct varpool_node *n; + + for (n = tgt; n && n->alias; + n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) + if (n == node) + { + error ("variable %q+D part of alias cycle", node->symbol.decl); + node->alias = false; + continue; + } + if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references)) + ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL); + /* C++ FE sometimes change linkage flags after producing same body aliases. */ + if (node->extra_name_alias) { - struct varpool_node *tgt = varpool_node (node->alias_of); - struct varpool_node *n; - - for (n = tgt; n && n->alias; - n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) - if (n == node) - { - error ("variable %q+D part of alias cycle", node->symbol.decl); - node->alias = false; - continue; - } - if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references)) - ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL); - /* C++ FE sometimes change linkage flags after producing same body aliases. */ - if (node->extra_name_alias) + DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of); + TREE_PUBLIC (node->symbol.decl) = TREE_PUBLIC (node->alias_of); + DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of); + DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of); + if (TREE_PUBLIC (node->symbol.decl)) { - DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of); - TREE_PUBLIC (node->symbol.decl) = TREE_PUBLIC (node->alias_of); - DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of); - DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of); - if (TREE_PUBLIC (node->symbol.decl)) + DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (node->alias_of); + DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (node->alias_of); + if (DECL_ONE_ONLY (node->alias_of) + && !node->symbol.same_comdat_group) { - DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (node->alias_of); - DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (node->alias_of); - if (DECL_ONE_ONLY (node->alias_of) - && !node->symbol.same_comdat_group) + node->symbol.same_comdat_group = (symtab_node)tgt; + if (!tgt->symbol.same_comdat_group) + tgt->symbol.same_comdat_group = (symtab_node)node; + else { - node->symbol.same_comdat_group = (symtab_node)tgt; - if (!tgt->symbol.same_comdat_group) - tgt->symbol.same_comdat_group = (symtab_node)node; - else - { - symtab_node n; - for (n = tgt->symbol.same_comdat_group; - n->symbol.same_comdat_group != (symtab_node)tgt; - n = n->symbol.same_comdat_group) - ; - n->symbol.same_comdat_group = (symtab_node)node; - } + symtab_node n; + for (n = tgt->symbol.same_comdat_group; + n->symbol.same_comdat_group != (symtab_node)tgt; + n = n->symbol.same_comdat_group) + ; + n->symbol.same_comdat_group = (symtab_node)node; } } } - varpool_mark_needed_node (tgt); - } - else if (DECL_INITIAL (decl)) - record_references_in_initializer (decl, analyzed); - if (node->symbol.same_comdat_group) - { - for (next = varpool (node->symbol.same_comdat_group); - next != node; - next = varpool (next->symbol.same_comdat_group)) - varpool_mark_needed_node (next); } - changed = true; } - timevar_pop (TV_VARPOOL); - return changed; + else if (DECL_INITIAL (decl)) + record_references_in_initializer (decl, node->analyzed); + node->analyzed = true; } /* Assemble thunks and aliases asociated to NODE. */ @@ -459,11 +315,6 @@ varpool_assemble_decl (struct varpool_node *node) assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { - node->next_needed = varpool_assembled_nodes_queue; - node->prev_needed = NULL; - if (varpool_assembled_nodes_queue) - varpool_assembled_nodes_queue->prev_needed = node; - varpool_assembled_nodes_queue = node; node->finalized = 1; assemble_aliases (node); return true; @@ -473,40 +324,85 @@ varpool_assemble_decl (struct varpool_node *node) return false; } +/* Add NODE to queue starting at FIRST. + The queue is linked via AUX pointers and terminated by pointer to 1. */ + +static void +enqueue_node (struct varpool_node *node, struct varpool_node **first) +{ + if (node->symbol.aux) + return; + gcc_checking_assert (*first); + node->symbol.aux = *first; + *first = node; +} + /* Optimization of function bodies might've rendered some variables as - unnecessary so we want to avoid these from being compiled. + unnecessary so we want to avoid these from being compiled. Re-do + reachability starting from variables that are either externally visible + or was referred from the asm output routines. */ - This is done by pruning the queue and keeping only the variables that - really appear needed (ie they are either externally visible or referenced - by compiled function). Re-doing the reachability analysis on variables - brings back the remaining variables referenced by these. */ void varpool_remove_unreferenced_decls (void) { - struct varpool_node *next, *node = varpool_nodes_queue; - - varpool_reset_queue (); + struct varpool_node *next, *node; + struct varpool_node *first = (struct varpool_node *)(void *)1; + int i; + struct ipa_ref *ref; if (seen_error ()) return; - while (node) + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "Trivially needed variables:"); + finish_aliases_1 (); + FOR_EACH_DEFINED_VARIABLE (node) { - next = node->next_needed; - node->needed = 0; - if (node->analyzed && (!varpool_can_remove_if_no_refs (node) /* We just expanded all function bodies. See if any of them needed the variable. */ || DECL_RTL_SET_P (node->symbol.decl))) - varpool_mark_needed_node (node); + { + enqueue_node (node, &first); + if (cgraph_dump_file) + fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); + } + } + while (first != (struct varpool_node *)(void *)1) + { + node = first; + first = (struct varpool_node *)first->symbol.aux; - node = next; + if (node->symbol.same_comdat_group) + { + symtab_node next; + for (next = node->symbol.same_comdat_group; + next != (symtab_node)node; + next = next->symbol.same_comdat_group) + if (symtab_variable_p (next) + && varpool (next)->analyzed) + enqueue_node (varpool (next), &first); + } + for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + if (symtab_variable_p (ref->referred) + && varpool (ref->referred)->analyzed) + enqueue_node (varpool (ref->referred), &first); } - /* Make sure we mark alias targets as used targets. */ - finish_aliases_1 (); - varpool_analyze_pending_decls (); + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "\nRemoving variables:"); + for (node = varpool_first_defined_variable (); node; node = next) + { + next = varpool_next_defined_variable (node); + if (!node->symbol.aux) + { + if (cgraph_dump_file) + fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); + varpool_remove_node (node); + } + } + if (cgraph_dump_file) + fprintf (cgraph_dump_file, "\n"); } /* For variables in named sections make sure get_variable_section @@ -537,55 +433,17 @@ varpool_assemble_pending_decls (void) return false; timevar_push (TV_VAROUT); - /* EH might mark decls as needed during expansion. This should be safe since - we don't create references to new function, but it should not be used - elsewhere. */ - varpool_analyze_pending_decls (); FOR_EACH_DEFINED_VARIABLE (node) varpool_finalize_named_section_flags (node); - while (varpool_nodes_queue) - { - struct varpool_node *node = varpool_nodes_queue; - - x_varpool_nodes_queue = (symtab_node)(varpool_nodes_queue->next_needed); - if (varpool_assemble_decl (node)) - changed = true; - else - { - node->prev_needed = NULL; - node->next_needed = NULL; - } - } - /* varpool_nodes_queue is now empty, clear the pointer to the last element - in the queue. */ - x_varpool_last_needed_node = NULL; + FOR_EACH_DEFINED_VARIABLE (node) + if (varpool_assemble_decl (node)) + changed = true; timevar_pop (TV_VAROUT); return changed; } -/* Remove all elements from the queue so we can re-use it for debug output. */ -void -varpool_empty_needed_queue (void) -{ - /* EH might mark decls as needed during expansion. This should be safe since - we don't create references to new function, but it should not be used - elsewhere. */ - varpool_analyze_pending_decls (); - - while (varpool_nodes_queue) - { - struct varpool_node *node = varpool_nodes_queue; - x_varpool_nodes_queue = (symtab_node)varpool_nodes_queue->next_needed; - node->next_needed = NULL; - node->prev_needed = NULL; - } - /* varpool_nodes_queue is now empty, clear the pointer to the last element - in the queue. */ - x_varpool_last_needed_node = NULL; -} - /* Create a new global variable of type TYPE. */ tree add_new_static_var (tree type) @@ -603,7 +461,6 @@ add_new_static_var (tree type) lang_hooks.dup_lang_specific_decl (new_decl); create_var_ann (new_decl); new_node = varpool_node (new_decl); - varpool_mark_needed_node (new_node); add_referenced_var (new_decl); varpool_finalize_decl (new_decl); @@ -624,10 +481,17 @@ varpool_create_variable_alias (tree alias, tree decl) alias_node->alias = 1; alias_node->finalized = 1; alias_node->alias_of = decl; - if ((!DECL_EXTERNAL (alias) - && decide_is_variable_needed (alias_node, alias)) - || alias_node->needed) - varpool_mark_needed_node (alias_node); + + /* Extra name alias mechanizm creates aliases really late + via DECL_ASSEMBLER_NAME mechanizm. + This is unfortunate because they are not going through the + standard channels. Ensure they get output. */ + if (cgraph_state >= CGRAPH_STATE_IPA) + { + varpool_analyze_node (alias_node); + if (TREE_PUBLIC (alias)) + alias_node->symbol.externally_visible = true; + } return alias_node; } @@ -688,4 +552,3 @@ varpool_for_node_and_aliases (struct varpool_node *node, } return false; } -#include "gt-varpool.h" |