OSDN Git Service

2007-08-04 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index 86b6014..b4bd069 100644 (file)
@@ -1,12 +1,12 @@
 /* Top-level control of tree optimizations.
 /* Top-level control of tree optimizations.
-   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -47,50 +46,87 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "cgraph.h"
 #include "graph.h"
 #include "ggc.h"
 #include "cgraph.h"
 #include "graph.h"
+#include "cfgloop.h"
+#include "except.h"
 
 
 
 
-/* Global variables used to communicate with passes.  */
-int dump_flags;
-bitmap vars_to_rename;
-bool in_gimple_form;
+/* Gate: execute, or not, all of the non-trivial optimizations.  */
+
+static bool
+gate_all_optimizations (void)
+{
+  return (optimize >= 1
+         /* Don't bother doing anything if the program has errors. 
+            We have to pass down the queue if we already went into SSA */
+         && (!(errorcount || sorrycount) || gimple_in_ssa_p (cfun)));
+}
+
+struct tree_opt_pass pass_all_optimizations =
+{
+  NULL,                                        /* name */
+  gate_all_optimizations,              /* gate */
+  NULL,                                        /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0,                                   /* todo_flags_finish */
+  0                                    /* letter */
+};
 
 
-/* The root of the compilation pass tree, once constructed.  */
-static struct tree_opt_pass *all_passes;
+/* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 
-/* Pass: dump the gimplified, inlined, functions.  */
+static bool
+gate_all_early_local_passes (void)
+{
+         /* Don't bother doing anything if the program has errors.  */
+  return (!errorcount && !sorrycount);
+}
 
 
-static struct tree_opt_pass pass_gimple = 
+struct tree_opt_pass pass_early_local_passes =
 {
 {
-  "gimple",                            /* name */
-  NULL,                                        /* gate */
+  "early_local_cleanups",              /* name */
+  gate_all_early_local_passes,         /* gate */
   NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   0,                                   /* tv_id */
   0,                                   /* properties_required */
   NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   0,                                   /* tv_id */
   0,                                   /* properties_required */
-  PROP_gimple_any,                     /* properties_provided */
+  0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
+  TODO_remove_functions,               /* todo_flags_finish */
   0                                    /* letter */
 };
 
   0                                    /* letter */
 };
 
+static unsigned int
+execute_early_local_optimizations (void)
+{
+  if (flag_unit_at_a_time)
+    cgraph_state = CGRAPH_STATE_IPA_SSA;
+  return 0;
+}
+
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 static bool
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 static bool
-gate_all_optimizations (void)
+gate_all_early_optimizations (void)
 {
   return (optimize >= 1
          /* Don't bother doing anything if the program has errors.  */
          && !(errorcount || sorrycount));
 }
 
 {
   return (optimize >= 1
          /* Don't bother doing anything if the program has errors.  */
          && !(errorcount || sorrycount));
 }
 
