OSDN Git Service

* sdbout.c (sdbout_one_type): Use TYPE_VALUES for enums, not
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index e42fa06..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.
 
@@ -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 ();
@@ -205,11 +240,31 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
                                clear_decl_rtl,
                                fndecl);
-  if (!cgraph_function_possibly_inlined_p (fndecl))
+  /* Restore original body if still needed.  */
+  if (cfun->saved_tree)
+    {
+      DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
+      DECL_ARGUMENTS (fndecl) = cfun->saved_args;
+
+      /* 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
     {
       DECL_SAVED_TREE (fndecl) = NULL;
-      if (DECL_SAVED_INSNS (fndecl) == 0
-         && !cgraph_node (fndecl)->origin)
+      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
@@ -218,10 +273,11 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
             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;
        }
     }
+  free_after_compilation (cfun);
+  cfun = 0;
+  DECL_STRUCT_FUNCTION (fndecl) = 0;
 
   input_location = saved_loc;