cgraph.c (cgraph_nodes_queue): Declare.
authorJan Hubicka <jh@suse.cz>
Mon, 23 Jun 2003 21:11:44 +0000 (23:11 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 23 Jun 2003 21:11:44 +0000 (21:11 +0000)
* 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.

From-SVN: r68390

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

index bb5a5ec1f60350246c906019b4262cb6ab84fdf9..ee9dab63280a327ea437eb38bec9e8fdea3ecdef 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 82e367f2929b67d7493217befab1828974de8873..b5753a12831dbd651d9e4a3fa958aa9f8c175468 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 b785e172665dd2ffbfa44d5375298ddf2c9aebf4..d29e190dbfd86c7c203422f99e2096a34768ecd5 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 a306908ac8e4fd4708735d0d96aee81a5135e6da..9fc5dd036b039f6e7f907bc2b1273c982a234111 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 091bbb312099c7b203dc49b7257420792ee478ea..a464e328b83a3b4293b5518c9a944837351fb626 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);