OSDN Git Service

* cgraph.c (cgraph_nodes_queue): Declare.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Jun 2003 21:11:44 +0000 (21:11 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Jun 2003 21:11:44 +0000 (21:11 +0000)
(eq_node): Take identifier as p2.
(cgraph_node): Update htab_find_slot_with_hash call.
(cgraph_node_for_identifier): New.
(cgraph_mark_needed_node): Move here from cgraphunit.c.
* cgraph.h (cgraph_nodes_queue): Declare.
(cgraph_node_for_identifier): Declare.
* cgraphunit.c (cgraph_finalize_function): Collect entry points here
instead of in cgraph_finalize_compilation_unit; constructors and
destructors are entry points.
(cgraph_finalize_compilation_unit): Reorganize debug outout;
examine nested functions after lowerng; call collect_functions hook.
(cgraph_mark_local_functions): DECL_COMDAT functions are not local.
(cgraph_finalize_compilation_unit): Do not collect entry points.
* varasm.c: Include cgraph.h
(assemble_name): Mark referenced identifier as needed.

* cgraphunit.c (record_call_1): Use get_callee_fndecl.

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

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/varasm.c

index bb5a5ec..ee9dab6 100644 (file)
@@ -1,3 +1,24 @@
+Mon Jun 23 23:07:35 CEST 2003  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_nodes_queue): Declare.
+       (eq_node): Take identifier as p2.
+       (cgraph_node): Update htab_find_slot_with_hash call.
+       (cgraph_node_for_identifier): New.
+       (cgraph_mark_needed_node): Move here from cgraphunit.c.
+       * cgraph.h (cgraph_nodes_queue): Declare.
+       (cgraph_node_for_identifier): Declare.
+       * cgraphunit.c (cgraph_finalize_function): Collect entry points here
+       instead of in cgraph_finalize_compilation_unit; constructors and
+       destructors are entry points.
+       (cgraph_finalize_compilation_unit): Reorganize debug outout; 
+       examine nested functions after lowerng; call collect_functions hook.
+       (cgraph_mark_local_functions): DECL_COMDAT functions are not local.
+       (cgraph_finalize_compilation_unit): Do not collect entry points.
+       * varasm.c: Include cgraph.h
+       (assemble_name): Mark referenced identifier as needed.
+
+       * cgraphunit.c (record_call_1): Use get_callee_fndecl.
+
 2003-06-23  Jakub Jelinek  <jakub@redhat.com>
 
        * config/i386/i386.c (x86_output_mi_thunk): Don't pass MEM to %P0,
index 82e367f..b5753a1 100644 (file)
@@ -48,6 +48,9 @@ static htab_t cgraph_hash = 0;
 /* The linked list of cgraph nodes.  */
 struct cgraph_node *cgraph_nodes;
 
+/* Queue of cgraph nodes scheduled to be lowered.  */
+struct cgraph_node *cgraph_nodes_queue;
+
 /* Number of nodes in existence.  */
 int cgraph_n_nodes;
 
@@ -79,7 +82,7 @@ eq_node (p1, p2)
      const void *p2;
 {
   return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
-         DECL_ASSEMBLER_NAME ((tree) p2));
+         (tree) p2);
 }
 
 /* Return cgraph node assigned to DECL.  Create new one when needed.  */
@@ -100,7 +103,8 @@ cgraph_node (decl)
     }
 
   slot =
-    (struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, decl,
+    (struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash,
+                                                     DECL_ASSEMBLER_NAME (decl),
                                                      htab_hash_pointer
                                                      (DECL_ASSEMBLER_NAME
                                                       (decl)), 1);
@@ -125,6 +129,30 @@ cgraph_node (decl)
   return node;
 }
 
+/* Try to find existing function for identifier ID.  */
+struct cgraph_node *
+cgraph_node_for_identifier (id)
+     tree id;
+{
+  struct cgraph_node **slot;
+
+  if (TREE_CODE (id) != IDENTIFIER_NODE)
+    abort ();
+
+  if (!cgraph_hash)
+    {
+      cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
+      VARRAY_TREE_INIT (known_fns, 32, "known_fns");
+    }
+
+  slot =
+    (struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, id,
+                                                     htab_hash_pointer (id), 0);
+  if (!slot)
+    return NULL;
+  return *slot;
+}
+
 /* Create edge from CALLER to CALLEE in the cgraph.  */
 
 static struct cgraph_edge *
