]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cgraph.c (cgraph_remove_node): Fix removal from linked list.
authorJan Hubicka <jh@suse.cz>
Mon, 19 Jan 2004 09:43:53 +0000 (10:43 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 19 Jan 2004 09:43:53 +0000 (09:43 +0000)
* cgraph.c (cgraph_remove_node): Fix removal from linked list.
* cgraphunit.c (cgraph_finalize_compilation_unit): Clear next_needed
list.
(cgraph_remove_unreachable_nodes): New function
(cgraph_decide_inlining_of_small_function): Fix pasto.
(cgraph_decide_inlining_incrementally): Fix pasto.
(cgrpah_decide_inlining): Likewise; remove unreachable nodes.

From-SVN: r76142

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraphunit.c

index 5d732db1d6d1367682f7d7166edfc4a402ca287b..5287af437ac91bc5c0648d793ac2318fc8c2b6e6 100644 (file)
@@ -1,3 +1,13 @@
+2004-01-19  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (cgraph_remove_node): Fix removal from linked list.
+       * cgraphunit.c (cgraph_finalize_compilation_unit): Clear next_needed
+       list.
+       (cgraph_remove_unreachable_nodes): New function
+       (cgraph_decide_inlining_of_small_function): Fix pasto.
+       (cgraph_decide_inlining_incrementally): Fix pasto.
+       (cgrpah_decide_inlining): Likewise; remove unreachable nodes.
+
 2004-01-19  Steven Bosscher  <stevenb@suse.de>
 
        * gengtype.c (header_file): Make it static.
index ec3bcca34e7a4ff5e2ede98467025670814dc09a..57d0844beae22203921457c98192232fafc06bd1 100644 (file)
@@ -231,7 +231,7 @@ cgraph_remove_node (struct cgraph_node *node)
   if (node->previous)
     node->previous->next = node->next;
   else
-    cgraph_nodes = node;
+    cgraph_nodes = node->next;
   if (node->next)
     node->next->previous = node->previous;
   DECL_SAVED_TREE (node->decl) = NULL;
index 27e4d8d8d7ce7d57717e1fc8184bae1fabc4c1be..a883ebf6728ddb5ac5f8487cd437226ad4306e28 100644 (file)
@@ -436,6 +436,8 @@ cgraph_finalize_compilation_unit (void)
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
        }
+      else
+       node->next_needed = NULL;
     }
   if (cgraph_dump_file)
     {
@@ -792,6 +794,105 @@ cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
   return nfound;
 }
 
+/* Perform reachability analysis and reclaim all unreachable nodes.
+   This function also remove unneeded bodies of extern inline functions
+   and thus needs to be done only after inlining decisions has been made.  */
+static bool
+cgraph_remove_unreachable_nodes (void)
+{
+  struct cgraph_node *first = (void *) 1;
+  struct cgraph_node *node;
+  bool changed = false;
+  int insns = 0;
+
+  if (cgraph_dump_file)
+    fprintf (cgraph_dump_file, "\nReclaiming functions:");
+#ifdef ENABLE_CHECKING
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->aux)
+      abort ();
+#endif
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->needed && (!DECL_EXTERNAL (node->decl) || !node->analyzed))
+      {
+       node->aux = first;
+       first = node;
+      }
+    else if (node->aux)
+      abort ();
+
+  /* Perform reachability analysis.  As a special case do not consider
+     extern inline functions not inlined as live because we won't output
+     them at all.  */
+  while (first != (void *) 1)
+    {
+      struct cgraph_edge *e;
+      node = first;
+      first = first->aux;
+
+      for (e = node->callees; e; e = e->next_callee)
+       if (!e->callee->aux
+           && node->analyzed
+           && (!e->inline_failed || !e->callee->analyzed
+               || !DECL_EXTERNAL (e->callee->decl)))
+         {
+           e->callee->aux = first;
+           first = e->callee;
+         }
+    }
+
+  /* Remove unreachable nodes.  Extern inline functions need special care;
+     Unreachable extern inline functions shall be removed.
+     Reachable extern inline functions we never inlined shall get their bodies
+     elliminated
+     Reachable extern inline functions we sometimes inlined will be turned into
+     unanalyzed nodes so they look like for true extern functions to the rest
+     of code.  */
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      if (!node->aux)
+       {
+         int local_insns;
+         tree decl = node->decl;
+
+         if (DECL_SAVED_INSNS (decl))
+           local_insns = node->local.self_insns;
+         else
+           local_insns = 0;
+         if (cgraph_dump_file)
+           fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
+         if (!node->analyzed || !DECL_EXTERNAL (node->decl))
+           cgraph_remove_node (node);
+         else
+           {
+             struct cgraph_edge *e;
+
+             for (e = node->callers; e; e = e->next_caller)
+               if (e->caller->aux)
+                 break;
+             if (e || node->needed)
+               {
+                 DECL_SAVED_TREE (node->decl) = NULL_TREE;
+                 while (node->callees)
+                   cgraph_remove_edge (node, node->callees->callee);
+                 node->analyzed = false;
+               }
+             else
+               cgraph_remove_node (node);
+           }
+         if (!DECL_SAVED_TREE (decl))
+           insns += local_insns;
+         changed = true;
+       }
+    }
+  for (node = cgraph_nodes; node; node = node->next)
+    node->aux = NULL;
+  if (cgraph_dump_file)
+    fprintf (cgraph_dump_file, "\nReclaimed %i insns", insns);
+  return changed;
+}
+
+
 /* Estimate size of the function after inlining WHAT into TO.  */
 
 static int