-static struct tree_opt_pass pass_all_optimizations =
+struct tree_opt_pass pass_all_early_optimizations =
 {
 {
-  NULL,                                        /* name */
-  gate_all_optimizations,              /* gate */
-  NULL,                                        /* execute */
+  "early_optimizations",               /* name */
+  gate_all_early_optimizations,                /* gate */
+  execute_early_local_optimizations,   /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
@@ -108,17 +144,49 @@ static struct tree_opt_pass pass_all_optimizations =
    because after the tree optimizers have run such cleanups may
    be necessary.  */
 
    because after the tree optimizers have run such cleanups may
    be necessary.  */
 
-static void 
+static unsigned int
+execute_cleanup_cfg_pre_ipa (void)
+{
+  cleanup_tree_cfg ();
+  return 0;
+}
+
+struct tree_opt_pass pass_cleanup_cfg =
+{
+  "cleanup_cfg",                       /* name */
+  NULL,                                        /* gate */
+  execute_cleanup_cfg_pre_ipa,         /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_dump_func,                                      /* todo_flags_finish */
+  0                                    /* letter */
+};
+
+
+/* Pass: cleanup the CFG just before expanding trees to RTL.
+   This is just a round of label cleanups and case node grouping
+   because after the tree optimizers have run such cleanups may
+   be necessary.  */
+
+static unsigned int
 execute_cleanup_cfg_post_optimizing (void)
 {
 execute_cleanup_cfg_post_optimizing (void)
 {
+  fold_cond_expr_cond ();
   cleanup_tree_cfg ();
   cleanup_dead_labels ();
   group_case_labels ();
   cleanup_tree_cfg ();
   cleanup_dead_labels ();
   group_case_labels ();
+  return 0;
 }
 
 }
 
-static struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
+struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
 {
 {
-  NULL,                                        /* name */
+  "final_cleanup",                     /* name */
   NULL,                                        /* gate */
   execute_cleanup_cfg_post_optimizing, /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* gate */
   execute_cleanup_cfg_post_optimizing, /* execute */
   NULL,                                        /* sub */
@@ -129,38 +197,26 @@ static struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
+  TODO_dump_func,                                      /* todo_flags_finish */
   0                                    /* letter */
 };
 
 /* Pass: do the actions required to finish with tree-ssa optimization
    passes.  */
 
   0                                    /* letter */
 };
 
 /* Pass: do the actions required to finish with tree-ssa optimization
    passes.  */
 
-static void
+static unsigned int
 execute_free_datastructures (void)
 {
 execute_free_datastructures (void)
 {
-  tree *chain;
-
-  /* ??? This isn't the right place for this.  Worse, it got computed
-     more or less at random in various passes.  */
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
 
 
-  /* Emit gotos for implicit jumps.  */
-  disband_implicit_edges ();
-
-  /* Remove the ssa structures.  Do it here since this includes statement
-     annotations that need to be intact during disband_implicit_edges.  */
-  delete_tree_ssa ();
-
-  /* Re-chain the statements from the blocks.  */
-  chain = &DECL_SAVED_TREE (current_function_decl);
-  *chain = alloc_stmt_list ();
-
-  /* And get rid of annotations we no longer need.  */
-  delete_tree_cfg_annotations ();
+  /* Remove the ssa structures.  */
+  if (cfun->gimple_df)
+    delete_tree_ssa ();
+  return 0;
 }
 
 }
 
-static struct tree_opt_pass pass_free_datastructures =
+struct tree_opt_pass pass_free_datastructures =
 {
   NULL,                                        /* name */
   NULL,                                        /* gate */
 {
   NULL,                                        /* name */
   NULL,                                        /* gate */
@@ -176,23 +232,22 @@ static struct tree_opt_pass pass_free_datastructures =
   0,                                   /* todo_flags_finish */
   0                                    /* letter */
 };
   0,                                   /* todo_flags_finish */
   0                                    /* letter */
 };
+/* Pass: free cfg annotations.  */
 
 
-
-/* Do the actions required to initialize internal data structures used
-   in tree-ssa optimization passes.  */
-
-static void
-execute_init_datastructures (void)
+static unsigned int
+execute_free_cfg_annotations (void)
 {
 {
-  /* Allocate hash tables, arrays and other structures.  */
-  init_tree_ssa ();
+  /* And get rid of annotations we no longer need.  */
+  delete_tree_cfg_annotations ();
+
+  return 0;
 }
 
 }
 
-static struct tree_opt_pass pass_init_datastructures =
+struct tree_opt_pass pass_free_cfg_annotations =
 {
   NULL,                                        /* name */
   NULL,                                        /* gate */
 {
   NULL,                                        /* name */
   NULL,                                        /* gate */
-  execute_init_datastructures,         /* execute */
+  execute_free_cfg_annotations,                /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
@@ -205,375 +260,134 @@ static struct tree_opt_pass pass_init_datastructures =
   0                                    /* letter */
 };
 
   0                                    /* letter */
 };
 
-/* Iterate over the pass tree allocating dump file numbers.  We want
-   to do this depth first, and independent of whether the pass is
-   enabled or not.  */
-
-static void
-register_one_dump_file (struct tree_opt_pass *pass, int n)
-{
-  char *dot_name, *flag_name;
-  char num[10];
-
-  /* See below in next_pass_1.  */
-  num[0] = '\0';
-  if (pass->static_pass_number != -1)
-    sprintf (num, "%d", ((int) pass->static_pass_number < 0
-                        ? 1 : pass->static_pass_number));
-
-  dot_name = concat (".", pass->name, num, NULL);
-  if (pass->properties_provided & PROP_trees)
-    {
-      flag_name = concat ("tree-", pass->name, num, NULL);
-      pass->static_pass_number = dump_register (dot_name, flag_name,
-                                                TDF_TREE, n + TDI_tree_all, 0);
-    }
-  else
-    {
-      flag_name = concat ("rtl-", pass->name, num, NULL);
-      pass->static_pass_number = dump_register (dot_name, flag_name,
-                                                TDF_RTL, n, pass->letter);
-    }
-}
-
-static int 
-register_dump_files (struct tree_opt_pass *pass, int properties)
-{
-  static int n = 0;
-  do
-    {
-      int new_properties;
-      int pass_number;
-
-      pass->properties_required = properties;
-      new_properties =
-        (properties | pass->properties_provided) & ~pass->properties_destroyed;
-
-      /* Reset the counter when we reach RTL-based passes.  */
-      if ((pass->properties_provided ^ pass->properties_required) & PROP_rtl)
-        n = 0;
-
-      pass_number = n;
-      if (pass->name)
-        n++;
-
-      if (pass->sub)
-        new_properties = register_dump_files (pass->sub, new_properties);
+/* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
+   might have changed some properties, such as marked functions nothrow.
+   Remove redundant edges and basic blocks, and create new ones if necessary.
 
 
-      /* If we have a gate, combine the properties that we could have with
-         and without the pass being examined.  */
-      if (pass->gate)
-        properties &= new_properties;
-      else
-        properties = new_properties;
+   This pass can't be executed as stand alone pass from pass manager, because
+   in between inlining and this fixup the verify_flow_info would fail.  */
 
 
-      pass->properties_provided = properties;
-      if (pass->name)
-        register_one_dump_file (pass, pass_number);
-
-      pass = pass->next;
-    }
-  while (pass);
-
-  return properties;
-}
-
-/* Add a pass to the pass list. Duplicate the pass if it's already
-   in the list.  */
-
-static struct tree_opt_pass **
-next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass)
+unsigned int
+execute_fixup_cfg (void)
 {
 {
+  basic_block bb;
+  block_stmt_iterator bsi;
+  int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
+
+  cfun->after_inlining = true;
+
+  if (cfun->eh)
+    FOR_EACH_BB (bb)
+      {
+       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+         {
+           tree stmt = bsi_stmt (bsi);
+           tree call = get_call_expr_in (stmt);
+           tree decl = call ? get_callee_fndecl (call) : NULL;
+
+           if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE)
+               && TREE_SIDE_EFFECTS (call))
+             {
+               if (gimple_in_ssa_p (cfun))
+                 {
+                   todo |= TODO_update_ssa | TODO_cleanup_cfg;
+                   update_stmt (stmt);
+                 }
+               TREE_SIDE_EFFECTS (call) = 0;
+             }
+           if (decl && TREE_NOTHROW (decl))
+             TREE_NOTHROW (call) = 1;
+           if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
+             remove_stmt_from_eh_region (stmt);
+         }
+       if (tree_purge_dead_eh_edges (bb))
+          todo |= TODO_cleanup_cfg;
+      }
+
+  /* Dump a textual representation of the flowgraph.  */
+  if (dump_file)
+    dump_tree_cfg (dump_file, dump_flags);
 
 
-  /* A nonzero static_pass_number indicates that the
-     pass is already in the list.  */
-  if (pass->static_pass_number)
-    {
-      struct tree_opt_pass *new;
-
-      new = xmalloc (sizeof (*new));
-      memcpy (new, pass, sizeof (*new));
-
-      /* Indicate to register_dump_files that this pass has duplicates,
-         and so it should rename the dump file.  The first instance will
-         be -1, and be number of duplicates = -static_pass_number - 1.
-         Subsequent instances will be > 0 and just the duplicate number.  */
-      if (pass->name)
-        {
-          pass->static_pass_number -= 1;
-          new->static_pass_number = -pass->static_pass_number;
-       }
-      
-      *list = new;
-    }
-  else
-    {
-      pass->static_pass_number = -1;
-      *list = pass;
-    }  
-  
-  return &(*list)->next;
-          
+  return todo;
 }
 
 }
 