@@ -194,6 +222,28 @@ cgraph_remove_node (node)
   /* Do not free the structure itself so the walk over chain can continue.  */
 }
 
+/* Notify finalize_compilation_unit that given node is reachable
+   or needed.  */
+void
+cgraph_mark_needed_node (node, needed)
+     struct cgraph_node *node;
+     int needed;
+{
+  if (needed)
+    {
+      node->needed = 1;
+    }
+  if (!node->reachable)
+    {
+      node->reachable = 1;
+      if (DECL_SAVED_TREE (node->decl))
+       {
+         node->aux = cgraph_nodes_queue;
+         cgraph_nodes_queue = node;
+        }
+    }
+}
+
 
 /* Record call from CALLER to CALLEE  */
 
index b785e17..d29e190 100644 (file)
@@ -100,6 +100,7 @@ struct cgraph_edge
 extern struct cgraph_node *cgraph_nodes;
 extern int cgraph_n_nodes;
 extern bool cgraph_global_info_ready;
+extern struct cgraph_node *cgraph_nodes_queue;
 
 /* In cgraph.c  */
 void dump_cgraph                       PARAMS ((FILE *));
@@ -107,6 +108,7 @@ void cgraph_remove_call                     PARAMS ((tree, tree));
 void cgraph_remove_node                        PARAMS ((struct cgraph_node *));
 struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
 struct cgraph_node *cgraph_node                PARAMS ((tree decl));
+struct cgraph_node *cgraph_node_for_identifier PARAMS ((tree id));
 bool cgraph_calls_p                    PARAMS ((tree, tree));
 struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
 struct cgraph_global_info *cgraph_global_info PARAMS ((tree));
index a306908..9fc5dd0 100644 (file)
@@ -55,7 +55,29 @@ cgraph_finalize_function (decl, body)
 
   node->decl = decl;
 
