aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-22 21:28:07 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-22 21:28:07 +0000
commitff2a5adaa72fef87cac689a40c23258a30b304c8 (patch)
treea4cd93cef18f73580dc0226c3ce10cbae70f9f08
parent62c34bfbaa44da92a4c3cb45314370d19b0d324c (diff)
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186687 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog79
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/gcc-interface/utils.c1
-rw-r--r--gcc/cgraph.c25
-rw-r--r--gcc/cgraph.h97
-rw-r--r--gcc/cgraphbuild.c5
-rw-r--r--gcc/cgraphunit.c365
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/decl2.c1
-rw-r--r--gcc/dwarf2out.c4
-rw-r--r--gcc/except.c9
-rw-r--r--gcc/ipa.c31
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/java/class.c1
-rw-r--r--gcc/lto-cgraph.c7
-rw-r--r--gcc/lto-symtab.c6
-rw-r--r--gcc/lto/lto-partition.c2
-rw-r--r--gcc/passes.c4
-rw-r--r--gcc/symtab.c5
-rw-r--r--gcc/toplev.c3
-rw-r--r--gcc/tree-profile.c2
-rw-r--r--gcc/tree-switch-conversion.c1
-rw-r--r--gcc/varasm.c1
-rw-r--r--gcc/varpool.c393
25 files changed, 524 insertions, 535 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e80ca560b0..88968a07b15 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 0070ceaea14..97c8973d260 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 8fd284af31f..34144913fd9 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 e95e967457f..41f83bfbe8a 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 4588249ac5f..ed4cdf64d08 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 5915a14c6c7..8e06fc1fc1b 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 37059a223c9..445a392110d 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 3e07e501013..409afa13da4 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 825d2bc2d26..69c5916cfaf 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 23b98f5401b..34c969c31fc 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 7e2ce58ae45..1240ddb5637 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 e6e7794f246..254dd8c32ae 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);
diff --git a/gcc/ipa.c b/gcc/ipa.c
index f4daf36aa37..34b58e857d7 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -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 14eb423b4d6..532a6bf26ee 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 145bb632016..33a39998034 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 c0398b41a35..25634899047 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 ed8a651b721..f1424447d0f 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 8287f8fdd77..e2aa595b502 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 ed5da15a3e9..4724f80b0e8 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 75078b089ba..975fdef89b1 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 51d52e1c8dd..574af3bc160 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 52d953ceb18..55ea0fa8a22 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 aa7b6c7d12e..95c8bd805e1 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 d506b317154..c3d289eb91a 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 2423ee88db2..7c8d1fd8c9f 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"