-/* Construct the pass tree.  */
+/* Do the actions required to initialize internal data structures used
+   in tree-ssa optimization passes.  */
 
 
-void
-init_tree_optimization_passes (void)
+static unsigned int
+execute_init_datastructures (void)
 {
 {
-  struct tree_opt_pass **p;
-
-#define NEXT_PASS(PASS)  (p = next_pass_1 (p, &PASS))
-
-  p = &all_passes;
-  NEXT_PASS (pass_gimple);
-  NEXT_PASS (pass_remove_useless_stmts);
-  NEXT_PASS (pass_mudflap_1);
-  NEXT_PASS (pass_lower_cf);
-  NEXT_PASS (pass_lower_eh);
-  NEXT_PASS (pass_build_cfg);
-  NEXT_PASS (pass_pre_expand);
-  NEXT_PASS (pass_tree_profile);
-  NEXT_PASS (pass_init_datastructures);
-  NEXT_PASS (pass_all_optimizations);
-  NEXT_PASS (pass_warn_function_return);
-  NEXT_PASS (pass_mudflap_2);
-  NEXT_PASS (pass_free_datastructures);
-  NEXT_PASS (pass_expand);
-  NEXT_PASS (pass_rest_of_compilation);
-  *p = NULL;
-
-  p = &pass_all_optimizations.sub;
-  NEXT_PASS (pass_referenced_vars);
-  NEXT_PASS (pass_build_ssa);
-  NEXT_PASS (pass_may_alias);
-  NEXT_PASS (pass_rename_ssa_copies);
-  NEXT_PASS (pass_early_warn_uninitialized);
-  NEXT_PASS (pass_dce);
-  NEXT_PASS (pass_dominator);
-  NEXT_PASS (pass_redundant_phi);
-  NEXT_PASS (pass_dce);
-  NEXT_PASS (pass_forwprop);
-  NEXT_PASS (pass_phiopt);
-  NEXT_PASS (pass_may_alias);
-  NEXT_PASS (pass_tail_recursion);
-  NEXT_PASS (pass_ch);
-  NEXT_PASS (pass_profile);
-  NEXT_PASS (pass_sra);
-  NEXT_PASS (pass_rename_ssa_copies);
-  NEXT_PASS (pass_dominator);
-  NEXT_PASS (pass_redundant_phi);
-  NEXT_PASS (pass_dce);
-  NEXT_PASS (pass_dse);
-  NEXT_PASS (pass_may_alias);
-  NEXT_PASS (pass_forwprop);
-  NEXT_PASS (pass_phiopt);
-  NEXT_PASS (pass_ccp);
-  NEXT_PASS (pass_redundant_phi);
-  NEXT_PASS (pass_fold_builtins);
-  NEXT_PASS (pass_split_crit_edges);
-  NEXT_PASS (pass_pre);
-  NEXT_PASS (pass_loop);
-  NEXT_PASS (pass_dominator);
-  NEXT_PASS (pass_redundant_phi);
-  NEXT_PASS (pass_cd_dce);
-  NEXT_PASS (pass_dse);
-  NEXT_PASS (pass_forwprop);
-  NEXT_PASS (pass_phiopt);
-  NEXT_PASS (pass_tail_calls);
-  NEXT_PASS (pass_late_warn_uninitialized);
-  NEXT_PASS (pass_del_ssa);
-  NEXT_PASS (pass_nrv);
-  NEXT_PASS (pass_remove_useless_vars);
-  NEXT_PASS (pass_cleanup_cfg_post_optimizing);
-  *p = NULL;
-
-  p = &pass_loop.sub;
-  NEXT_PASS (pass_loop_init);
-  NEXT_PASS (pass_lim);
-  NEXT_PASS (pass_iv_canon);
-  NEXT_PASS (pass_if_conversion);
-  NEXT_PASS (pass_vectorize);
-  NEXT_PASS (pass_linear_transform);
-  NEXT_PASS (pass_complete_unroll);
-  NEXT_PASS (pass_iv_optimize);
-  NEXT_PASS (pass_loop_done);
-  *p = NULL;
-
-#undef NEXT_PASS
-
-  /* Register the passes with the tree dump code.  */
-  register_dump_files (all_passes, 0);
+  /* Allocate hash tables, arrays and other structures.  */
+  init_tree_ssa ();
+  return 0;
 }
 
 }
 
