OSDN Git Service

2005-03-31 Jan Hubicka <jh@suse.cz>
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Mar 2005 22:28:02 +0000 (22:28 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Mar 2005 22:28:02 +0000 (22:28 +0000)
2004-11-02  Jan Hubicka  <jh@suse.cz>

* cgraph.c (cgraph_varpool_node_name): New function.
(dump_cgraph_varpool_node): New function.
(dump_varpool): New function.
* cgraphunit.c (cgraph_optimize): Dump varpool.

2004-10-16  Jan Hubicka  <jh@suse.cz>

* cgraph.c (decide_is_variable_needed): New function.
(cgraph_varpool_finalize_decl): Use it.
* cgraphunit.c (cgraph_optimize): Assemble_pending_decls when not doing
unit-at-a-time.
* final.c (output_addr_const): Do not call mark_referenced.
* passes.c (rest_of_decl_compilation): ifdef out DECL_RTL_SET_P hack;
always go via cgraph.
* toplev.c (wrapup_global_declarations): Kill non-unit-at-a-time code.
(check_global_declarations): Ifdef out code clearing DECL_RTL.
* tree-optimize.c (execute_inline): Mark functions called.
* i386.c (output_pic_addr_const): Do not call mark_decl_referenced.

2004-10-11  Jan Hubicka  <jh@suse.cz>

* cgraph.c (cgraph_varpool_first_unanalyzed_node): New global voriable
(cgraph_varpool_last_needed_node): New static variable.
(enqueue_needed_varpool_node): Break out from ...; add items to the
end of queue; update first pointers.
(cgraph_varpool_mark_needed_node): ... here.
(cgraph_varpool_finalize_decl): Use enqueue_needed_varpool_node.
(cgraph_varpool_assemble_pending_decls): Move to cgraphunit.c
* cgraph.h (cgraph_varpool_node): Add analyzed field.
(cgraph_varpool_first_unanalyzed_node): Declare.
* cgraphunit.c: Include output.h.
(cgraph_varpool_analyze_pending_decls): New function.
(cgraph_varpool_assemble_pending_decls): Move from cgraph.c; bail out
for errors, analyze pending decls.
(cgraph_finalize_compilation_unit): Only analyze decls.
(cgraph_optimize): Assemble the decls after expanding.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97287 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/config/i386/i386.c
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/java/ChangeLog
gcc/java/Make-lang.in
gcc/java/class.c
gcc/java/resource.c
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/varpool-1.c [new file with mode: 0644]
gcc/toplev.c
gcc/tree-optimize.c
gcc/varasm.c

index 9fac180..a7394c5 100644 (file)
@@ -1,3 +1,44 @@
+2005-03-31  Jan Hubicka  <jh@suse.cz>
+
+       2004-11-02  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_varpool_node_name): New function.
+       (dump_cgraph_varpool_node): New function.
+       (dump_varpool): New function.
+       * cgraphunit.c (cgraph_optimize): Dump varpool.
+
+       2004-10-16  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (decide_is_variable_needed): New function.
+       (cgraph_varpool_finalize_decl): Use it.
+       * cgraphunit.c (cgraph_optimize): Assemble_pending_decls when not doing
+       unit-at-a-time.
+       * final.c (output_addr_const): Do not call mark_referenced.
+       * passes.c (rest_of_decl_compilation): ifdef out DECL_RTL_SET_P hack;
+       always go via cgraph.
+       * toplev.c (wrapup_global_declarations): Kill non-unit-at-a-time code.
+       (check_global_declarations): Ifdef out code clearing DECL_RTL.
+       * tree-optimize.c (execute_inline): Mark functions called.
+       * i386.c (output_pic_addr_const): Do not call mark_decl_referenced.
+
+       2004-10-11  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_varpool_first_unanalyzed_node): New global voriable
+       (cgraph_varpool_last_needed_node): New static variable.
+       (enqueue_needed_varpool_node): Break out from ...; add items to the
+       end of queue; update first pointers.
+       (cgraph_varpool_mark_needed_node): ... here.
+       (cgraph_varpool_finalize_decl): Use enqueue_needed_varpool_node.
+       (cgraph_varpool_assemble_pending_decls): Move to cgraphunit.c
+       * cgraph.h (cgraph_varpool_node): Add analyzed field.
+       (cgraph_varpool_first_unanalyzed_node): Declare.
+       * cgraphunit.c: Include output.h.
+       (cgraph_varpool_analyze_pending_decls): New function.
+       (cgraph_varpool_assemble_pending_decls): Move from cgraph.c; bail out
+       for errors, analyze pending decls.
+       (cgraph_finalize_compilation_unit): Only analyze decls.
+       (cgraph_optimize): Assemble the decls after expanding.
+
 2005-03-30  Daniel Berlin  <dberlin@dberlin.org>
 
        * tree-ssa-alias.c (compute_flow_insensitive_aliasing): Make sure
