cgraph.c (cgraph_mark_reachable_node): Split out from ...
authorRichard Henderson <rth@redhat.com>
Fri, 5 Sep 2003 04:24:30 +0000 (21:24 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 5 Sep 2003 04:24:30 +0000 (21:24 -0700)
        * cgraph.c (cgraph_mark_reachable_node): Split out from ...
        (cgraph_mark_needed_node): Remove needed argument.
        * cgraph.h: Update to match.
        * cgraphunit.c (decide_is_function_needed): Split out from ...
        (cgraph_finalize_function): Reorg.  Avoid deferred_inline_function
        if we generated the function.
        (record_call_1): Update for cgraph_mark_reachable_node.
        * varasm.c (mark_referenced): Likewise.
        * objc/objc-act.c (mark_referenced_methods): Likewise.

        * decl2.c (mark_member_pointers_and_eh_handlers): Update for
        change in cgraph_mark_needed_node arguments.

From-SVN: r71104

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/objc/objc-act.c
gcc/varasm.c

index 8ecc67dff6c78710120a78fabd1cc585e2fff3b9..92437ba59e877cabbb5e0e8179857ffebb45aad2 100644 (file)
@@ -1,3 +1,15 @@
+2003-09-04  Richard Henderson  <rth@redhat.com>
+
+       * cgraph.c (cgraph_mark_reachable_node): Split out from ...
+       (cgraph_mark_needed_node): Remove needed argument.
+       * cgraph.h: Update to match.
+       * cgraphunit.c (decide_is_function_needed): Split out from ...
+       (cgraph_finalize_function): Reorg.  Avoid deferred_inline_function
+       if we generated the function.
+       (record_call_1): Update for cgraph_mark_reachable_node.
+       * varasm.c (mark_referenced): Likewise.
+       * objc/objc-act.c (mark_referenced_methods): Likewise.
+
 2003-09-04  DJ Delorie  <dj@redhat.com>
 
        * targhooks.c: Add comment explaining the migration process.
index bd83f6a194636dba39b3bd84cb5853df75d22672..8b4c0ccf13d39cbaf26e94b19f3a07865eea4852 100644 (file)
@@ -234,14 +234,11 @@ cgraph_remove_node (struct cgraph_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.  */
+/* Notify finalize_compilation_unit that given node is reachable.  */
+
 void
-cgraph_mark_needed_node (struct cgraph_node *node, int needed)
+cgraph_mark_reachable_node (struct cgraph_node *node)
 {
-  if (needed)
-    node->needed = 1;
-
   if (!node->reachable && DECL_SAVED_TREE (node->decl))
     {
       node->reachable = 1;
@@ -257,11 +254,20 @@ cgraph_mark_needed_node (struct cgraph_node *node, int needed)
 
          for (node2 = node->nested; node2; node2 = node2->next_nested)
            if (!node2->reachable)
-             cgraph_mark_needed_node (node2, 0);
+             cgraph_mark_reachable_node (node2);
        }
     }
 }
 
+/* Likewise indicate that a node is needed, i.e. reachable via some
+   external means.  */
+
+void
+cgraph_mark_needed_node (struct cgraph_node *node)
+{
+  node->needed = 1;
+  cgraph_mark_reachable_node (node);
+}
 
 /* Record call from CALLER to CALLEE  */
 
index f96ac0d0d59ab1483303a1f242a58c3ed6b5b9dd..aaa09a201e8858b6874bce7f45bb06beca3fb43d 100644 (file)
@@ -173,7 +173,8 @@ void cgraph_finalize_function (tree, tree);
 void cgraph_finalize_compilation_unit (void);
 void cgraph_create_edges (tree, tree);
 void cgraph_optimize (void);
-void cgraph_mark_needed_node (struct cgraph_node *, int);
+void cgraph_mark_needed_node (struct cgraph_node *);
+void cgraph_mark_reachable_node (struct cgraph_node *);
 bool cgraph_inline_p (tree, tree);
 
 #endif  /* GCC_CGRAPH_H  */
index 7188501c71972eade9e36e6bac72417d4ac9b6cf..1476c8b3b23ca04649f59e15d34bd0e93ce79140 100644 (file)
@@ -62,6 +62,64 @@ static int overall_insns;
    record_calls_1.  */
 static htab_t visited_nodes;
 
+/* Determine if function 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 havn't
+   seen yet.  */
+
+static bool
+decide_is_function_needed (struct cgraph_node *node, tree decl)
+{
+  /* If we decided it was needed before, but at the time we didn't have
+     the body of the function available, then it's still needed.  We have
+     to go back and re-check its dependencies now.  */
+  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;
+
+  /* Constructors and destructors are reachable from the runtime by
+     some mechanism.  */
+  if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
+    return true;
+
+  /* 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 (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.  */
+
+  /* "extern inline" functions are never output locally.  */
+  if (DECL_EXTERNAL (decl))
+    return false;
+  /* ??? */
+  if (node->origin)
+    return false;
+  if (!DECL_INLINE (decl)
+      || (!node->local.disregard_inline_limits
+         /* When declared inline, defer even the uninlinable functions.
+            This allows them to be elliminated when unused.  */
+         && !DECL_DECLARED_INLINE_P (decl) 
+         && (node->local.inlinable || !cgraph_default_inline_p (node))))
+    return true;
+
+  return false;
+}
+
 /* Analyze function once it is parsed.  Set up the local information
    available - create cgraph edges for function calls via BODY.  */
 
@@ -73,42 +131,16 @@ cgraph_finalize_function (tree decl, tree body ATTRIBUTE_UNUSED)
   node->decl = decl;
   node->local.finalized = true;
 
-  /* Function now has DECL_SAVED_TREE set.  Enqueue it into cgraph_nodes_queue
-     if needed.  */
-  if (node->needed)
-    cgraph_mark_needed_node (node, 0);
+  /* If not unit at a time, then we need to create the call graph
+     now, so that called functions can be queued and emitted now.  */
   if (!flag_unit_at_a_time)
     cgraph_analyze_function (node);
-  if (/* Externally visible functions must be output.  The exception are
-        COMDAT functions that must be output only when they are needed.
-        Similarly are handled deferred 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)))
-      || lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
-     cgraph_mark_needed_node (node, 1);
-  /* When not doing unit-at-a-time deffer only inline functions.  */
-  else if (!flag_unit_at_a_time
-          && !DECL_EXTERNAL (decl)
-          && !node->origin
-          && (!DECL_INLINE (decl)
-              || (!node->local.disregard_inline_limits
-                  /* When declared inline, deffer even the uninlinable functions.
-                     This allows them to be elliminated when unused.  */
-                  && !DECL_DECLARED_INLINE_P (decl) 
-                  && (node->local.inlinable
-                      || !cgraph_default_inline_p (node)))))
-     cgraph_mark_needed_node (node, 1);
 
+  if (decide_is_function_needed (node, decl))
+    cgraph_mark_needed_node (node);
+
+  /* If not unit at a time, go ahead and emit everything we've
+     found to be reachable at this time.  */
   if (!flag_unit_at_a_time)
     while (cgraph_nodes_queue)
       {
@@ -118,7 +150,9 @@ cgraph_finalize_function (tree decl, tree body ATTRIBUTE_UNUSED)
           cgraph_expand_function (n);
       }
 
-  (*debug_hooks->deferred_inline_function) (decl);
+  /* If we've not yet emitted decl, tell the debug info about it.  */
+  if (flag_unit_at_a_time || !node->reachable)
+    (*debug_hooks->deferred_inline_function) (decl);
 }
 
 /* Walk tree and record all calls.  Called via walk_tree.  */
@@ -133,7 +167,7 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
     {
       tree decl = TREE_OPERAND (*tp, 0);
       if (TREE_CODE (decl) == FUNCTION_DECL)
-        cgraph_mark_needed_node (cgraph_node (decl), 1);
+        cgraph_mark_needed_node (cgraph_node (decl));
     }
   else if (TREE_CODE (*tp) == CALL_EXPR)
     {
@@ -251,13 +285,14 @@ cgraph_finalize_compilation_unit (void)
        abort ();
 
       cgraph_analyze_function (node);
+
       for (edge = node->callees; edge; edge = edge->next_callee)
-      {
        if (!edge->callee->reachable)
-           cgraph_mark_needed_node (edge->callee, 0);
-      }
+         cgraph_mark_reachable_node (edge->callee);
+
       cgraph_varpool_assemble_pending_decls ();
     }
+
   /* Collect entry points to the unit.  */
 
   if (cgraph_dump_file)
index ca8ea06d7fc8a6937b9973b1e22e796ed6cfdca4..6f8668c608af9670f0ccd95e5408f6e2da012b6c 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-04  Richard Henderson  <rth@redhat.com>
+
+       * decl2.c (mark_member_pointers_and_eh_handlers): Update for
+       change in cgraph_mark_needed_node arguments.
+
 2003-09-02  Geoffrey Keating  <geoffk@apple.com>
 
        PR 12161
index 7ca20c8ef309f7fd52b7a2249f6e3c0d19a192aa..20d97d469a09ec5ea9eec8b6427b96e12527f42c 100644 (file)
@@ -2570,7 +2570,7 @@ mark_member_pointers_and_eh_handlers (tree *tp,
     {
     case PTRMEM_CST:
       if (TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp)))
-       cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
+       cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)));
       break;
 
     /* EH handlers will emit EH tables referencing typeinfo.  */
index 10cc88912fca972e10e7ca2c8b7eb8e2993d1438..0e1c1beb92f57c6aa9fff2c91ed4874525a93263 100644 (file)
@@ -3981,13 +3981,14 @@ mark_referenced_methods ()
       chain = CLASS_CLS_METHODS (impent->imp_context);
       while (chain)
        {
-         cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1);
+         cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
          chain = TREE_CHAIN (chain);
        }
+
       chain = CLASS_NST_METHODS (impent->imp_context);
       while (chain)
        {
-         cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1);
+         cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
          chain = TREE_CHAIN (chain);
        }
     }
index ac535212056b69415ade6aace4efbfc264b1eb86..d327cb2d8c236e62ca9591793e9c2ea996e932fd 100644 (file)
@@ -1662,7 +1662,7 @@ mark_referenced (tree id)
        {
          node = cgraph_node_for_identifier (id);
          if (node)
-           cgraph_mark_needed_node (node, 1);
+           cgraph_mark_needed_node (node);
        }
 
       vnode = cgraph_varpool_node_for_identifier (id);