-static void execute_pass_list (struct tree_opt_pass *);
-
-static unsigned int last_verified;
-
-static void
-execute_todo (int properties, unsigned int flags)
-{
-  if (flags & TODO_rename_vars)
-    {
-      rewrite_into_ssa (false);
-      bitmap_clear (vars_to_rename);
-    }
-
-  if ((flags & TODO_dump_func) && dump_file)
-    {
-      if (properties & PROP_trees)
-        dump_function_to_file (current_function_decl,
-                               dump_file, dump_flags);
-      else if (properties & PROP_cfg)
-        print_rtl_with_bb (dump_file, get_insns ());
-      else
-        print_rtl (dump_file, get_insns ());
-
-      /* Flush the file.  If verification fails, we won't be able to
-        close the file before aborting.  */
-      fflush (dump_file);
-    }
-
-  if (flags & TODO_ggc_collect)
-    ggc_collect ();
-
-#ifdef ENABLE_CHECKING
-  if (flags & TODO_verify_ssa)
-    verify_ssa ();
-  if (flags & TODO_verify_flow)
-    verify_flow_info ();
-  if (flags & TODO_verify_stmts)
-    verify_stmts ();
-#endif
-}
+/* Gate: initialize or not the SSA datastructures.  */
 
 static bool
 
 static bool
