OSDN Git Service

* config/mips/t-iris6 (CRTSTUFF_T_CFLAGS): Add -Wno-error.
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index 5f89a58..d2d4d4c 100644 (file)
@@ -49,6 +49,7 @@ static void cgraph_mark_local_functions (void);
 static void cgraph_optimize_function (struct cgraph_node *);
 static bool cgraph_default_inline_p (struct cgraph_node *n);
 static void cgraph_analyze_function (struct cgraph_node *node);
+static void cgraph_decide_inlining_incrementally (struct cgraph_node *);
 
 /* Statistics we collect about inlining algorithm.  */
 static int ncalls_inlined;
@@ -114,7 +115,7 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
          /* When declared inline, defer even the uninlinable functions.
             This allows them to be eliminated when unused.  */
          && !DECL_DECLARED_INLINE_P (decl) 
-         && (node->local.inlinable || !cgraph_default_inline_p (node))))
+         && (!node->local.inlinable || !cgraph_default_inline_p (node))))
     return true;
 
   return false;
@@ -206,7 +207,10 @@ cgraph_finalize_function (tree decl, bool nested)
   /* 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);
+    {
+      cgraph_analyze_function (node);
+      cgraph_decide_inlining_incrementally (node);
+    }
 
   if (decide_is_function_needed (node, decl))
     cgraph_mark_needed_node (node);
@@ -482,7 +486,6 @@ static void
 cgraph_expand_function (struct cgraph_node *node)
 {
   tree decl = node->decl;
-  struct cgraph_edge *e;
 
   if (flag_unit_at_a_time)
     announce_function (decl);
@@ -493,21 +496,8 @@ cgraph_expand_function (struct cgraph_node *node)
      via lang_expand_decl_stmt.  */
   (*lang_hooks.callgraph.expand_function) (decl);
 
-  if (!flag_unit_at_a_time)
-    {
-       if (!node->local.inlinable
-          || (!node->local.disregard_inline_limits
-              && !cgraph_default_inline_p (node)))
-        DECL_SAVED_TREE (node->decl) = NULL;
-    }
-  else
-    {
-      for (e = node->callers; e; e = e->next_caller)
-       if (e->inline_call)
-         break;
-      if (!e)
-       DECL_SAVED_TREE (decl) = NULL;
-    }
+  if (!cgraph_function_possibly_inlined_p (decl))
+    DECL_SAVED_TREE (decl) = NULL;
   current_function_decl = NULL;
 }
 
@@ -829,6 +819,7 @@ cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what,
   bool called = false;
   int new_insns;
 
+  what->global.inlined = 1;
   for (e = what->callers; e; e = e->next_caller)
     {
       if (e->caller == to)
@@ -852,6 +843,7 @@ cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what,
   to->global.insns = new_insns;
 
   if (!called && !what->needed && !what->origin
+      && flag_unit_at_a_time
       && !DECL_EXTERNAL (what->decl))
     {
       if (!what->global.will_be_output)
@@ -939,7 +931,7 @@ cgraph_default_inline_p (struct cgraph_node *n)
    All inline candidates are put into prioritized heap based on estimated
    growth of the overall number of instructions and then update the estimates.
 
-   INLINED and INLINED_CALEES are just pointers to arrays large enought
+   INLINED and INLINED_CALEES are just pointers to arrays large enough
    to be passed to cgraph_inlined_into and cgraph_inlined_callees.  */
 
 static void
@@ -1080,7 +1072,7 @@ cgraph_decide_inlining (void)
     xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
   int ninlined;
   int ninlined_callees;
-  int old_insns;
+  int old_insns = 0;
   int i, y;
 
   for (node = cgraph_nodes; node; node = node->next)
@@ -1221,6 +1213,59 @@ cgraph_decide_inlining (void)
   free (inlined_callees);
 }
 
+/* Decide on the inlining.  We do so in the topological order to avoid
+   expenses on updating datastructures.  */
+
+static void
+cgraph_decide_inlining_incrementally (struct cgraph_node *node)
+{
+  struct cgraph_edge *e;
+  struct cgraph_node **inlined =
+    xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes);
+  struct cgraph_node **inlined_callees =
+    xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes);
+  int ninlined;
+  int ninlined_callees;
+  int y;
+
+  ninlined = cgraph_inlined_into (node, inlined);
+
+  /* First of all look for always inline functions.  */
+  for (e = node->callees; e; e = e->next_callee)
+    if (e->callee->local.disregard_inline_limits && !e->callee->output
+       && e->callee != node && !e->inline_call)
+      {
+       ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
+       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;
+      }
+
+  /* Now do the automatic inlining.  */
+  for (e = node->callees; e; e = e->next_callee)
+    if (e->callee->local.inlinable && !e->callee->output
+       && e->callee != node && !e->inline_call
+        && cgraph_default_inline_p (e->callee)
+       && cgraph_check_inline_limits (node, e->callee, inlined,
+                                      ninlined))
+      {
+       ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
+       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;
+      }
+
+  /* Clear the flags set by cgraph_inlined_into.  */
+  for (y = 0; y < ninlined; y++)
+    inlined[y]->output = 0, node->aux = 0;
+
+  free (inlined);
+  free (inlined_callees);
+}
+
+
 /* Return true when CALLER_DECL should be inlined into CALLEE_DECL.  */
 
 bool