index b769f84..5ed13bc 100644 (file)
@@ -84,6 +84,7 @@ The varpool data structure:
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "tree-inline.h"
 #include "langhooks.h"
 #include "hashtab.h"
 #include "toplev.h"
@@ -91,6 +92,7 @@ The varpool data structure:
 #include "ggc.h"
 #include "debug.h"
 #include "target.h"
+#include "basic-block.h"
 #include "cgraph.h"
 #include "varray.h"
 #include "output.h"
@@ -118,14 +120,21 @@ int cgraph_max_uid;
 /* Set when whole unit has been analyzed so we can access global info.  */
 bool cgraph_global_info_ready = false;
 
+/* Set when the cgraph is fully build and the basic flags are computed.  */
+bool cgraph_function_flags_ready = false;
+
 /* Hash table used to convert declarations into nodes.  */
 static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
 
 /* Queue of cgraph nodes scheduled to be lowered and output.  */
-struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
+struct cgraph_varpool_node *cgraph_varpool_nodes_queue, *cgraph_varpool_first_unanalyzed_node;
+
 
 /* The linked list of cgraph varpool nodes.  */
-static GTY(())  struct cgraph_varpool_node *cgraph_varpool_nodes;
+static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
+
+/* End of the varpool queue.  Needs to be QTYed to work with PCH.  */
+static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
 
 static hashval_t hash_node (const void *);
 static int eq_node (const void *, const void *);
@@ -533,6 +542,13 @@ cgraph_node_name (struct cgraph_node *node)
   return lang_hooks.decl_printable_name (node->decl, 2);
 }
 
+/* Return name of the node used in debug output.  */
+static const char *
+cgraph_varpool_node_name (struct cgraph_varpool_node *node)
+{
+  return lang_hooks.decl_printable_name (node->decl, 2);
+}
+
 /* Dump given cgraph node.  */
 void
 dump_cgraph_node (FILE *f, struct cgraph_node *node)
@@ -598,6 +614,36 @@ dump_cgraph (FILE *f)
     dump_cgraph_node (f, node);
 }
 
+/* Dump given cgraph node.  */
+void
+dump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
+{
+  fprintf (f, "%s:", cgraph_varpool_node_name (node));
+  if (DECL_INITIAL (node->decl))
+    fprintf (f, " initialized");
+  if (node->needed)
+    fprintf (f, " needed");
+  if (node->analyzed)
+    fprintf (f, " analyzed");
+  if (node->finalized)
+    fprintf (f, " finalized");
+  if (node->output)
+    fprintf (f, " output");
+  fprintf (f, "\n");
+}
+
+/* Dump the callgraph.  */
+
+void
+dump_varpool (FILE *f)
+{
+  struct cgraph_varpool_node *node;
+
+  fprintf (f, "variable pool:\n\n");
+  for (node = cgraph_varpool_nodes; node; node = node->next_needed)
+    dump_cgraph_varpool_node (f, node);
+}
+
 /* Returns a hash code for P.  */
 
 static hashval_t