-execute_one_pass (struct tree_opt_pass *pass)
+gate_init_datastructures (void)
 {
 {
-  unsigned int todo; 
-
-  /* See if we're supposed to run this pass.  */
-  if (pass->gate && !pass->gate ())
-    return false;
-
-  /* Note that the folders should only create gimple expressions.
-     This is a hack until the new folder is ready.  */
-  in_gimple_form = (pass->properties_provided & PROP_trees) != 0;
-
-  /* Run pre-pass verification.  */
-  todo = pass->todo_flags_start & ~last_verified;
-  if (todo)
-    execute_todo (pass->properties_required, todo);
-
-  /* If a dump file name is present, open it if enabled.  */
-  if (pass->static_pass_number != -1)
-    {
-      bool initializing_dump = !dump_initialized_p (pass->static_pass_number);
-      dump_file_name = get_dump_file_name (pass->static_pass_number);
-      dump_file = dump_begin (pass->static_pass_number, &dump_flags);
-      if (dump_file)
-       {
-         const char *dname, *aname;
-         dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-         aname = (IDENTIFIER_POINTER
-                  (DECL_ASSEMBLER_NAME (current_function_decl)));
-          fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-             cfun->function_frequency == FUNCTION_FREQUENCY_HOT
-             ? " (hot)"
-             : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
-             ? " (unlikely executed)"
-             : "");
-       }
-
-      if (initializing_dump
-          && graph_dump_format != no_graph
-         && (pass->properties_provided & (PROP_cfg | PROP_rtl))
-             == (PROP_cfg | PROP_rtl))
-        clean_graph_dump_file (dump_file_name);
-    }
-
-  /* If a timevar is present, start it.  */
-  if (pass->tv_id)
-    timevar_push (pass->tv_id);
-
-  /* Do it!  */
-  if (pass->execute)
-    pass->execute ();
-
-  if (dump_file
-      && (pass->properties_provided & (PROP_cfg | PROP_rtl))
-         == (PROP_cfg | PROP_rtl))
-    print_rtl_graph_with_bb (dump_file_name, get_insns ());
-
-  /* Run post-pass cleanup and verification.  */
-  todo = pass->todo_flags_finish;
-  last_verified = todo & TODO_verify_all;
-  if (todo)
-    execute_todo (pass->properties_provided, todo);
-
-  /* Close down timevar and dump file.  */
-  if (pass->tv_id)
-    timevar_pop (pass->tv_id);
-  if (dump_file_name)
-    {
-      free ((char *) dump_file_name);
-      dump_file_name = NULL;
-    }
-  if (dump_file)
-    {
-      dump_end (pass->static_pass_number, dump_file);
-      dump_file = NULL;
-    }
-
-  return true;
+  return (optimize >= 1);
 }
 
 }
 
