OSDN Git Service

* sdbout.c (sdbout_one_type): Use TYPE_VALUES for enums, not
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index e6049cb..f946593 100644 (file)
@@ -1,5 +1,5 @@
 /* Control and data flow functions for trees.
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -65,13 +65,13 @@ clear_decl_rtl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
     {
     case VAR_DECL:
       nonstatic_p = !TREE_STATIC (t) && !DECL_EXTERNAL (t);
-      local_p = DECL_CONTEXT (t) == data;
+      local_p = decl_function_context (t) == data;
       break;
 
     case PARM_DECL:
     case LABEL_DECL:
       nonstatic_p = true;
-      local_p = DECL_CONTEXT (t) == data;
+      local_p = decl_function_context (t) == data;
       break;
 
     case RESULT_DECL:
@@ -96,6 +96,7 @@ void
 tree_rest_of_compilation (tree fndecl, bool nested_p)
 {
   location_t saved_loc;
+  struct cgraph_node *node, *saved_node = NULL;
 
   timevar_push (TV_EXPAND);
 
@@ -118,6 +119,39 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
 
+  node = cgraph_node (fndecl);
+
+  /* We might need the body of this function so that we can expand
+     it inline somewhere else.  This means not lowering some constructs
+     such as exception handling.  */
+  if (cgraph_preserve_function_body_p (fndecl))
+    {
+      if (!flag_unit_at_a_time)
+       {
+         struct cgraph_edge *e;
+
+         saved_node = cgraph_clone_node (node);
+         for (e = saved_node->callees; e; e = e->next_callee)
+           if (!e->inline_failed)
+             cgraph_clone_inlined_nodes (e, true);
+       }
+      cfun->saved_tree = save_body (fndecl, &cfun->saved_args);
+    }
+
+  if (flag_inline_trees)
+    {
+      struct cgraph_edge *e;
+      for (e = node->callees; e; e = e->next_callee)
+       if (!e->inline_failed || warn_inline)
+         break;
+      if (e)
+       {
+         timevar_push (TV_INTEGRATION);
+         optimize_inline_calls (fndecl);
+         timevar_pop (TV_INTEGRATION);
+       }
+    }
+
   /* If the function has a variably modified type, there may be
      SAVE_EXPRs in the parameter types.  Their context must be set to
      refer to this function; they cannot be expanded in the containing
@@ -131,7 +165,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   expand_function_start (fndecl, 0);
 
   /* Allow language dialects to perform special processing.  */
-  (*lang_hooks.rtl_expand.start) ();
+  lang_hooks.rtl_expand.start ();
 
   /* If this function is `main', emit a call to `__main'
      to run global initializers, etc.  */
@@ -141,7 +175,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
     expand_main_function ();
 
   /* Generate the RTL for this function.  */
-  (*lang_hooks.rtl_expand.stmt) (DECL_SAVED_TREE (fndecl));
+  lang_hooks.rtl_expand.stmt (DECL_SAVED_TREE (fndecl));
 
   /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
@@ -150,7 +184,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   immediate_size_expand = 1;
 
   /* Allow language dialects to perform special processing.  */
-  (*lang_hooks.rtl_expand.end) ();
+  lang_hooks.rtl_expand.end ();
 
   /* Generate rtl for function exit.  */
   expand_function_end ();
@@ -167,6 +201,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   /* Run the optimizers and output the assembler code for this function.  */
   rest_of_compilation (fndecl);
 
+
   /* Undo the GC context switch.  */
   if (nested_p)
     ggc_pop_context ();
@@ -195,21 +230,6 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
        }
     }
 
-  /* ??? Looks like some of this could be combined.  */
-
-  /* If possible, obliterate the body of the function so that it can
-     be garbage collected.  */
-  if (dump_enabled_p (TDI_all))
-    /* Keep the body; we're going to dump it.  */
-    ;
-  else if (DECL_INLINE (fndecl) && flag_inline_trees)
-    /* We might need the body of this function so that we can expand
-       it inline somewhere else.  */
-    ;
-  else
-    /* We don't need the body; blow it away.  */
-    DECL_SAVED_TREE (fndecl) = NULL;
-
   /* Since we don't need the RTL for this function anymore, stop pointing to
      it.  That's especially important for LABEL_DECLs, since you can reach all
      the instructions in the function from the CODE_LABEL stored in the
@@ -220,19 +240,44 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
                                clear_decl_rtl,
                                fndecl);
+  /* Restore original body if still needed.  */
+  if (cfun->saved_tree)
+    {
+      DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
+      DECL_ARGUMENTS (fndecl) = cfun->saved_args;
 
-  if (DECL_SAVED_INSNS (fndecl) == 0 && !nested_p && !flag_inline_trees)
+      /* When not in unit-at-a-time mode, we must preserve out of line copy
+        representing node before inlining.  Restore original outgoing edges
+        using clone we created earlier.  */
+      if (!flag_unit_at_a_time)
+       {
+         struct cgraph_edge *e;
+         while (node->callees)
+           cgraph_remove_edge (node->callees);
+         node->callees = saved_node->callees;
+         saved_node->callees = NULL;
+         for (e = saved_node->callees; e; e = e->next_callee)
+           e->caller = node;
+         cgraph_remove_node (saved_node);
+       }
+    }
+  else
     {
-      /* Stop pointing to the local nodes about to be freed.
-        But DECL_INITIAL must remain nonzero so we know this
-        was an actual function definition.
-        For a nested function, this is done in c_pop_function_context.
-        If rest_of_compilation set this to 0, leave it 0.  */
-      if (DECL_INITIAL (fndecl) != 0)
-       DECL_INITIAL (fndecl) = error_mark_node;
-
-      DECL_ARGUMENTS (fndecl) = 0;
+      DECL_SAVED_TREE (fndecl) = NULL;
+      if (cgraph_node (fndecl)->origin)
+       {
+         /* Stop pointing to the local nodes about to be freed.
+            But DECL_INITIAL must remain nonzero so we know this
+            was an actual function definition.
+            For a nested function, this is done in c_pop_function_context.
+            If rest_of_compilation set this to 0, leave it 0.  */
+         if (DECL_INITIAL (fndecl) != 0)
+           DECL_INITIAL (fndecl) = error_mark_node;
+       }
     }
+  free_after_compilation (cfun);
+  cfun = 0;
+  DECL_STRUCT_FUNCTION (fndecl) = 0;
 
   input_location = saved_loc;