OSDN Git Service

PR bootstrap/21215
[pf3gnuchains/gcc-fork.git] / gcc / passes.c
index 4b50a1f..9d8e2da 100644 (file)
@@ -1,6 +1,6 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -60,7 +60,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "intl.h"
 #include "ggc.h"
 #include "graph.h"
 #include "intl.h"
 #include "ggc.h"
 #include "graph.h"
-#include "loop.h"
 #include "regs.h"
 #include "timevar.h"
 #include "diagnostic.h"
 #include "regs.h"
 #include "timevar.h"
 #include "diagnostic.h"
@@ -79,8 +78,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "opts.h"
 #include "coverage.h"
 #include "value-prof.h"
 #include "opts.h"
 #include "coverage.h"
 #include "value-prof.h"
-#include "alloc-pool.h"
 #include "tree-pass.h"
 #include "tree-pass.h"
+#include "tree-dump.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -108,166 +107,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define DUMPFILE_FORMAT ".%02d."
 #endif
 
 #define DUMPFILE_FORMAT ".%02d."
 #endif
 
-/* Describes a dump file.  */
-
-struct dump_file_info
-{
-  /* The unique extension to apply, e.g. ".jump".  */
-  const char *const extension;
-
-  /* The -d<c> character that enables this dump file.  */
-  char const debug_switch;
-
-  /* True if there is a corresponding graph dump file.  */
-  char const graph_dump_p;
-
-  /* True if the user selected this dump.  */
-  char enabled;
-
-  /* True if the files have been initialized (ie truncated).  */
-  char initialized;
-};
-
-/* Enumerate the extant dump files.  */
-
-enum dump_file_index
-{
-  DFI_cgraph,
-  DFI_rtl,
-  DFI_sibling,
-  DFI_eh,
-  DFI_jump,
-  DFI_null,
-  DFI_cse,
-  DFI_gcse,
-  DFI_loop,
-  DFI_bypass,
-  DFI_cfg,
-  DFI_bp,
-  DFI_vpt,
-  DFI_ce1,
-  DFI_tracer,
-  DFI_loop2,
-  DFI_web,
-  DFI_cse2,
-  DFI_life,
-  DFI_combine,
-  DFI_ce2,
-  DFI_regmove,
-  DFI_sms,
-  DFI_sched,
-  DFI_lreg,
-  DFI_greg,
-  DFI_postreload,
-  DFI_gcse2,
-  DFI_flow2,
-  DFI_peephole2,
-  DFI_ce3,
-  DFI_rnreg,
-  DFI_bbro,
-  DFI_branch_target_load,
-  DFI_sched2,
-  DFI_stack,
-  DFI_vartrack,
-  DFI_mach,
-  DFI_dbr,
-  DFI_MAX
-};
-
-/* Describes all the dump files.  Should be kept in order of the
-   pass and in sync with dump_file_index above.
-
-   Remaining -d letters:
-
-       "   e            q         "
-       "    F     K   O Q     WXY "
-*/
-
-static struct dump_file_info dump_file_tbl[DFI_MAX] =
-{
-  { "cgraph",  'U', 0, 0, 0 },
-  { "rtl",     'r', 0, 0, 0 },
-  { "sibling",  'i', 0, 0, 0 },
-  { "eh",      'h', 0, 0, 0 },
-  { "jump",    'j', 0, 0, 0 },
-  { "null",    'u', 0, 0, 0 },
-  { "cse",     's', 0, 0, 0 },
-  { "gcse",    'G', 1, 0, 0 },
-  { "loop",    'L', 1, 0, 0 },
-  { "bypass",   'G', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
-  { "cfg",     'f', 1, 0, 0 },
-  { "bp",      'b', 1, 0, 0 },
-  { "vpt",     'V', 1, 0, 0 },
-  { "ce1",     'C', 1, 0, 0 },
-  { "tracer",  'T', 1, 0, 0 },
-  { "loop2",   'L', 1, 0, 0 },
-  { "web",      'Z', 0, 0, 0 },
-  { "cse2",    't', 1, 0, 0 },
-  { "life",    'f', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
-  { "combine", 'c', 1, 0, 0 },
-  { "ce2",     'C', 1, 0, 0 },
-  { "regmove", 'N', 1, 0, 0 },
-  { "sms",      'm', 0, 0, 0 },
-  { "sched",   'S', 1, 0, 0 },
-  { "lreg",    'l', 1, 0, 0 },
-  { "greg",    'g', 1, 0, 0 },
-  { "postreload", 'o', 1, 0, 0 },
-  { "gcse2",    'J', 0, 0, 0 },
-  { "flow2",   'w', 1, 0, 0 },
-  { "peephole2", 'z', 1, 0, 0 },
-  { "ce3",     'E', 1, 0, 0 },
-  { "rnreg",   'n', 1, 0, 0 },
-  { "bbro",    'B', 1, 0, 0 },
-  { "btl",     'd', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
-  { "sched2",  'R', 1, 0, 0 },
-  { "stack",   'k', 1, 0, 0 },
-  { "vartrack",        'V', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
-  { "mach",    'M', 1, 0, 0 },
-  { "dbr",     'd', 0, 0, 0 },
-};
+static int initializing_dump = 0;
 
 /* Routine to open a dump file.  Return true if the dump file is enabled.  */
 
 static int
 
 /* Routine to open a dump file.  Return true if the dump file is enabled.  */
 
 static int
-open_dump_file (enum dump_file_index index, tree decl)
+open_dump_file (enum tree_dump_index index, tree decl)
 {
 {
-  char *dump_name;
-  const char *open_arg;
-  char seq[16];
-
-  if (! dump_file_tbl[index].enabled)
+  if (! dump_enabled_p (index))
     return 0;
 
   timevar_push (TV_DUMP);
     return 0;
 
   timevar_push (TV_DUMP);
-  if (dump_file != NULL)
-    fclose (dump_file);
-
-  sprintf (seq, DUMPFILE_FORMAT, index);
 
 
-  if (! dump_file_tbl[index].initialized)
-    {
-      /* If we've not initialized the files, do so now.  */
-      if (graph_dump_format != no_graph
-         && dump_file_tbl[index].graph_dump_p)
-       {
-         dump_name = concat (seq, dump_file_tbl[index].extension, NULL);
-         clean_graph_dump_file (dump_base_name, dump_name);
-         free (dump_name);
-       }
-      dump_file_tbl[index].initialized = 1;
-      open_arg = "w";
-    }
-  else
-    open_arg = "a";
+  gcc_assert (!dump_file && !dump_file_name);
 
 
-  dump_name = concat (dump_base_name, seq,
-                     dump_file_tbl[index].extension, NULL);
+  dump_file_name = get_dump_file_name (index);
+  initializing_dump = !dump_initialized_p (index);
+  dump_file = dump_begin (index, NULL);
 
 
-  dump_file = fopen (dump_name, open_arg);
   if (dump_file == NULL)
   if (dump_file == NULL)
-    fatal_error ("can't open %s: %m", dump_name);
-
-  free (dump_name);
+    fatal_error ("can't open %s: %m", dump_file_name);
 
   if (decl)
     fprintf (dump_file, "\n;; Function %s%s\n\n",
 
   if (decl)
     fprintf (dump_file, "\n;; Function %s%s\n\n",
@@ -285,7 +144,7 @@ open_dump_file (enum dump_file_index index, tree decl)
 /* Routine to close a dump file.  */
 
 static void
 /* Routine to close a dump file.  */
 
 static void
-close_dump_file (enum dump_file_index index,
+close_dump_file (enum tree_dump_index index,
                 void (*func) (FILE *, rtx),
                 rtx insns)
 {
                 void (*func) (FILE *, rtx),
                 rtx insns)
 {
@@ -294,25 +153,23 @@ close_dump_file (enum dump_file_index index,
 
   timevar_push (TV_DUMP);
   if (insns
 
   timevar_push (TV_DUMP);
   if (insns
-      && graph_dump_format != no_graph
-      && dump_file_tbl[index].graph_dump_p)
+      && graph_dump_format != no_graph)
     {
     {
-      char seq[16];
-      char *suffix;
+      /* If we've not initialized the files, do so now.  */
+      if (initializing_dump)
+       clean_graph_dump_file (dump_file_name);
 
 
-      sprintf (seq, DUMPFILE_FORMAT, index);
-      suffix = concat (seq, dump_file_tbl[index].extension, NULL);
-      print_rtl_graph_with_bb (dump_base_name, suffix, insns);
-      free (suffix);
+      print_rtl_graph_with_bb (dump_file_name, insns);
     }
 
   if (func && insns)
     func (dump_file, insns);
 
     }
 
   if (func && insns)
     func (dump_file, insns);
 
-  fflush (dump_file);
-  fclose (dump_file);
+  dump_end (index, dump_file);
+  free ((char *) dump_file_name);
 
   dump_file = NULL;
 
   dump_file = NULL;
+  dump_file_name = NULL;
   timevar_pop (TV_DUMP);
 }
 
   timevar_pop (TV_DUMP);
 }
 
@@ -320,18 +177,16 @@ close_dump_file (enum dump_file_index index,
    and TYPE_DECL nodes.
 
    This does nothing for local (non-static) variables, unless the
    and TYPE_DECL nodes.
 
    This does nothing for local (non-static) variables, unless the
-   variable is a register variable with an ASMSPEC.  In that case, or
-   if the variable is not an automatic, it sets up the RTL and
-   outputs any assembler code (label definition, storage allocation
-   and initialization).
+   variable is a register variable with DECL_ASSEMBLER_NAME set.  In
+   that case, or if the variable is not an automatic, it sets up the
+   RTL and outputs any assembler code (label definition, storage
+   allocation and initialization).
 
 
-   DECL is the declaration.  If ASMSPEC is nonzero, it specifies
-   the assembler symbol name to be used.  TOP_LEVEL is nonzero
+   DECL is the declaration.  TOP_LEVEL is nonzero
    if this declaration is not within a function.  */
 
 void
 rest_of_decl_compilation (tree decl,
    if this declaration is not within a function.  */
 
 void
 rest_of_decl_compilation (tree decl,
-                         const char *asmspec,
                          int top_level,
                          int at_end)
 {
                          int top_level,
                          int at_end)
 {
@@ -348,6 +203,11 @@ rest_of_decl_compilation (tree decl,
       }
   }
 
       }
   }
 
+  /* Can't defer this, because it needs to happen before any
+     later function definitions are processed.  */
+  if (DECL_REGISTER (decl) && DECL_ASSEMBLER_NAME_SET_P (decl))
+    make_decl_rtl (decl);
+
   /* Forward declarations for nested functions are not "external",
      but we need to treat them as if they were.  */
   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
   /* Forward declarations for nested functions are not "external",
      but we need to treat them as if they were.  */
   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
@@ -355,9 +215,6 @@ rest_of_decl_compilation (tree decl,
     {
       timevar_push (TV_VARCONST);
 
     {
       timevar_push (TV_VARCONST);
 
-      if (asmspec)
-       make_decl_rtl (decl, asmspec);
-
       /* Don't output anything when a tentative file-scope definition
         is seen.  But at end of compilation, do output code for them.
 
       /* Don't output anything when a tentative file-scope definition
         is seen.  But at end of compilation, do output code for them.
 
@@ -366,18 +223,11 @@ rest_of_decl_compilation (tree decl,
         (see gcc.c-torture/compile/920624-1.c) */
       if ((at_end
           || !DECL_DEFER_OUTPUT (decl)
         (see gcc.c-torture/compile/920624-1.c) */
       if ((at_end
           || !DECL_DEFER_OUTPUT (decl)
-          || (flag_unit_at_a_time && DECL_INITIAL (decl)))
+          || DECL_INITIAL (decl))
          && !DECL_EXTERNAL (decl))
        {
          if (flag_unit_at_a_time && !cgraph_global_info_ready
          && !DECL_EXTERNAL (decl))
        {
          if (flag_unit_at_a_time && !cgraph_global_info_ready
-             && TREE_CODE (decl) != FUNCTION_DECL && top_level
-             /* If we defer processing of decls that have had their
-                DECL_RTL set above (say, in make_decl_rtl),
-                check_global_declarations() will clear it before
-                assemble_variable has a chance to act on it.  This
-                would remove all traces of the register name in a
-                global register variable, for example.  */
-             && !DECL_RTL_SET_P (decl))
+             && TREE_CODE (decl) != FUNCTION_DECL && top_level)
            cgraph_varpool_finalize_decl (decl);
          else
            assemble_variable (decl, top_level, at_end, 0);
            cgraph_varpool_finalize_decl (decl);
          else
            assemble_variable (decl, top_level, at_end, 0);
@@ -393,28 +243,16 @@ rest_of_decl_compilation (tree decl,
 
       timevar_pop (TV_VARCONST);
     }
 
       timevar_pop (TV_VARCONST);
     }
-  else if (DECL_REGISTER (decl) && asmspec != 0)
-    {
-      if (decode_reg_name (asmspec) >= 0)
-       {
-         SET_DECL_RTL (decl, NULL_RTX);
-         make_decl_rtl (decl, asmspec);
-       }
-      else
-       {
-         error ("%Hinvalid register name `%s' for register variable",
-                &DECL_SOURCE_LOCATION (decl), asmspec);
-         DECL_REGISTER (decl) = 0;
-         if (!top_level)
-           expand_decl (decl);
-       }
-    }
   else if (TREE_CODE (decl) == TYPE_DECL)
     {
       timevar_push (TV_SYMOUT);
       debug_hooks->type_decl (decl, !top_level);
       timevar_pop (TV_SYMOUT);
     }
   else if (TREE_CODE (decl) == TYPE_DECL)
     {
       timevar_push (TV_SYMOUT);
       debug_hooks->type_decl (decl, !top_level);
       timevar_pop (TV_SYMOUT);
     }
+
+  /* Let cgraph know about the existence of variables.  */
+  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+    cgraph_varpool_node (decl);
 }
 
 /* Called after finishing a record, union or enumeral type.  */
 }
 
 /* Called after finishing a record, union or enumeral type.  */
@@ -445,16 +283,14 @@ rest_of_handle_final (void)
        different from the DECL_NAME name used in the source file.  */
 
     x = DECL_RTL (current_function_decl);
        different from the DECL_NAME name used in the source file.  */
 
     x = DECL_RTL (current_function_decl);
-    if (!MEM_P (x))
-      abort ();
+    gcc_assert (MEM_P (x));
     x = XEXP (x, 0);
     x = XEXP (x, 0);
-    if (GET_CODE (x) != SYMBOL_REF)
-      abort ();
+    gcc_assert (GET_CODE (x) == SYMBOL_REF);
     fnname = XSTR (x, 0);
 
     assemble_start_function (current_function_decl, fnname);
     final_start_function (get_insns (), asm_out_file, optimize);
     fnname = XSTR (x, 0);
 
     assemble_start_function (current_function_decl, fnname);
     final_start_function (get_insns (), asm_out_file, optimize);
-    final (get_insns (), asm_out_file, optimize, 0);
+    final (get_insns (), asm_out_file, optimize);
     final_end_function ();
 
 #ifdef TARGET_UNWIND_INFO
     final_end_function ();
 
 #ifdef TARGET_UNWIND_INFO
@@ -470,14 +306,13 @@ rest_of_handle_final (void)
     output_function_exception_table ();
 #endif
 
     output_function_exception_table ();
 #endif
 
+    user_defined_section_attribute = false;
+
     if (! quiet_flag)
       fflush (asm_out_file);
 
     /* Release all memory allocated by flow.  */
     free_basic_block_vars ();
     if (! quiet_flag)
       fflush (asm_out_file);
 
     /* Release all memory allocated by flow.  */
     free_basic_block_vars ();
-
-    /* Release all memory held by regsets now.  */
-    regset_release_memory ();
   }
 
   /* Write DBX symbols if requested.  */
   }
 
   /* Write DBX symbols if requested.  */
@@ -493,6 +328,7 @@ rest_of_handle_final (void)
 
   timevar_push (TV_SYMOUT);
   (*debug_hooks->function_decl) (current_function_decl);
 
   timevar_push (TV_SYMOUT);
   (*debug_hooks->function_decl) (current_function_decl);
+
   timevar_pop (TV_SYMOUT);
 
   ggc_collect ();
   timevar_pop (TV_SYMOUT);
 
   ggc_collect ();
@@ -561,7 +397,7 @@ rest_of_handle_stack_regs (void)
 }
 #endif
 
 }
 #endif
 
-/* Track the variables, ie. compute where the variable is stored at each position in function.  */
+/* Track the variables, i.e. compute where the variable is stored at each position in function.  */
 static void
 rest_of_handle_variable_tracking (void)
 {
 static void
 rest_of_handle_variable_tracking (void)
 {
@@ -590,49 +426,6 @@ rest_of_handle_machine_reorg (void)
 }
 
 
 }
 
 
-/* Run new register allocator.  Return TRUE if we must exit
-   rest_of_compilation upon return.  */
-static bool
-rest_of_handle_new_regalloc (void)
-{
-  int failure;
-
-  timevar_push (TV_LOCAL_ALLOC);
-  open_dump_file (DFI_lreg, current_function_decl);
-
-  delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_alloc ();
-
-  timevar_pop (TV_LOCAL_ALLOC);
-  close_dump_file (DFI_lreg, NULL, NULL);
-
-  /* XXX clean up the whole mess to bring live info in shape again.  */
-  timevar_push (TV_GLOBAL_ALLOC);
-  open_dump_file (DFI_greg, current_function_decl);
-
-  build_insn_chain (get_insns ());
-  failure = reload (get_insns (), 0);
-
-  timevar_pop (TV_GLOBAL_ALLOC);
-
-  ggc_collect ();
-
-  if (dump_file_tbl[DFI_greg].enabled)
-    {
-      timevar_push (TV_DUMP);
-      dump_global_regs (dump_file);
-      timevar_pop (TV_DUMP);
-      close_dump_file (DFI_greg, print_rtl_with_bb, get_insns ());
-    }
-
-  if (failure)
-    return true;
-
-  reload_completed = 1;
-
-  return false;
-}
-
 /* Run old register allocator.  Return TRUE if we must exit
    rest_of_compilation upon return.  */
 static bool
 /* Run old register allocator.  Return TRUE if we must exit
    rest_of_compilation upon return.  */
 static bool
@@ -666,12 +459,13 @@ rest_of_handle_old_regalloc (void)
       timevar_push (TV_JUMP);
 
       rebuild_jump_labels (get_insns ());
       timevar_push (TV_JUMP);
 
       rebuild_jump_labels (get_insns ());
-      purge_all_dead_edges (0);
+      purge_all_dead_edges ();
+      delete_unreachable_blocks ();
 
       timevar_pop (TV_JUMP);
     }
 
 
       timevar_pop (TV_JUMP);
     }
 
-  if (dump_file_tbl[DFI_lreg].enabled)
+  if (dump_enabled_p (DFI_lreg))
     {
       timevar_push (TV_DUMP);
       dump_flow_info (dump_file);
     {
       timevar_push (TV_DUMP);
       dump_flow_info (dump_file);
@@ -697,7 +491,7 @@ rest_of_handle_old_regalloc (void)
       failure = reload (get_insns (), 0);
     }
 
       failure = reload (get_insns (), 0);
     }
 
-  if (dump_file_tbl[DFI_greg].enabled)
+  if (dump_enabled_p (DFI_greg))
     {
       timevar_push (TV_DUMP);
       dump_global_regs (dump_file);
     {
       timevar_push (TV_DUMP);
       dump_global_regs (dump_file);
@@ -778,24 +572,38 @@ rest_of_handle_partition_blocks (void)
 static void
 rest_of_handle_sms (void)
 {
 static void
 rest_of_handle_sms (void)
 {
+  basic_block bb;
+  sbitmap blocks;
+
   timevar_push (TV_SMS);
   open_dump_file (DFI_sms, current_function_decl);
 
   /* We want to be able to create new pseudos.  */
   no_new_pseudos = 0;
   timevar_push (TV_SMS);
   open_dump_file (DFI_sms, current_function_decl);
 
   /* We want to be able to create new pseudos.  */
   no_new_pseudos = 0;
+  /* Collect loop information to be used in SMS.  */
+  cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
   sms_schedule (dump_file);
   close_dump_file (DFI_sms, print_rtl, get_insns ());
 
   sms_schedule (dump_file);
   close_dump_file (DFI_sms, print_rtl, get_insns ());
 
-
   /* Update the life information, because we add pseudos.  */
   max_regno = max_reg_num ();
   allocate_reg_info (max_regno, FALSE, FALSE);
   /* Update the life information, because we add pseudos.  */
   max_regno = max_reg_num ();
   allocate_reg_info (max_regno, FALSE, FALSE);
-  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
-                                   (PROP_DEATH_NOTES
-                                    | PROP_KILL_DEAD_CODE
-                                    | PROP_SCAN_DEAD_CODE));
+  blocks = sbitmap_alloc (last_basic_block);
+  sbitmap_ones (blocks);
+  update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
+                   (PROP_DEATH_NOTES
+                    | PROP_REG_INFO
+                    | PROP_KILL_DEAD_CODE
+                    | PROP_SCAN_DEAD_CODE));
+
   no_new_pseudos = 1;
 
   no_new_pseudos = 1;
 
+  /* Finalize layout changes.  */
+  FOR_EACH_BB (bb)
+    if (bb->next_bb != EXIT_BLOCK_PTR)
+      bb->rbi->next = bb->next_bb;
+  cfg_layout_finalize ();
+  free_dominance_info (CDI_DOMINATORS);
   ggc_collect ();
   timevar_pop (TV_SMS);
 }
   ggc_collect ();
   timevar_pop (TV_SMS);
 }
@@ -855,10 +663,10 @@ rest_of_handle_sched2 (void)
 static void
 rest_of_handle_gcse2 (void)
 {
 static void
 rest_of_handle_gcse2 (void)
 {
-  timevar_push (TV_RELOAD_CSE_REGS);
+  timevar_push (TV_GCSE_AFTER_RELOAD);
   open_dump_file (DFI_gcse2, current_function_decl);
 
   open_dump_file (DFI_gcse2, current_function_decl);
 
-  gcse_after_reload_main (get_insns (), dump_file);
+  gcse_after_reload_main (get_insns ());
   rebuild_jump_labels (get_insns ());
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
   close_dump_file (DFI_gcse2, print_rtl_with_bb, get_insns ());
   rebuild_jump_labels (get_insns ());
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
   close_dump_file (DFI_gcse2, print_rtl_with_bb, get_insns ());
@@ -869,7 +677,7 @@ rest_of_handle_gcse2 (void)
   verify_flow_info ();
 #endif
 
   verify_flow_info ();
 #endif
 
-  timevar_pop (TV_RELOAD_CSE_REGS);
+  timevar_pop (TV_GCSE_AFTER_RELOAD);
 }
 
 /* Register allocation pre-pass, to reduce number of moves necessary
 }
 
 /* Register allocation pre-pass, to reduce number of moves necessary
@@ -898,7 +706,7 @@ rest_of_handle_tracer (void)
     dump_flow_info (dump_file);
   tracer (0);
   cleanup_cfg (CLEANUP_EXPENSIVE);
     dump_flow_info (dump_file);
   tracer (0);
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ());
 }
 
   close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ());
 }
 
@@ -914,13 +722,13 @@ rest_of_handle_if_conversion (void)
       if (dump_file)
        dump_flow_info (dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE);
       if (dump_file)
        dump_flow_info (dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE);
-      reg_scan (get_insns (), max_reg_num (), 0);
+      reg_scan (get_insns (), max_reg_num ());
       if_convert (0);
     }
 
   timevar_push (TV_JUMP);
   cleanup_cfg (CLEANUP_EXPENSIVE);
       if_convert (0);
     }
 
   timevar_push (TV_JUMP);
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   timevar_pop (TV_JUMP);
 
   close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_JUMP);
 
   close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ());
@@ -971,7 +779,7 @@ rest_of_handle_web (void)
 
   timevar_pop (TV_WEB);
   close_dump_file (DFI_web, print_rtl_with_bb, get_insns ());
 
   timevar_pop (TV_WEB);
   close_dump_file (DFI_web, print_rtl_with_bb, get_insns ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
 }
 
 /* Do branch profiling and static profile estimation passes.  */
 }
 
 /* Do branch profiling and static profile estimation passes.  */
@@ -988,7 +796,7 @@ rest_of_handle_branch_prob (void)
 
   /* Discover and record the loop depth at the head of each basic
      block.  The loop infrastructure does the real job for us.  */
 
   /* Discover and record the loop depth at the head of each basic
      block.  The loop infrastructure does the real job for us.  */
-  flow_loops_find (&loops, LOOP_TREE);
+  flow_loops_find (&loops);
 
   if (dump_file)
     flow_loops_dump (&loops, dump_file, NULL, 0);
 
   if (dump_file)
     flow_loops_dump (&loops, dump_file, NULL, 0);
@@ -1035,12 +843,19 @@ rest_of_handle_cfg (void)
      it as constant, otherwise -fbranch-probabilities will not read data back.
 
      life_analysis rarely eliminates modification of external memory.
      it as constant, otherwise -fbranch-probabilities will not read data back.
 
      life_analysis rarely eliminates modification of external memory.
-   */
-  if (optimize)
+
+     FIXME: now with tree based profiling we are in the trap described above
+     again.  It seems to be easiest to disable the optimization for time
+     being before the problem is either solved by moving the transformation
+     to the IPA level (we need the CFG for this) or the very early optimization
+     passes are made to ignore the const/pure flags so code does not change.  */
+  if (optimize
+      && (!flag_tree_based_profiling
+         || (!profile_arc_flag && !flag_branch_probabilities)))
     {
       /* Alias analysis depends on this information and mark_constant_function
        depends on alias analysis.  */
     {
       /* Alias analysis depends on this information and mark_constant_function
        depends on alias analysis.  */
-      reg_scan (get_insns (), max_reg_num (), 1);
+      reg_scan (get_insns (), max_reg_num ());
       mark_constant_function ();
     }
 
       mark_constant_function ();
     }
 
@@ -1055,7 +870,7 @@ rest_of_handle_jump_bypass (void)
   open_dump_file (DFI_bypass, current_function_decl);
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
   open_dump_file (DFI_bypass, current_function_decl);
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
-  reg_scan (get_insns (), max_reg_num (), 1);
+  reg_scan (get_insns (), max_reg_num ());
 
   if (bypass_jumps (dump_file))
     {
 
   if (bypass_jumps (dump_file))
     {
@@ -1095,6 +910,7 @@ rest_of_handle_combine (void)
       rebuild_jump_labels (get_insns ());
       timevar_pop (TV_JUMP);
 
       rebuild_jump_labels (get_insns ());
       timevar_pop (TV_JUMP);
 
+      delete_dead_jumptables ();
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
     }
 
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
     }
 
@@ -1116,8 +932,7 @@ rest_of_handle_life (void)
 #endif
   life_analysis (dump_file, PROP_FINAL);
   if (optimize)
 #endif
   life_analysis (dump_file, PROP_FINAL);
   if (optimize)
-    cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE
-                | CLEANUP_LOG_LINKS
+    cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS
                 | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
   if (extra_warnings)
                 | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
   if (extra_warnings)
@@ -1128,7 +943,7 @@ rest_of_handle_life (void)
 
   if (optimize)
     {
 
   if (optimize)
     {
-      if (!flag_new_regalloc && initialize_uninitialized_subregs ())
+      if (initialize_uninitialized_subregs ())
        {
          /* Insns were inserted, and possibly pseudos created, so
             things might look a bit different.  */
        {
          /* Insns were inserted, and possibly pseudos created, so
             things might look a bit different.  */
@@ -1158,12 +973,12 @@ rest_of_handle_cse (void)
     dump_flow_info (dump_file);
   timevar_push (TV_CSE);
 
     dump_flow_info (dump_file);
   timevar_push (TV_CSE);
 
-  reg_scan (get_insns (), max_reg_num (), 1);
+  reg_scan (get_insns (), max_reg_num ());
 
 
-  tem = cse_main (get_insns (), max_reg_num (), 0, dump_file);
+  tem = cse_main (get_insns (), max_reg_num (), dump_file);
   if (tem)
     rebuild_jump_labels (get_insns ());
   if (tem)
     rebuild_jump_labels (get_insns ());
-  if (purge_all_dead_edges (0))
+  if (purge_all_dead_edges ())
     delete_unreachable_blocks ();
 
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
     delete_unreachable_blocks ();
 
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
@@ -1172,6 +987,9 @@ rest_of_handle_cse (void)
      expecting CSE to be run.  But always rerun it in a cheap mode.  */
   cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
 
      expecting CSE to be run.  But always rerun it in a cheap mode.  */
   cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
 
+  if (tem)
+    delete_dead_jumptables ();
+
   if (tem || optimize > 1)
     cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
   if (tem || optimize > 1)
     cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
@@ -1192,7 +1010,7 @@ rest_of_handle_cse2 (void)
   if (dump_file)
     dump_flow_info (dump_file);
   /* CFG is no longer maintained up-to-date.  */
   if (dump_file)
     dump_flow_info (dump_file);
   /* CFG is no longer maintained up-to-date.  */
-  tem = cse_main (get_insns (), max_reg_num (), 1, dump_file);
+  tem = cse_main (get_insns (), max_reg_num (), dump_file);
 
   /* Run a pass to eliminate duplicated assignments to condition code
      registers.  We have to run this after bypass_jumps, because it
 
   /* Run a pass to eliminate duplicated assignments to condition code
      registers.  We have to run this after bypass_jumps, because it
@@ -1200,17 +1018,18 @@ rest_of_handle_cse2 (void)
      bypassed safely.  */
   cse_condition_code_reg ();
 
      bypassed safely.  */
   cse_condition_code_reg ();
 
-  purge_all_dead_edges (0);
+  purge_all_dead_edges ();
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   if (tem)
     {
       timevar_push (TV_JUMP);
       rebuild_jump_labels (get_insns ());
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   if (tem)
     {
       timevar_push (TV_JUMP);
       rebuild_jump_labels (get_insns ());
+      delete_dead_jumptables ();
       cleanup_cfg (CLEANUP_EXPENSIVE);
       timevar_pop (TV_JUMP);
     }
       cleanup_cfg (CLEANUP_EXPENSIVE);
       timevar_pop (TV_JUMP);
     }
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   close_dump_file (DFI_cse2, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_CSE2);
 
   close_dump_file (DFI_cse2, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_CSE2);
 
@@ -1240,33 +1059,23 @@ rest_of_handle_gcse (void)
   if (flag_expensive_optimizations)
     {
       timevar_push (TV_CSE);
   if (flag_expensive_optimizations)
     {
       timevar_push (TV_CSE);
-      reg_scan (get_insns (), max_reg_num (), 1);
-      tem2 = cse_main (get_insns (), max_reg_num (), 0, dump_file);
-      purge_all_dead_edges (0);
+      reg_scan (get_insns (), max_reg_num ());
+      tem2 = cse_main (get_insns (), max_reg_num (), dump_file);
+      purge_all_dead_edges ();
       delete_trivially_dead_insns (get_insns (), max_reg_num ());
       timevar_pop (TV_CSE);
       cse_not_expected = !flag_rerun_cse_after_loop;
     }
 
   /* If gcse or cse altered any jumps, rerun jump optimizations to clean
       delete_trivially_dead_insns (get_insns (), max_reg_num ());
       timevar_pop (TV_CSE);
       cse_not_expected = !flag_rerun_cse_after_loop;
     }
 
   /* If gcse or cse altered any jumps, rerun jump optimizations to clean
-     things up.  Then possibly re-run CSE again.  */
-  while (tem || tem2)
+     things up.  */
+  if (tem || tem2)
     {
     {
-      tem = tem2 = 0;
       timevar_push (TV_JUMP);
       rebuild_jump_labels (get_insns ());
       timevar_push (TV_JUMP);
       rebuild_jump_labels (get_insns ());
+      delete_dead_jumptables ();
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       timevar_pop (TV_JUMP);
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       timevar_pop (TV_JUMP);
-
-      if (flag_expensive_optimizations)
-       {
-         timevar_push (TV_CSE);
-         reg_scan (get_insns (), max_reg_num (), 1);
-         tem2 = cse_main (get_insns (), max_reg_num (), 0, dump_file);
-         purge_all_dead_edges (0);
-         delete_trivially_dead_insns (get_insns (), max_reg_num ());
-         timevar_pop (TV_CSE);
-       }
     }
 
   close_dump_file (DFI_gcse, print_rtl_with_bb, get_insns ());
     }
 
   close_dump_file (DFI_gcse, print_rtl_with_bb, get_insns ());
@@ -1284,20 +1093,15 @@ rest_of_handle_gcse (void)
 static void
 rest_of_handle_loop_optimize (void)
 {
 static void
 rest_of_handle_loop_optimize (void)
 {
-  int do_unroll, do_prefetch;
+  int do_prefetch;
 
   timevar_push (TV_LOOP);
 
   timevar_push (TV_LOOP);
-  delete_dead_jumptables ();
-  cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
   open_dump_file (DFI_loop, current_function_decl);
 
   /* CFG is no longer maintained up-to-date.  */
   free_bb_for_insn ();
   open_dump_file (DFI_loop, current_function_decl);
 
   /* CFG is no longer maintained up-to-date.  */
   free_bb_for_insn ();
+  profile_status = PROFILE_ABSENT;
 
 
-  if (flag_unroll_loops)
-    do_unroll = LOOP_AUTO_UNROLL;      /* Having two unrollers is useless.  */
-  else
-    do_unroll = flag_old_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
   do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
 
   if (flag_rerun_loop_opt)
   do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
 
   if (flag_rerun_loop_opt)
@@ -1305,8 +1109,7 @@ rest_of_handle_loop_optimize (void)
       cleanup_barriers ();
 
       /* We only want to perform unrolling once.  */
       cleanup_barriers ();
 
       /* We only want to perform unrolling once.  */
-      loop_optimize (get_insns (), dump_file, do_unroll);
-      do_unroll = 0;
+      loop_optimize (get_insns (), dump_file, 0);
 
       /* The first call to loop_optimize makes some instructions
         trivially dead.  We delete those instructions now in the
 
       /* The first call to loop_optimize makes some instructions
         trivially dead.  We delete those instructions now in the
@@ -1316,14 +1119,14 @@ rest_of_handle_loop_optimize (void)
 
       /* The regscan pass is currently necessary as the alias
         analysis code depends on this information.  */
 
       /* The regscan pass is currently necessary as the alias
         analysis code depends on this information.  */
-      reg_scan (get_insns (), max_reg_num (), 1);
+      reg_scan (get_insns (), max_reg_num ());
     }
   cleanup_barriers ();
     }
   cleanup_barriers ();
-  loop_optimize (get_insns (), dump_file, do_unroll | do_prefetch);
+  loop_optimize (get_insns (), dump_file, do_prefetch);
 
   /* Loop can create trivially dead instructions.  */
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   /* Loop can create trivially dead instructions.  */
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  find_basic_blocks (get_insns (), max_reg_num (), dump_file);
+  find_basic_blocks (get_insns ());
   close_dump_file (DFI_loop, print_rtl, get_insns ());
   timevar_pop (TV_LOOP);
 
   close_dump_file (DFI_loop, print_rtl, get_insns ());
   timevar_pop (TV_LOOP);
 
@@ -1389,7 +1192,7 @@ rest_of_handle_loop2 (void)
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
   cleanup_cfg (CLEANUP_EXPENSIVE);
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   if (dump_file)
     dump_flow_info (dump_file);
   close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ());
   if (dump_file)
     dump_flow_info (dump_file);
   close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ());
@@ -1409,7 +1212,7 @@ rest_of_handle_branch_target_load_optimize (void)
       && flag_branch_target_load_optimize2
       && !warned)
     {
       && flag_branch_target_load_optimize2
       && !warned)
     {
-      warning ("branch target register load optimization is not intended "
+      warning (0, "branch target register load optimization is not intended "
               "to be run twice");
 
       warned = 1;
               "to be run twice");
 
       warned = 1;
@@ -1443,31 +1246,15 @@ rest_of_handle_jump (void)
   timevar_push (TV_JUMP);
   open_dump_file (DFI_sibling, current_function_decl);
 
   timevar_push (TV_JUMP);
   open_dump_file (DFI_sibling, current_function_decl);
 
-  /* ??? We may get caled either via tree_rest_of_compilation when the CFG
-     is already built or directly (for instance from coverage code).
-     The direct callers shall be updated.  */
-  if (!basic_block_info)
-    {
-      init_flow ();
-      rebuild_jump_labels (get_insns ());
-      find_exception_handler_labels ();
-      find_basic_blocks (get_insns (), max_reg_num (), dump_file);
-    }
-
-  /* ??? We may get called either via tree_rest_of_compilation when the CFG
-     is already built or directly (for instance from coverage code).
-     The direct callers shall be updated.  */
-  if (!basic_block_info)
-    {
-      init_flow ();
-      rebuild_jump_labels (get_insns ());
-      find_exception_handler_labels ();
-      find_basic_blocks (get_insns (), max_reg_num (), dump_file);
-    }
   delete_unreachable_blocks ();
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
 #endif
   delete_unreachable_blocks ();
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
 #endif
+
+  if (cfun->tail_call_emit)
+    fixup_tail_calls ();
+
+  close_dump_file (DFI_sibling, print_rtl, get_insns ());
   timevar_pop (TV_JUMP);
 }
 
   timevar_pop (TV_JUMP);
 }
 
@@ -1492,24 +1279,6 @@ rest_of_handle_eh (void)
     }
 }
 
     }
 }
 
-
-static void
-rest_of_handle_prologue_epilogue (void)
-{
-  if (optimize && !flow2_completed)
-    cleanup_cfg (CLEANUP_EXPENSIVE);
-
-  /* On some machines, the prologue and epilogue code, or parts thereof,
-     can be represented as RTL.  Doing so lets us schedule insns between
-     it and the rest of the code and also allows delayed branch
-     scheduling to operate in the epilogue.  */
-  thread_prologue_and_epilogue_insns (get_insns ());
-  epilogue_completed = 1;
-
-  if (optimize && flow2_completed)
-    life_analysis (dump_file, PROP_POSTRELOAD);
-}
-
 static void
 rest_of_handle_stack_adjustments (void)
 {
 static void
 rest_of_handle_stack_adjustments (void)
 {
@@ -1545,10 +1314,21 @@ rest_of_handle_flow2 (void)
     split_all_insns (0);
 
   if (flag_branch_target_load_optimize)
     split_all_insns (0);
 
   if (flag_branch_target_load_optimize)
-    rest_of_handle_branch_target_load_optimize ();
+    {
+      close_dump_file (DFI_flow2, print_rtl_with_bb, get_insns ());
+      rest_of_handle_branch_target_load_optimize ();
+      open_dump_file (DFI_flow2, current_function_decl);
+    }
+
+  if (optimize)
+    cleanup_cfg (CLEANUP_EXPENSIVE);
 
 
-  if (!targetm.late_rtl_prologue_epilogue)
-    rest_of_handle_prologue_epilogue ();
+  /* On some machines, the prologue and epilogue code, or parts thereof,
+     can be represented as RTL.  Doing so lets us schedule insns between
+     it and the rest of the code and also allows delayed branch
+     scheduling to operate in the epilogue.  */
+  thread_prologue_and_epilogue_insns (get_insns ());
+  epilogue_completed = 1;
 
   if (optimize)
     rest_of_handle_stack_adjustments ();
 
   if (optimize)
     rest_of_handle_stack_adjustments ();
@@ -1578,7 +1358,7 @@ rest_of_handle_jump2 (void)
     expected_value_to_br_prob ();
 
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
     expected_value_to_br_prob ();
 
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
-  reg_scan (get_insns (), max_reg_num (), 0);
+  reg_scan (get_insns (), max_reg_num ());
   if (dump_file)
     dump_flow_info (dump_file);
   cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
   if (dump_file)
     dump_flow_info (dump_file);
   cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
@@ -1629,7 +1409,7 @@ rest_of_handle_postreload (void)
   /* reload_cse_regs can eliminate potentially-trapping MEMs.
      Remove any EH edges associated with them.  */
   if (flag_non_call_exceptions)
   /* reload_cse_regs can eliminate potentially-trapping MEMs.
      Remove any EH edges associated with them.  */
   if (flag_non_call_exceptions)
-    purge_all_dead_edges (0);
+    purge_all_dead_edges ();
 
   close_dump_file (DFI_postreload, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_RELOAD_CSE_REGS);
 
   close_dump_file (DFI_postreload, print_rtl_with_bb, get_insns ());
   timevar_pop (TV_RELOAD_CSE_REGS);
@@ -1647,8 +1427,20 @@ rest_of_handle_shorten_branches (void)
 static void
 rest_of_clean_state (void)
 {
 static void
 rest_of_clean_state (void)
 {
+  rtx insn, next;
   coverage_end_function ();
 
   coverage_end_function ();
 
+  /* It is very important to decompose the RTL instruction chain here:
+     debug information keeps pointing into CODE_LABEL insns inside the function
+     body.  If these remain pointing to the other insns, we end up preserving
+     whole RTL chain and attached detailed debug info in memory.  */
+  for (insn = get_insns (); insn; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      NEXT_INSN (insn) = NULL;
+      PREV_INSN (insn) = NULL;
+    }
+
   /* In case the function was not output,
      don't leave any temporary anonymous types
      queued up for sdb output.  */
   /* In case the function was not output,
      don't leave any temporary anonymous types
      queued up for sdb output.  */
@@ -1679,8 +1471,7 @@ rest_of_clean_state (void)
   if (targetm.binds_local_p (current_function_decl))
     {
       int pref = cfun->preferred_stack_boundary;
   if (targetm.binds_local_p (current_function_decl))
     {
       int pref = cfun->preferred_stack_boundary;
-      if (cfun->recursive_call_emit
-          && cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
+      if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
        pref = cfun->stack_alignment_needed;
       cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
         = pref;
        pref = cfun->stack_alignment_needed;
       cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
         = pref;
@@ -1699,6 +1490,7 @@ rest_of_clean_state (void)
 
   /* We're done with this function.  Free up memory if we can.  */
   free_after_parsing (cfun);
 
   /* We're done with this function.  Free up memory if we can.  */
   free_after_parsing (cfun);
+  free_after_compilation (cfun);
 }
 \f
 
 }
 \f
 
@@ -1706,37 +1498,14 @@ rest_of_clean_state (void)
    after all tree passes have finished for a single function, and we
    have expanded the function body from trees to RTL.
    Once we are here, we have decided that we're supposed to output
    after all tree passes have finished for a single function, and we
    have expanded the function body from trees to RTL.
    Once we are here, we have decided that we're supposed to output
-   that function, ie. that we should write assembler code for it.
+   that function, i.e. that we should write assembler code for it.
 
    We run a series of low-level passes here on the function's RTL
    representation.  Each pass is called via a rest_of_* function.  */
 
 
    We run a series of low-level passes here on the function's RTL
    representation.  Each pass is called via a rest_of_* function.  */
 
-void
+static void
 rest_of_compilation (void)
 {
 rest_of_compilation (void)
 {
-  /* There's no need to defer outputting this function any more; we
-     know we want to output it.  */
-  DECL_DEFER_OUTPUT (current_function_decl) = 0;
-
-  /* Now that we're done expanding trees to RTL, we shouldn't have any
-     more CONCATs anywhere.  */
-  generating_concat_p = 0;
-
-  /* When processing delayed functions, prepare_function_start () won't
-     have been run to re-initialize it.  */
-  cse_not_expected = ! optimize;
-
-  finalize_block_changes ();
-
-  /* Dump the rtl code if we are dumping rtl.  */
-  if (open_dump_file (DFI_rtl, current_function_decl))
-    close_dump_file (DFI_rtl, print_rtl, get_insns ());
-
-  /* Convert from NOTE_INSN_EH_REGION style notes, and do other
-     sorts of eh initialization.  Delay this until after the
-     initial rtl dump so that we can see the original nesting.  */
-  convert_from_eh_region_ranges ();
-
   /* If we're emitting a nested function, make sure its parent gets
      emitted as well.  Doing otherwise confuses debug info.  */
   {
   /* If we're emitting a nested function, make sure its parent gets
      emitted as well.  Doing otherwise confuses debug info.  */
   {
@@ -1771,9 +1540,6 @@ rest_of_compilation (void)
 
   rest_of_handle_jump ();
 
 
   rest_of_handle_jump ();
 
-  if (cfun->tail_call_emit)
-    fixup_tail_calls ();
-
   rest_of_handle_eh ();
 
   /* Delay emitting hard_reg_initial_value sets until after EH landing pad
   rest_of_handle_eh ();
 
   /* Delay emitting hard_reg_initial_value sets until after EH landing pad
@@ -1834,7 +1600,8 @@ rest_of_compilation (void)
 
       if (flag_branch_probabilities
          && flag_profile_values
 
       if (flag_branch_probabilities
          && flag_profile_values
-         && flag_value_profile_transformations)
+         && (flag_value_profile_transformations
+             || flag_speculative_prefetching))
        rest_of_handle_value_profile_transformations ();
 
       /* Remove the death notes created for vpt.  */
        rest_of_handle_value_profile_transformations ();
 
       /* Remove the death notes created for vpt.  */
@@ -1870,13 +1637,16 @@ rest_of_compilation (void)
     rest_of_handle_if_after_combine ();
 
   /* The optimization to partition hot/cold basic blocks into separate
     rest_of_handle_if_after_combine ();
 
   /* The optimization to partition hot/cold basic blocks into separate
-     sections of the .o file does not work well with exception handling.
-     Don't call it if there are exceptions.  */
+     sections of the .o file does not work well with linkonce or with
+     user defined section attributes.  Don't call it if either case
+     arises.  */
 
 
-  if (optimize > 0 && flag_reorder_blocks_and_partition && !flag_exceptions)
+  if (flag_reorder_blocks_and_partition 
+      && !DECL_ONE_ONLY (current_function_decl)
+      && !user_defined_section_attribute)
     rest_of_handle_partition_blocks ();
 
     rest_of_handle_partition_blocks ();
 
-  if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
+  if (optimize > 0 && flag_regmove)
     rest_of_handle_regmove ();
 
   /* Do unconditional splitting before register allocation to allow machine
     rest_of_handle_regmove ();
 
   /* Do unconditional splitting before register allocation to allow machine
@@ -1890,7 +1660,7 @@ rest_of_compilation (void)
   /* Any of the several passes since flow1 will have munged register
      lifetime data a bit.  We need it to be up to date for scheduling
      (see handling of reg_known_equiv in init_alias_analysis).  */
   /* Any of the several passes since flow1 will have munged register
      lifetime data a bit.  We need it to be up to date for scheduling
      (see handling of reg_known_equiv in init_alias_analysis).  */
-  recompute_reg_usage (get_insns (), !optimize_size);
+  recompute_reg_usage ();
 
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_modulo_sched)
 
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_modulo_sched)
@@ -1905,16 +1675,8 @@ rest_of_compilation (void)
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
-  if (flag_new_regalloc)
-    {
-      if (rest_of_handle_new_regalloc ())
-       goto exit_rest_of_compilation;
-    }
-  else
-    {
-      if (rest_of_handle_old_regalloc ())
-       goto exit_rest_of_compilation;
-    }
+  if (rest_of_handle_old_regalloc ())
+    goto exit_rest_of_compilation;
 
   if (optimize > 0)
     rest_of_handle_postreload ();
 
   if (optimize > 0)
     rest_of_handle_postreload ();
@@ -1948,9 +1710,6 @@ rest_of_compilation (void)
     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
 #endif
 
     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
 #endif
 
-  if (targetm.late_rtl_prologue_epilogue)
-    rest_of_handle_prologue_epilogue ();
-
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_schedule_insns_after_reload)
     rest_of_handle_sched2 ();
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_schedule_insns_after_reload)
     rest_of_handle_sched2 ();
@@ -1962,6 +1721,11 @@ rest_of_compilation (void)
 
   compute_alignments ();
 
 
   compute_alignments ();
 
+  /* Aggressively duplicate basic blocks ending in computed gotos to the
+     tails of their predecessors, unless we are optimizing for size.  */
+  if (flag_expensive_optimizations && !optimize_size)
+    duplicate_computed_gotos ();
+
   if (flag_var_tracking)
     rest_of_handle_variable_tracking ();
 
   if (flag_var_tracking)
     rest_of_handle_variable_tracking ();
 
@@ -1999,16 +1763,12 @@ rest_of_compilation (void)
 }
 
 void
 }
 
 void
-init_optimization_passes (void)
-{
-  open_dump_file (DFI_cgraph, NULL);
-  cgraph_dump_file = dump_file;
-  dump_file = NULL;
-}
-
-void
 finish_optimization_passes (void)
 {
 finish_optimization_passes (void)
 {
+  enum tree_dump_index i;
+  struct dump_file_info *dfi;
+  char *name;
+
   timevar_push (TV_DUMP);
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
   timevar_push (TV_DUMP);
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
@@ -2023,59 +1783,23 @@ finish_optimization_passes (void)
       close_dump_file (DFI_combine, NULL, NULL_RTX);
     }
 
       close_dump_file (DFI_combine, NULL, NULL_RTX);
     }
 
-  dump_file = cgraph_dump_file;
-  cgraph_dump_file = NULL;
-  close_dump_file (DFI_cgraph, NULL, NULL_RTX);
-
   /* Do whatever is necessary to finish printing the graphs.  */
   if (graph_dump_format != no_graph)
   /* Do whatever is necessary to finish printing the graphs.  */
   if (graph_dump_format != no_graph)
-    {
-      int i;
-
-      for (i = 0; i < (int) DFI_MAX; ++i)
-       if (dump_file_tbl[i].initialized && dump_file_tbl[i].graph_dump_p)
-         {
-           char seq[16];
-           char *suffix;
-
-           sprintf (seq, DUMPFILE_FORMAT, i);
-           suffix = concat (seq, dump_file_tbl[i].extension, NULL);
-           finish_graph_dump_file (dump_base_name, suffix);
-           free (suffix);
-         }
-    }
+    for (i = DFI_MIN; (dfi = get_dump_file_info (i)) != NULL; ++i)
+      if (dump_initialized_p (i)
+         && (dfi->flags & TDF_RTL) != 0
+         && (name = get_dump_file_name (i)) != NULL)
+        {
+          finish_graph_dump_file (name);
+          free (name);
+        }
 
   timevar_pop (TV_DUMP);
 }
 
 
   timevar_pop (TV_DUMP);
 }
 
-bool
-enable_rtl_dump_file (int letter)
-{
-  bool matched = false;
-  int i;
-
-  if (letter == 'a')
-    {
-      for (i = 0; i < (int) DFI_MAX; ++i)
-       dump_file_tbl[i].enabled = 1;
-      matched = true;
-    }
-  else
-    {
-      for (i = 0; i < (int) DFI_MAX; ++i)
-       if (letter == dump_file_tbl[i].debug_switch)
-         {
-           dump_file_tbl[i].enabled = 1;
-           matched = true;
-         }
-    }
-
-  return matched;
-}
-
 struct tree_opt_pass pass_rest_of_compilation =
 {
 struct tree_opt_pass pass_rest_of_compilation =
 {
-  "rest of compilation",                /* name */
+  NULL,                                        /* name */
   NULL,                                        /* gate */
   rest_of_compilation,                  /* execute */
   NULL,                                 /* sub */
   NULL,                                        /* gate */
   rest_of_compilation,                  /* execute */
   NULL,                                 /* sub */
@@ -2086,7 +1810,8 @@ struct tree_opt_pass pass_rest_of_compilation =
   0,                                    /* properties_provided */
   PROP_rtl,                             /* properties_destroyed */
   0,                                    /* todo_flags_start */
   0,                                    /* properties_provided */
   PROP_rtl,                             /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_ggc_collect                     /* todo_flags_finish */
+  TODO_ggc_collect,                    /* todo_flags_finish */
+  0                                    /* letter */
 };
 
 
 };