-static void
-execute_pass_list (struct tree_opt_pass *pass)
+struct tree_opt_pass pass_init_datastructures =
 {
 {
-  do
-    {
-      if (execute_one_pass (pass) && pass->sub)
-       execute_pass_list (pass->sub);
-      pass = pass->next;
-    }
-  while (pass);
-}
-\f
+  NULL,                                        /* name */
+  gate_init_datastructures,            /* gate */
+  execute_init_datastructures,         /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  0,                                   /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0,                                   /* todo_flags_finish */
+  0                                    /* letter */
+};
 
 
-/* Update recursively all inlined_to pointers of functions
-   inlined into NODE to INLINED_TO.  */
-static void
-update_inlined_to_pointers (struct cgraph_node *node,
-                           struct cgraph_node *inlined_to)
+void
+tree_lowering_passes (tree fn)
 {
 {
-  struct cgraph_edge *e;
-  for (e = node->callees; e; e = e->next_callee)
-    {
-      if (e->callee->global.inlined_to)
-       {
-         e->callee->global.inlined_to = inlined_to;
-         update_inlined_to_pointers (e->callee, node);
-       }
-    }
+  tree saved_current_function_decl = current_function_decl;
+
+  current_function_decl = fn;
+  push_cfun (DECL_STRUCT_FUNCTION (fn));
+  tree_register_cfg_hooks ();
+  bitmap_obstack_initialize (NULL);
+  execute_pass_list (all_lowering_passes);
+  if (optimize && cgraph_global_info_ready)
+    execute_pass_list (pass_early_local_passes.sub);
+  free_dominance_info (CDI_POST_DOMINATORS);
+  free_dominance_info (CDI_DOMINATORS);
+  compact_blocks ();
+  current_function_decl = saved_current_function_decl;
+  bitmap_obstack_release (NULL);
+  pop_cfun ();
 }
 }
-
 \f
 /* For functions-as-trees languages, this performs all optimization and
    compilation for FNDECL.  */
 
 void
 \f
 /* For functions-as-trees languages, this performs all optimization and
    compilation for FNDECL.  */
 
 void