@@ -671,20 +717,82 @@ change_decl_assembler_name (tree decl, tree name)
   SET_DECL_ASSEMBLER_NAME (decl, name);
 }
 
+/* Helper function for finalization code - add node into lists so it will
+   be analyzed and compiled.  */
+void
+cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *node)
+{
+  if (cgraph_varpool_last_needed_node)
+    cgraph_varpool_last_needed_node->next_needed = node;
+  cgraph_varpool_last_needed_node = node;
+  node->next_needed = NULL;
+  if (!cgraph_varpool_nodes_queue)
+    cgraph_varpool_nodes_queue = node;
+  if (!cgraph_varpool_first_unanalyzed_node)
+    cgraph_varpool_first_unanalyzed_node = node;
+  notice_global_symbol (node->decl);
+}
+
+/* Reset the queue of needed nodes.  */
+void
+cgraph_varpool_reset_queue (void)
+{
+  cgraph_varpool_last_needed_node = NULL;
+  cgraph_varpool_nodes_queue = NULL;
+  cgraph_varpool_first_unanalyzed_node = NULL;
+}
+
 /* Notify finalize_compilation_unit that given node is reachable
    or needed.  */
 void
 cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
 {
   if (!node->needed && node->finalized)
-    {
-      node->next_needed = cgraph_varpool_nodes_queue;
-      cgraph_varpool_nodes_queue = node;
-      notice_global_symbol (node->decl);
-    }
+    cgraph_varpool_enqueue_needed_node (node);
   node->needed = 1;
 }
 