-  node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
+  if (/* Externally visible functions must be output.  The exception are
+        COMDAT functions that must be output only when they are needed.
+        Similarly are handled defered functions and
+        external functions (GCC extension "extern inline") */
+      (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+      /* ??? Constructors and destructors not called otherwise can be inlined
+        into single construction/destruction function per section to save some
+        resources.  For now just mark it as reachable.  */
+      || DECL_STATIC_CONSTRUCTOR (decl)
+      || DECL_STATIC_DESTRUCTOR (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_mark_needed_node (node, 1);
+    }
+
+  if (!node->needed && !DECL_COMDAT (node->decl))
+    node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
+  else
+    node->local.can_inline_once = 0;
   if (flag_inline_trees)
     node->local.inline_many = tree_inlinable_function_p (decl, 0);
   else
@@ -64,33 +86,6 @@ cgraph_finalize_function (decl, body)
   (*debug_hooks->deferred_inline_function) (decl);
 }
 
-static struct cgraph_node *queue = NULL;
-
-/* Notify finalize_compilation_unit that given node is reachable
-   or needed.  */
-
-void
-cgraph_mark_needed_node (node, needed)
-     struct cgraph_node *node;
-     int needed;
-{
-  if (needed)
-    {
-      if (DECL_SAVED_TREE (node->decl))
-        announce_function (node->decl);
-      node->needed = 1;
-    }
-  if (!node->reachable)
-    {
-      node->reachable = 1;
-      if (DECL_SAVED_TREE (node->decl))
-       {
-         node->aux = queue;
-         queue = node;
-        }
-    }
-}
-
 /* Walk tree and record all calls.  Called via walk_tree.  */
 static tree
 record_call_1 (tp, walk_subtrees, data)
@@ -108,15 +103,8 @@ record_call_1 (tp, walk_subtrees, data)
     }
   else if (TREE_CODE (*tp) == CALL_EXPR)
     {
-      /* We cannot use get_callee_fndecl here because it actually tries
-        too hard to get the function declaration, looking for indirect
-        references and stripping NOPS.  As a result, get_callee_fndecl
-        finds calls that shouldn't be in the call graph.  */
-
-      tree decl = TREE_OPERAND (*tp, 0);
-      if (TREE_CODE (decl) == ADDR_EXPR)
-       decl = TREE_OPERAND (decl, 0);
-      if (TREE_CODE (decl) == FUNCTION_DECL)
+      tree decl = get_callee_fndecl (*tp);
+      if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        {
          if (DECL_BUILT_IN (decl))
            return NULL;
@@ -156,40 +144,31 @@ cgraph_finalize_compilation_unit ()
   struct cgraph_node *node;
   struct cgraph_edge *edge;
 
-  /* Collect entry points to the unit.  */
-
   if (!quiet_flag)
-    fprintf (stderr, "\n\nUnit entry points:");
-
-  for (node = cgraph_nodes; node; node = node->next)
     {
-      tree decl = node->decl;
-
-      if (!DECL_SAVED_TREE (decl))
-       continue;
-      if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
-         || (DECL_ASSEMBLER_NAME_SET_P (decl)
-             && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
-       {
-         /* This function can be called from outside this compliation
-            unit, so it most definitely is needed.  */
-         cgraph_mark_needed_node (node, 1);
-       }
+      fprintf (stderr, "\n\nInitial entry points:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->needed && DECL_SAVED_TREE (node->decl))
+         announce_function (node->decl);
     }
 
   /* 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 (queue)
+  while (cgraph_nodes_queue)
     {
-      tree decl = queue->decl;
+      tree decl = cgraph_nodes_queue->decl;
+
+      node = cgraph_nodes_queue;
+      cgraph_nodes_queue = cgraph_nodes_queue->aux;
 
-      node = queue;
-      queue = queue->aux;
       if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
        abort ();
 
+      if (lang_hooks.callgraph.lower_function)
+       (*lang_hooks.callgraph.lower_function) (decl);
+
       /* At the moment frontend automatically emits all nested functions.  */
       if (node->nested)
        {
@@ -200,9 +179,6 @@ cgraph_finalize_compilation_unit ()
              cgraph_mark_needed_node (node2, 0);
        }
 
-      if (lang_hooks.callgraph.lower_function)
-       (*lang_hooks.callgraph.lower_function) (decl);
-
       /* First kill forward declaration so reverse inling works properly.  */
       cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
 
@@ -213,6 +189,15 @@ cgraph_finalize_compilation_unit ()
        }
       node->lowered = true;
     }
+  /* Collect entry points to the unit.  */
+
+  if (!quiet_flag)
+    {
+      fprintf (stderr, "\n\nUnit entry points:");
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->needed && DECL_SAVED_TREE (node->decl))
+         announce_function (node->decl);
+    }
 
   if (!quiet_flag)
     fprintf (stderr, "\n\nReclaiming functions:");
@@ -248,7 +233,8 @@ cgraph_mark_functions_to_output ()
          && (node->needed
              || (!node->local.inline_many && !node->global.inline_once
                  && node->reachable)
-             || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+             || (DECL_ASSEMBLER_NAME_SET_P (decl)
+                 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
          && !TREE_ASM_WRITTEN (decl) && !node->origin
          && !DECL_EXTERNAL (decl))
        node->output = 1;
@@ -331,7 +317,7 @@ cgraph_expand_functions ()
   for (node = cgraph_nodes; node; node = node->next)
     node->aux = NULL;
   for (node = cgraph_nodes; node; node = node->next)
-    if (node->output && !node->aux)
+    if (!node->aux)
       {
        node2 = node;
        if (!node->callers)
@@ -400,6 +386,7 @@ cgraph_mark_local_functions ()
     {
       node->local.local = (!node->needed
                           && DECL_SAVED_TREE (node->decl)
+                          && !DECL_COMDAT (node->decl)
                           && !TREE_PUBLIC (node->decl));
       if (node->local.local)
        announce_function (node->decl);
index 091bbb3..a464e32 100644 (file)
@@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm_p.h"
 #include "debug.h"
 #include "target.h"
+#include "cgraph.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"          /* Needed for external data
@@ -1742,7 +1743,16 @@ assemble_name (file, name)
 
   id = maybe_get_identifier (real_name);
   if (id)
-    TREE_SYMBOL_REFERENCED (id) = 1;
+    {
+      if (!TREE_SYMBOL_REFERENCED (id)
+         && !cgraph_global_info_ready)
+       {
+         struct cgraph_node *node = cgraph_node_for_identifier (id);
+         if (node)
+           cgraph_mark_needed_node (node, 1);
+       }
+      TREE_SYMBOL_REFERENCED (id) = 1;
+    }
 
   if (name[0] == '*')
     fputs (&name[1], file);