]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lto-symtab.c (lto_varpool_replace_node): Do not merge needed flags.
authorJan Hubicka <jh@suse.cz>
Sun, 22 Apr 2012 21:28:07 +0000 (23:28 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 22 Apr 2012 21:28:07 +0000 (21:28 +0000)
* 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

25 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/ada/ChangeLog
gcc/ada/gcc-interface/utils.c
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphbuild.c
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/dwarf2out.c
gcc/except.c
gcc/ipa.c
gcc/java/ChangeLog
gcc/java/class.c
gcc/lto-cgraph.c
gcc/lto-symtab.c
gcc/lto/lto-partition.c
gcc/passes.c
gcc/symtab.c
gcc/toplev.c
gcc/tree-profile.c
gcc/tree-switch-conversion.c
gcc/varasm.c
gcc/varpool.c

index 1e80ca560b077a404dd31b4fa3fba9b0a74017fa..88968a07b15ec6237aaaee406bd6c5df257e2738 100644 (file)
@@ -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
index 0070ceaea14666e41fdd18696962acb9a8874d82..97c8973d260c8c84e411f660a5c64b3d690bfe15 100644 (file)
@@ -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 \
index 8fd284af31fd2f406ca9b3bafab059cefe2bb9bb..34144913fd96c3fcac79bc0e101f9a18e016c438 100644 (file)
@@ -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
index e95e967457f466d55aac38078f3df7b2d642de4b..41f83bfbe8a134d9738256d3c8caeb4286e308dd 100644 (file)
@@ -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))
        {
index 4588249ac5fa8fc5a98002a02fe6e9952205adc8..ed4cdf64d08d6679b2dee00669df711364b1585b 100644 (file)
@@ -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;
     }
 }
 
index 5915a14c6c73043553960374958a42e09a85ef73..8e06fc1fc1b8253afc4becc3238389464e53ba86 100644 (file)
@@ -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 *
index 37059a223c9053997d1152045a99661e57f8938c..445a392110dce324636a4fe27c4d8e8b208641c8 100644 (file)
@@ -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);
index 3e07e501013900242fa3a44f5fe81677efd6a93a..409afa13da48e1242d99176d09a530963e2ef247 100644 (file)
@@ -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)
     {
index 825d2bc2d26ba259e65133cc6ee173a6f2ddd8f2..69c5916cfaf46fb1cd179464b843888d7680f73f 100644 (file)
@@ -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
index 23b98f5401b267cdc3a5b134a538b3bba1c1bb1d..34c969c31fcce83ec5afb9bb66600813a82ee85a 100644 (file)
@@ -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;
        }
     }
 }
index 7e2ce58ae4519828859aa3c75366120f9a8c0e13..1240ddb563789280b22c0c99a23909628d0fa08d 100644 (file)
@@ -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.  */
index e6e7794f246494bb9be52a13533f6cbdd60c417e..254dd8c32aefb07613e24424614eefdb2bb2d223 100644 (file)
@@ -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);
index f4daf36aa37e7e8037bc7565b0236ed8b934b42d..34b58e857d7d1317e7511c9e79ad2503ecd80d92 100644 (file)
--- 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;
index 14eb423b4d64f24e3bd898d4c0643d9a269a4d0d..532a6bf26ee8b1bfed20c9bc138955d11a232627 100644 (file)
@@ -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.
index 145bb632016876a8409c41815cb03620f365121d..33a399980345e4e23e5347aa6909f6f04f90bdcc 100644 (file)
@@ -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;
index c0398b41a359a5c873e69957df639b74fb595569..2563489904784de9274b32ba806d896f736c56f8 100644 (file)
@@ -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;
index ed8a651b72139c9bf7100110540096ba902535a6..f1424447d0fa9e56657677e0fba2363a2693fa12 100644 (file)
@@ -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);
 
index 8287f8fdd779fde418619fc9157710196db12467..e2aa595b502f0d1d460453d852894116de8af084 100644 (file)
@@ -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)
index ed5da15a3e9e8e18f05a7d0ff077ded94bfffd79..4724f80b0e8181cd1e3d55c77684a1b337f93631 100644 (file)
@@ -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);
index 75078b089bac9744bd83089600dd72268816c111..975fdef89b1614b618d1c54a9d1db5cc3f178281 100644 (file)
@@ -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);
index 51d52e1c8dd77bb6feb1f54d74dd32c9a9b18aa1..574af3bc1608e1fa799e77246076d8247dc552bd 100644 (file)
@@ -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 ();
 
index 52d953ceb18f435bd40333b55269f2a4733faf7b..55ea0fa8a22587dd8e8c2397a7a5878924ac5622 100644 (file)
@@ -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
index aa7b6c7d12ef8530a63ff630ab798eb0b1cb4fe5..95c8bd805e12f04df6b56ecf1b5113c5da74e87b 100644 (file)
@@ -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,
index d506b31715444c784a4d0ef987fe39d3bca4332a..c3d289eb91a057324ea97af9612c3a5f6756e0e1 100644 (file)
@@ -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;
index 2423ee88db2d2facef09e9a890ba69775a76e66a..7c8d1fd8c9fb7ce35b2bb803bedc7db74c666417 100644 (file)
@@ -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"