-tree_rest_of_compilation (tree fndecl, bool nested_p)
+tree_rest_of_compilation (tree fndecl)
 {
   location_t saved_loc;
 {
   location_t saved_loc;
-  struct cgraph_node *saved_node = NULL, *node;
+  struct cgraph_node *node;
 
   timevar_push (TV_EXPAND);
 
   gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
 
 
   timevar_push (TV_EXPAND);
 
   gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
 
+  node = cgraph_node (fndecl);
+
+  /* Initialize the default bitmap obstack.  */
+  bitmap_obstack_initialize (NULL);
+
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
+  cfun = DECL_STRUCT_FUNCTION (fndecl);
   saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fndecl);
   init_function_start (fndecl);
   saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fndecl);
   init_function_start (fndecl);
@@ -583,90 +397,19 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
   cfun->x_dont_save_pending_sizes_p = 1;
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
   cfun->x_dont_save_pending_sizes_p = 1;
+  
+  tree_register_cfg_hooks ();
 
 
-  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_static_chain_decl = cfun->static_chain_decl;
-      cfun->saved_tree = save_body (fndecl, &cfun->saved_args,
-                                   &cfun->saved_static_chain_decl);
-    }
-
-  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);
-       }
-    }
-
-  /* We are not going to maintain the cgraph edges up to date.
-     Kill it so it won't confuse us.  */
-  while (node->callees)
-    cgraph_remove_edge (node->callees);
-
-  if (!vars_to_rename)
-    vars_to_rename = BITMAP_XMALLOC ();
-
-  /* If this is a nested function, protect the local variables in the stack
-     above us from being collected while we're compiling this function.  */
-  if (nested_p)
-    ggc_push_context ();
-
+  bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
   /* Perform all tree transforms and optimizations.  */
   execute_pass_list (all_passes);
   /* Perform all tree transforms and optimizations.  */
   execute_pass_list (all_passes);
+  
+  bitmap_obstack_release (&reg_obstack);
 
 
-  /* Restore original body if still needed.  */
-  if (cfun->saved_tree)
-    {
-      DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
-      DECL_ARGUMENTS (fndecl) = cfun->saved_args;
-      cfun->static_chain_decl = cfun->saved_static_chain_decl;
-
-      /* 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 = node->callees; e; e = e->next_callee)
-           {
-             if (e->callee->global.inlined_to)
-               {
-                 e->callee->global.inlined_to = node;
-                 update_inlined_to_pointers (e->callee, node);
-               }
-             e->caller = node;
-           }
-         cgraph_remove_node (saved_node);
-       }
-    }
-  else
-    DECL_SAVED_TREE (fndecl) = NULL;
+  /* Release the default bitmap obstack.  */
+  bitmap_obstack_release (NULL);
+  
+  DECL_SAVED_TREE (fndecl) = NULL;
   cfun = 0;
 
   /* If requested, warn about function definitions where the function will
   cfun = 0;
 
   /* If requested, warn about function definitions where the function will
@@ -685,15 +428,15 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
-           warning ("%Jsize of return value of '%D' is %u bytes",
-                     fndecl, fndecl, size_as_int);
+           warning (0, "size of return value of %q+D is %u bytes",
+                     fndecl, size_as_int);
          else
          else
-           warning ("%Jsize of return value of '%D' is larger than %wd bytes",
-                     fndecl, fndecl, larger_than_size);
+           warning (0, "size of return value of %q+D is larger than %wd bytes",
+                     fndecl, larger_than_size);
        }
     }
 
        }
     }
 
-  if (!nested_p && !flag_inline_trees)
+  if (!flag_inline_trees)
     {
       DECL_SAVED_TREE (fndecl) = NULL;
       if (DECL_STRUCT_FUNCTION (fndecl) == 0
     {
       DECL_SAVED_TREE (fndecl) = NULL;
       if (DECL_STRUCT_FUNCTION (fndecl) == 0
@@ -712,9 +455,5 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
   input_location = saved_loc;
 
   ggc_collect ();
   input_location = saved_loc;
 
   ggc_collect ();
-
-  /* Undo the GC context switch.  */
-  if (nested_p)
-    ggc_pop_context ();
   timevar_pop (TV_EXPAND);
 }
   timevar_pop (TV_EXPAND);
 }