@@ -1055,7 +1156,7 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
                                                ninlined, &e->inline_failed))
              {
                for (i = 0; i < ninlined; i++)
-                 inlined[i]->output = 0, node->aux = 0;
+                 inlined[i]->output = 0, inlined[i]->aux = 0;
                if (cgraph_dump_file)
                  fprintf (cgraph_dump_file, " Not inlining into %s.\n",
                           cgraph_node_name (e->caller));
@@ -1071,17 +1172,16 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
               the keys.  */
            for (i = 0; i < ninlined; i++)
              {
-               inlined[i]->output = 0, node->aux = 0;
+               inlined[i]->output = 0, inlined[i]->aux = 0;
                if (heap_node[inlined[i]->uid])
                  fibheap_replace_key (heap, heap_node[inlined[i]->uid],
                                       cgraph_estimate_growth (inlined[i]));
              }
-       if (cgraph_dump_file)
-         fprintf (cgraph_dump_file, 
-                  " Inlined into %s which now has %i insns.\n",
-                  cgraph_node_name (e->caller),
-                  e->caller->global.insns);
-
+           if (cgraph_dump_file)
+             fprintf (cgraph_dump_file, 
+                      " Inlined into %s which now has %i insns.\n",
+                      cgraph_node_name (e->caller),
+                      e->caller->global.insns);
          }
 
       /* Similarly all functions called by the function we just inlined
@@ -1101,7 +1201,8 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
              fibheap_replace_key (heap, heap_node[e->callee->uid],
                                   cgraph_estimate_growth (e->callee));
 
-         inlined_callees[i]->output = 0, node->aux = 0;
+         inlined_callees[i]->output = 0;
+         inlined_callees[i]->aux = 0;
        }
       if (cgraph_dump_file)
        fprintf (cgraph_dump_file, 
@@ -1150,6 +1251,11 @@ cgraph_decide_inlining (void)
 
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "\nInlining always_inline functions:\n");
+#ifdef ENABLE_CHECKING
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->aux || node->output)
+      abort ();
+#endif
 
   /* In the first pass mark all always_inline edges.  Do this with a priority
      so none of our later choices will make this impossible.  */
@@ -1185,7 +1291,7 @@ cgraph_decide_inlining (void)
          cgraph_mark_inline (node, e->callee, inlined, ninlined,
                              inlined_callees, ninlined_callees);
          for (y = 0; y < ninlined_callees; y++)
-           inlined_callees[y]->output = 0, node->aux = 0;
+           inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, 
                     " Inlined into %s which now has %i insns.\n",
@@ -1197,12 +1303,22 @@ cgraph_decide_inlining (void)
                 " Inlined %i times for a net change of %+i insns.\n",
                 node->global.cloned_times, overall_insns - old_insns);
       for (y = 0; y < ninlined; y++)
-       inlined[y]->output = 0, node->aux = 0;
+       inlined[y]->output = 0, inlined[y]->aux = 0;
     }
+#ifdef ENABLE_CHECKING
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->aux || node->output)
+      abort ();
+#endif
 
   if (!flag_really_no_inline)
     {
       cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
+#ifdef ENABLE_CHECKING
+      for (node = cgraph_nodes; node; node = node->next)
+       if (node->aux || node->output)
+         abort ();
+#endif
 
       if (cgraph_dump_file)
        fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
@@ -1251,7 +1367,7 @@ cgraph_decide_inlining (void)
                                          ninlined, inlined_callees,
                                          ninlined_callees);
                      for (y = 0; y < ninlined_callees; y++)
-                       inlined_callees[y]->output = 0, node->aux = 0;
+                       inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
                      if (cgraph_dump_file)
                        fprintf (cgraph_dump_file,
                                 " Inlined into %s which now has %i insns"
@@ -1267,11 +1383,12 @@ cgraph_decide_inlining (void)
                                 " Inline limit reached, not inlined.\n");
                    }
                  for (y = 0; y < ninlined; y++)
-                   inlined[y]->output = 0, node->aux = 0;
+                   inlined[y]->output = 0, inlined[y]->aux = 0;
                }
            }
        }
     }
+  cgraph_remove_unreachable_nodes ();
 
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file,
@@ -1317,7 +1434,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
        cgraph_mark_inline (node, e->callee, inlined, ninlined,
                            inlined_callees, ninlined_callees);
        for (y = 0; y < ninlined_callees; y++)
-         inlined_callees[y]->output = 0, node->aux = 0;
+         inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
       }
 
   if (!flag_really_no_inline)
@@ -1342,13 +1459,13 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
            cgraph_mark_inline (node, e->callee, inlined, ninlined,
                                inlined_callees, ninlined_callees);
            for (y = 0; y < ninlined_callees; y++)
-             inlined_callees[y]->output = 0, node->aux = 0;
+             inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
          }
     }
 
   /* Clear the flags set by cgraph_inlined_into.  */
   for (y = 0; y < ninlined; y++)
-    inlined[y]->output = 0, node->aux = 0;
+    inlined[y]->output = 0, inlined[y]->aux = 0;
 
   free (inlined);
   free (inlined_callees);