+/* Determine if variable DECL is needed.  That is, visible to something
+   either outside this translation unit, something magic in the system
+   configury, or (if not doing unit-at-a-time) to something we haven't
+   seen yet.  */
+
+bool
+decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
+{
+  /* If the user told us it is used, then it must be so.  */
+  if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+    return true;
+
+  /* ??? If the assembler name is set by hand, it is possible to assemble
+     the name later after finalizing the function and the fact is noticed
+     in assemble_name then.  This is arguably a bug.  */
+  if (DECL_ASSEMBLER_NAME_SET_P (decl)
+      && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+    return true;
+
+  /* If we decided it was needed before, but at the time we didn't have
+     the definition available, then it's still needed.  */
+  if (node->needed)
+    return true;
+
+  /* Externally visible functions must be output.  The exception is
+     COMDAT functions that must be output only when they are needed.  */
+  if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+    return true;
+
+  if (flag_unit_at_a_time)
+    return false;
+
+  /* If not doing unit at a time, then we'll only defer this function
+     if its marked for inlining.  Otherwise we want to emit it now.  */
+
+  /* We want to emit COMDAT variables only when absolutely necessary.  */
+  if (DECL_COMDAT (decl))
+    return false;
+  return true;
+}
+
 void
 cgraph_varpool_finalize_decl (tree decl)
 {
@@ -695,47 +803,19 @@ cgraph_varpool_finalize_decl (tree decl)
      or local (in C, has internal linkage).  So do nothing more
      if this function has already run.  */
   if (node->finalized)
-    return;
-  if (node->needed)
     {
-      node->next_needed = cgraph_varpool_nodes_queue;
-      cgraph_varpool_nodes_queue = node;
-      notice_global_symbol (decl);
+      if (cgraph_global_info_ready || !flag_unit_at_a_time)
+       cgraph_varpool_assemble_pending_decls ();
+      return;
     }
+  if (node->needed)
+    cgraph_varpool_enqueue_needed_node (node);
   node->finalized = true;
 
-  if (/* Externally visible variables must be output.  The exception are
-        COMDAT functions that must be output only when they are needed.  */
-      (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
-      /* Function whose name is output to the assembler file must be produced.
-        It is possible to assemble the name later after finalizing the function
-        and the fact is noticed in assemble_name then.  */
-      || (DECL_ASSEMBLER_NAME_SET_P (decl)
-         && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
-    {
-      cgraph_varpool_mark_needed_node (node);
-    }
-}
-
-bool
-cgraph_varpool_assemble_pending_decls (void)
-{
-  bool changed = false;
-
-  while (cgraph_varpool_nodes_queue)
-    {
-      struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
-      tree decl = node->decl;
-
-      cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
-      if (!TREE_ASM_WRITTEN (decl) && !node->alias)
-       {
-         assemble_variable (decl, 0, 1, 0);
-         changed = true;
-       }
-      node->next_needed = NULL;
-    }
-  return changed;
+  if (decide_is_variable_needed (node, decl))
+    cgraph_varpool_mark_needed_node (node);
+  if (cgraph_global_info_ready || !flag_unit_at_a_time)
+    cgraph_varpool_assemble_pending_decls ();
 }
 
 /* Return true when the DECL can possibly be inlined.  */
index b9a8d6e..e701e56 100644 (file)
@@ -151,6 +151,12 @@ struct cgraph_varpool_node GTY(())
   /* Set when function must be output - it is externally visible
      or its address is taken.  */
   bool needed;
+  /* Needed variables might become dead by optimization.  This flag
+     forces the variable to be output even if it appears dead otherwise.  */
+  bool force_output;
+  /* Set once the variable has been instantiated and its callee
+     lists created.  */
+  bool analyzed;
   /* Set once it has been finalized so we consider it to be output.  */
   bool finalized;
   /* Set when function is scheduled to be assembled.  */
@@ -165,11 +171,14 @@ extern GTY(()) int cgraph_max_uid;
 extern bool cgraph_global_info_ready;
 extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
 
+extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
 extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
 
 /* In cgraph.c  */
 void dump_cgraph (FILE *);
 void dump_cgraph_node (FILE *, struct cgraph_node *);
+void dump_varpool (FILE *);
+void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
 void cgraph_remove_edge (struct cgraph_edge *);
 void cgraph_remove_node (struct cgraph_node *);
 void cgraph_node_remove_callees (struct cgraph_node *node);
@@ -190,14 +199,17 @@ struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
 struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
 void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
 void cgraph_varpool_finalize_decl (tree);
-bool cgraph_varpool_assemble_pending_decls (void);
 void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
 
 bool cgraph_function_possibly_inlined_p (tree);
 void cgraph_unnest_node (struct cgraph_node *node);
+void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
+void cgraph_varpool_reset_queue (void);
+bool decide_is_variable_needed (struct cgraph_varpool_node *, tree);
 
 /* In cgraphunit.c  */
 bool cgraph_assemble_pending_functions (void);
+bool cgraph_varpool_assemble_pending_decls (void);
 void cgraph_finalize_function (tree, bool);
 void cgraph_finalize_compilation_unit (void);
 void cgraph_create_edges (struct cgraph_node *, tree);
index 9fef33e..3bb143f 100644 (file)
@@ -189,6 +189,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "intl.h"
 #include "function.h"
 #include "tree-gimple.h"
+#include "output.h"
 
 #define INSNS_PER_CALL 10
 
@@ -281,6 +282,64 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
   return false;
 }
 
+/* Walk the decls we marked as neccesary and see if they reference new variables
+   or functions and add them into the worklists.  */
+static bool
+cgraph_varpool_analyze_pending_decls (void)
+{
+  bool changed = false;
+  timevar_push (TV_CGRAPH);
+
+  while (cgraph_varpool_first_unanalyzed_node)
+    {
+      tree decl = cgraph_varpool_first_unanalyzed_node->decl;
+
+      cgraph_varpool_first_unanalyzed_node->analyzed = true;
+
+      cgraph_varpool_first_unanalyzed_node = cgraph_varpool_first_unanalyzed_node->next_needed;
+
+      if (DECL_INITIAL (decl))
+       cgraph_create_edges (NULL, DECL_INITIAL (decl));
+      changed = true;
+    }
+  timevar_pop (TV_CGRAPH);
+  return changed;
+}
+
+/* Optimization of function bodies might've rendered some variables as
+   unnecesary so we want to avoid these from being compiled.
+
+   This is done by prunning the queue and keeping only the variables that
+   really appear needed (ie thery are either externally visible or referenced
+   by compiled function). Re-doing the reachability analysis on variables
+   brings back the remaining variables referenced by these.  */
+static void
+cgraph_varpool_remove_unreferenced_decls (void)
+{
+  struct cgraph_varpool_node *next, *node = cgraph_varpool_nodes_queue;
+
+  cgraph_varpool_reset_queue ();
+
+  if (errorcount || sorrycount)
+    return;
+
+  while (node)
+    {
+      tree decl = node->decl;
+      next = node->next_needed;
+      node->needed = 0;
+
+      if (node->finalized
+         && ((DECL_ASSEMBLER_NAME_SET_P (decl)
+              && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+             || node->force_output
+             || decide_is_variable_needed (node, decl)))
+       cgraph_varpool_mark_needed_node (node);
+
+      node = next;
+    }
+  cgraph_varpool_analyze_pending_decls ();
+}
 
 
 /* When not doing unit-at-a-time, output all functions enqueued.
@@ -421,7 +480,7 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
       /* ??? Really, we should mark this decl as *potentially* referenced
         by this function and re-examine whether the decl is actually used
         after rtl has been generated.  */
-      if (TREE_STATIC (t))
+      if (TREE_STATIC (t) || DECL_EXTERNAL (t))
        {
          cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
          if (lang_hooks.callgraph.analyze_expr)
@@ -639,6 +698,37 @@ verify_cgraph (void)
     verify_cgraph_node (node);
 }
 
+
+/* Output all variables enqueued to be assembled.  */
+bool
+cgraph_varpool_assemble_pending_decls (void)
+{
+  bool changed = false;
+
+  if (errorcount || sorrycount)
+    return false;
+  /* 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.  */
+  cgraph_varpool_analyze_pending_decls ();
+
+  while (cgraph_varpool_nodes_queue)
+    {
+      tree decl = cgraph_varpool_nodes_queue->decl;
+      struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
+
+      cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
+      if (!TREE_ASM_WRITTEN (decl) && !node->alias && !DECL_EXTERNAL (decl))
+       {
+         assemble_variable (decl, 0, 1, 0);
+         changed = true;
+       }
+      node->next_needed = NULL;
+    }
+  return changed;
+}
+
 /* Analyze the function scheduled to be output.  */
 static void
 cgraph_analyze_function (struct cgraph_node *node)
@@ -681,6 +771,9 @@ void
 cgraph_finalize_compilation_unit (void)
 {
   struct cgraph_node *node;
+  /* Keep track of already processed nodes when called multiple times for
+     intermodule optmization.  */
+  static struct cgraph_node *first_analyzed;
 
   finish_aliases_1 ();
 
@@ -690,15 +783,18 @@ cgraph_finalize_compilation_unit (void)
       return;
     }
 
-  cgraph_varpool_assemble_pending_decls ();
   if (!quiet_flag)
-    fprintf (stderr, "\nAnalyzing compilation unit\n");
+    {
+      fprintf (stderr, "\nAnalyzing compilation unit");
+      fflush (stderr);
+    }
 
   timevar_push (TV_CGRAPH);
+  cgraph_varpool_analyze_pending_decls ();
   if (cgraph_dump_file)
     {
       fprintf (cgraph_dump_file, "Initial entry points:");
-      for (node = cgraph_nodes; node; node = node->next)
+      for (node = cgraph_nodes; node != first_analyzed; node = node->next)
        if (node->needed && DECL_SAVED_TREE (node->decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n");
@@ -732,7 +828,7 @@ cgraph_finalize_compilation_unit (void)
        if (!edge->callee->reachable)
          cgraph_mark_reachable_node (edge->callee);
 
-      cgraph_varpool_assemble_pending_decls ();
+      cgraph_varpool_analyze_pending_decls ();
     }
 
   /* Collect entry points to the unit.  */
@@ -740,7 +836,7 @@ cgraph_finalize_compilation_unit (void)
   if (cgraph_dump_file)
     {
       fprintf (cgraph_dump_file, "Unit entry points:");
-      for (node = cgraph_nodes; node; node = node->next)
+      for (node = cgraph_nodes; node != first_analyzed; node = node->next)
        if (node->needed && DECL_SAVED_TREE (node->decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
       fprintf (cgraph_dump_file, "\n\nInitial ");
@@ -750,7 +846,7 @@ cgraph_finalize_compilation_unit (void)
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "\nReclaiming functions:");
 
-  for (node = cgraph_nodes; node; node = node->next)
+  for (node = cgraph_nodes; node != first_analyzed; node = node->next)
     {
       tree decl = node->decl;
 
@@ -768,6 +864,7 @@ cgraph_finalize_compilation_unit (void)
       fprintf (cgraph_dump_file, "\n\nReclaimed ");
       dump_cgraph (cgraph_dump_file);
     }
+  first_analyzed = cgraph_nodes;
   ggc_collect ();
   timevar_pop (TV_CGRAPH);
 }
@@ -1766,9 +1863,16 @@ cgraph_optimize (void)
   verify_cgraph ();
 #endif
   if (!flag_unit_at_a_time)
-    return;
+    {
+      cgraph_varpool_assemble_pending_decls ();
+      return;
+    }
 
   process_pending_assemble_externals ();
+  
+  /* 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.  */
+  cgraph_varpool_analyze_pending_decls ();
 
   timevar_push (TV_CGRAPHOPT);
   if (!quiet_flag)
@@ -1788,6 +1892,7 @@ cgraph_optimize (void)
     {
       fprintf (cgraph_dump_file, "Optimized ");
       dump_cgraph (cgraph_dump_file);
+      dump_varpool (cgraph_dump_file);
     }
   timevar_pop (TV_CGRAPHOPT);
 
@@ -1799,8 +1904,11 @@ cgraph_optimize (void)
 #endif
   
   cgraph_mark_functions_to_output ();
-  
   cgraph_expand_all_functions ();
+  cgraph_varpool_remove_unreferenced_decls ();
+
+  cgraph_varpool_assemble_pending_decls ();
+
   if (cgraph_dump_file)
     {
       fprintf (cgraph_dump_file, "\nFinal ");
index 1e9165f..fffc5f3 100644 (file)
@@ -5889,10 +5889,6 @@ output_pic_addr_const (FILE *file, rtx x, int code)
       break;
 
     case SYMBOL_REF:
-     /* Mark the decl as referenced so that cgraph will output the function.  */
-     if (SYMBOL_REF_DECL (x))
-       mark_decl_referenced (SYMBOL_REF_DECL (x));
-
       assemble_name (file, XSTR (x, 0));
       if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
        fputs ("@PLT", file);
index 859be9d..d232838 100644 (file)
@@ -1,3 +1,8 @@
+2005-03-31  Jan Hubicka  <jh@suse.cz>
+
+       * decl2.c (finish_objects): Mark ctor as needed.
+       (cp_finish_file): Output variables only in nonunit-at-a-time.
+
 2005-03-29  Richard Henderson  <rth@redhat.com>
 
        PR c/20519
index 474e04e..78ba602 100644 (file)
@@ -2110,6 +2110,7 @@ finish_objects (int method_type, int initp, tree body)
   if (targetm.have_ctors_dtors)
     {
       rtx fnsym = XEXP (DECL_RTL (fn), 0);
+      cgraph_mark_needed_node (cgraph_node (fn));
       if (method_type == 'I')
        (* targetm.asm_out.constructor) (fnsym, initp);
       else
@@ -2959,9 +2960,9 @@ cp_finish_file (void)
       /* Ask the back end to emit functions and variables that are
         enqueued.  These emissions may result in marking more entities
         as needed.  */
-      if (cgraph_assemble_pending_functions ())
+      if (!flag_unit_at_a_time && cgraph_assemble_pending_functions ())
        reconsider = true;
-      if (cgraph_varpool_assemble_pending_decls ())
+      if (!flag_unit_at_a_time && cgraph_varpool_assemble_pending_decls ())
        reconsider = true;
 
       retries++;
index b46ec5b..3b11a3e 100644 (file)
@@ -1,3 +1,11 @@
+2005-03-31  Jan Hubicka  <jh@suse.cz>
+
+       * Make-lang.in (class.o, decl.o): Depend on cgraph.h.
+       * class.c: Include cgraph.h
+       (make_local_functoin_alias): Mark aslias as needed.
+       * resource.c: Include cgraph.h
+       (compile_resource_data): Go via cgraph interface.
+
 2005-03-30  Ian Lance Taylor  <ian@airs.com>
 
        * parse.y (maybe_yank_clinit): Don't crash if bbody is NULL.
index a6d2013..face962 100644 (file)
@@ -299,13 +299,13 @@ java/check-init.o: java/check-init.c $(CONFIG_H) $(JAVA_TREE_H) $(SYSTEM_H) \
   coretypes.h $(TM_H) toplev.h
 java/class.o: java/class.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   $(JAVA_TREE_H) $(RTL_H) java/jcf.h java/parse.h toplev.h output.h $(GGC_H) \
-  $(TARGET_H) function.h gt-java-class.h
+  $(TARGET_H) function.h gt-java-class.h cgraph.h
 java/constants.o: java/constants.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
   toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-constants.h
 java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) $(RTL_H) java/jcf.h \
   toplev.h flags.h $(SYSTEM_H) coretypes.h $(TM_H) function.h expr.h \
   libfuncs.h except.h java/java-except.h $(GGC_H) real.h gt-java-decl.h \
-  target.h
+  target.h cgraph.h
 java/except.o: java/except.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \
   $(RTL_H) java/javaop.h java/java-opcodes.h except.h java/java-except.h \
   toplev.h $(SYSTEM_H) coretypes.h $(TM_H) function.h 
index 5e2e535..1c7c3ab 100644 (file)
@@ -45,6 +45,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "except.h"
 #include "cgraph.h"
 #include "tree-iterator.h"
+#include "cgraph.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -910,6 +911,7 @@ build_utf8_ref (tree name)
   layout_decl (decl, 0);
   pushdecl (decl);
   rest_of_decl_compilation (decl, global_bindings_p (), 0);
+  cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
   utf8_decl_list = decl;
   make_decl_rtl (decl);
   ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
@@ -2436,8 +2438,11 @@ emit_register_classes (tree *list_p)
       named_section_flags (JCR_SECTION_NAME, SECTION_WRITE);
       assemble_align (POINTER_SIZE);
       for (t = registered_class; t; t = TREE_CHAIN (t))
-       assemble_integer (XEXP (DECL_RTL (t), 0),
-                         POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+       {
+         mark_decl_referenced (t);
+         assemble_integer (XEXP (DECL_RTL (t), 0),
+                           POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+       }
 #else
       /* A target has defined TARGET_USE_JCR_SECTION, but doesn't have a
         JCR_SECTION_NAME.  */
index 7f7d72a..5f11810 100644 (file)
@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "target.h"
 #include "expr.h"
 #include "tree-iterator.h"
+#include "cgraph.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -93,7 +94,7 @@ compile_resource_data (const char *name, const char *buffer, int length)
   pushdecl (decl);
   rest_of_decl_compilation (decl, global_bindings_p (), 0);
   make_decl_rtl (decl);
-  assemble_variable (decl, 1, 0, 0);
+  cgraph_varpool_finalize_decl (decl);
 
   resources = tree_cons (NULL_TREE, decl, resources);
 }
index 17e42c4..988f4f2 100644 (file)
@@ -225,7 +225,7 @@ rest_of_decl_compilation (tree decl,
         (see gcc.c-torture/compile/920624-1.c) */
       if ((at_end
           || !DECL_DEFER_OUTPUT (decl)
-          || (flag_unit_at_a_time && DECL_INITIAL (decl)))
+          || DECL_INITIAL (decl))
          && !DECL_EXTERNAL (decl))
        {
          if (flag_unit_at_a_time && !cgraph_global_info_ready
index 35bc042..411540f 100644 (file)
@@ -1,3 +1,7 @@
+2005-03-31  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.dg/varpool-1.c: New testcase.
+
 2005-03-30  Joseph S. Myers  <joseph@codesourcery.com>
 
        PR c/772
diff --git a/gcc/testsuite/gcc.dg/varpool-1.c b/gcc/testsuite/gcc.dg/varpool-1.c
new file mode 100644 (file)
index 0000000..48f1cd3
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "unnecesary_static_initialized_variable" } } */
+
+static int unnecesary_static_initialized_variable;
+static int *unnecesary_static_initialized_variable2 =
+  &unnecesary_static_initialized_variable;
+static inline
+simplify_after_inline (int param1, int *param2)
+{
+  if (unnecesary_static_initialized_variable != param1)
+    return unnecesary_static_initialized_variable;
+  if (unnecesary_static_initialized_variable2 != param2)
+    return unnecesary_static_initialized_variable;
+}
+
+main ()
+{
+  return simplify_after_inline (unnecesary_static_initialized_variable,
+                               unnecesary_static_initialized_variable2) +
+    simplify_after_inline (unnecesary_static_initialized_variable,
+                          unnecesary_static_initialized_variable2);
+}
index 5895d37..8cfd740 100644 (file)
@@ -781,11 +781,11 @@ wrapup_global_declarations (tree *vec, int len)
              bool needed = 1;
              node = cgraph_varpool_node (decl);
 
-             if (flag_unit_at_a_time && node->finalized)
+             if (node->finalized)
                needed = 0;
              else if (node->alias)
                needed = 0;
-             else if ((flag_unit_at_a_time && !cgraph_global_info_ready)
+             else if (!cgraph_global_info_ready
                       && (TREE_USED (decl)
                           || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
                /* needed */;
index bb31a0e..63131af 100644 (file)
@@ -660,6 +660,16 @@ tree_rest_of_compilation (tree fndecl)
          timevar_pop (TV_INTEGRATION);
        }
     }
+  /* We are not going to maintain the cgraph edges up to date.
+     Kill it so it won't confuse us.  */
+  while (node->callees)
+    {
+      /* In non-unit-at-a-time we must mark all referenced functions as needed.
+         */
+      if (node->callees->callee->analyzed && !flag_unit_at_a_time)
+        cgraph_mark_needed_node (node->callees->callee);
+      cgraph_remove_edge (node->callees);
+    }
 
   /* We are not going to maintain the cgraph edges up to date.
      Kill it so it won't confuse us.  */
index cf323f4..9210c41 100644 (file)
@@ -1883,7 +1883,13 @@ mark_decl_referenced (tree decl)
         cgraph_mark_needed_node (cgraph_node (decl));
     }
   else if (TREE_CODE (decl) == VAR_DECL)
-    cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
+    {
+      struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
+      cgraph_varpool_mark_needed_node (node);
+      /* C++ frontend use mark_decl_references to force COMDAT variables
+         to be output that might appear dead otherwise.  */
+      node->force_output = true;
+    }
   /* else do nothing - we can get various sorts of CST nodes here,
      which do not need to be marked.  */
 }