OSDN Git Service

Patches from David Mosberger, and a patch to make bootstrap work.
[pf3gnuchains/gcc-fork.git] / gcc / toplev.c
index 1c65d30..1a35497 100644 (file)
@@ -1,5 +1,6 @@
 /* Top level of GNU C compiler
-   Copyright (C) 1987, 88, 89, 92-98, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -58,6 +59,12 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "graph.h"
 #include "loop.h"
+#include "regs.h"
+#include "timevar.h"
+
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
 
 #ifdef DWARF_DEBUGGING_INFO
 #include "dwarfout.h"
@@ -137,10 +144,9 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
 #define PREFERRED_DEBUGGING_TYPE NO_DEBUG
 #endif
 
-#if ! (defined (VMS) || defined (OS2))
+#ifdef NEED_DECLARATION_ENVIRON
 extern char **environ;
 #endif
-extern char *version_string;
 
 /* Carry information from ASM_DECLARE_OBJECT_NAME
    to ASM_FINISH_DECLARE_OBJECT.  */
@@ -148,35 +154,31 @@ extern char *version_string;
 extern int size_directive_output;
 extern tree last_assemble_variable_decl;
 
-static void set_target_switch PROTO((const char *));
-static const char *decl_name PROTO((tree, int));
+static void set_target_switch PARAMS ((const char *));
+static const char *decl_name PARAMS ((tree, int));
 
-extern void set_fatal_function PROTO((void (*)(const char *, va_list)));
-static void float_signal PROTO((int)) ATTRIBUTE_NORETURN;
-static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
+static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
+static void pipe_closed PARAMS ((int)) ATTRIBUTE_NORETURN;
 #ifdef ASM_IDENTIFY_LANGUAGE
 /* This might or might not be used in ASM_IDENTIFY_LANGUAGE. */
-static void output_lang_identify PROTO((FILE *)) ATTRIBUTE_UNUSED;
+static void output_lang_identify PARAMS ((FILE *)) ATTRIBUTE_UNUSED;
 #endif
-static void open_dump_file PROTO((const char *, const char *));
-static void close_dump_file PROTO((void (*) (FILE *, rtx), rtx));
-static void dump_rtl PROTO((const char *, tree, void (*) (FILE *, rtx), rtx));
-static void clean_dump_file PROTO((const char *));
-static void compile_file PROTO((char *));
-static void display_help PROTO ((void));
-static void mark_file_stack PROTO ((void *));
-
-static void decode_d_option PROTO ((const char *));
-static int  decode_f_option PROTO ((const char *));
-static int  decode_W_option PROTO ((const char *));
-static int  decode_g_option PROTO ((const char *));
-static unsigned independent_decode_option PROTO ((int, char **, unsigned));
-
-static void print_version PROTO((FILE *, const char *));
-static int print_single_switch PROTO((FILE *, int, int, const char *,
+static void compile_file PARAMS ((char *));
+static void display_help PARAMS ((void));
+static void mark_file_stack PARAMS ((void *));
+
+static void decode_d_option PARAMS ((const char *));
+static int decode_f_option PARAMS ((const char *));
+static int decode_W_option PARAMS ((const char *));
+static int decode_g_option PARAMS ((const char *));
+static unsigned int independent_decode_option PARAMS ((int, char **,
+                                                      unsigned int));
+
+static void print_version PARAMS ((FILE *, const char *));
+static int print_single_switch PARAMS ((FILE *, int, int, const char *,
                                      const char *, const char *,
                                      const char *, const char *));
-static void print_switch_values PROTO((FILE *, int, int, const char *,
+static void print_switch_values PARAMS ((FILE *, int, int, const char *,
                                       const char *, const char *));
 
 /* Length of line when printing switch values.  */
@@ -225,40 +227,113 @@ const char *dump_base_name;
 
 extern int target_flags;
 
-/* Flags saying which kinds of debugging dump have been requested.  */
-
-int rtl_dump = 0;
-int rtl_dump_and_exit = 0;
-int jump_opt_dump = 0;
-int addressof_dump = 0;
-int cse_dump = 0;
-int gcse_dump = 0;
-int loop_dump = 0;
-int cse2_dump = 0;
-int branch_prob_dump = 0;
-int flow_dump = 0;
-int combine_dump = 0;
-int regmove_dump = 0;
-int sched_dump = 0;
-int local_reg_dump = 0;
-int global_reg_dump = 0;
-int flow2_dump = 0;
-int peephole2_dump = 0;
-int sched2_dump = 0;
-int jump2_opt_dump = 0;
-#ifdef DELAY_SLOTS
-int dbr_sched_dump = 0;
-#endif
-int flag_print_asm_name = 0;
-#ifdef STACK_REGS
-int stack_reg_dump = 0;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
-int mach_dep_reorg_dump = 0;
-#endif
-static int flag_print_mem = 0;
-static int version_flag = 0;
-static char * filename = 0;
+/* 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_rtl,
+  DFI_sibling,
+  DFI_jump,
+  DFI_cse,
+  DFI_addressof,
+  DFI_ssa,
+  DFI_ussa,
+  DFI_gcse,
+  DFI_loop,
+  DFI_cse2,
+  DFI_bp,
+  DFI_flow,
+  DFI_combine,
+  DFI_ce,
+  DFI_regmove,
+  DFI_sched,
+  DFI_lreg,
+  DFI_greg,
+  DFI_flow2,
+  DFI_ce2,
+  DFI_peephole2,
+  DFI_sched2,
+  DFI_bbro,
+  DFI_rnreg,
+  DFI_jump2,
+  DFI_mach,
+  DFI_dbr,
+  DFI_stack,
+  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:
+
+       "       h      o q   u     "
+       "       H  K   OPQ  TUVWXYZ"
+*/
+
+struct dump_file_info dump_file[DFI_MAX] = 
+{
+  { "rtl",     'r', 0, 0, 0 },
+  { "sibling",  'i', 0, 0, 0 },
+  { "jump",    'j', 0, 0, 0 },
+  { "cse",     's', 0, 0, 0 },
+  { "addressof", 'F', 0, 0, 0 },
+  { "ssa",     'e', 1, 0, 0 },
+  { "ussa",    'e', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
+  { "gcse",    'G', 1, 0, 0 },
+  { "loop",    'L', 1, 0, 0 },
+  { "cse2",    't', 1, 0, 0 },
+  { "bp",      'b', 1, 0, 0 },
+  { "flow",    'f', 1, 0, 0 },
+  { "combine", 'c', 1, 0, 0 },
+  { "ce",      'C', 1, 0, 0 },
+  { "regmove", 'N', 1, 0, 0 },
+  { "sched",   'S', 1, 0, 0 },
+  { "lreg",    'l', 1, 0, 0 },
+  { "greg",    'g', 1, 0, 0 },
+  { "flow2",   'w', 1, 0, 0 },
+  { "ce2",     'E', 1, 0, 0 },
+  { "peephole2", 'z', 1, 0, 0 },
+  { "sched2",  'R', 1, 0, 0 },
+  { "bbro",    'B', 1, 0, 0 },
+  { "rnreg",   'n', 1, 0, 0 },
+  { "jump2",   'J', 1, 0, 0 },
+  { "mach",    'M', 1, 0, 0 },
+  { "dbr",     'd', 0, 0, 0 },
+  { "stack",   'k', 1, 0, 0 },
+};
+
+static int open_dump_file PARAMS ((enum dump_file_index, tree));
+static void close_dump_file PARAMS ((enum dump_file_index,
+                                    void (*) (FILE *, rtx), rtx));
+
+/* Other flags saying which kinds of debugging dump have been requested.  */
+
+int rtl_dump_and_exit;
+int flag_print_asm_name;
+static int flag_print_mem;
+static int version_flag;
+static char * filename;
 enum graph_dump_types graph_dump_format;
 
 /* Name for output file of assembly code, specified with -o.  */
@@ -306,6 +381,14 @@ int errorcount = 0;
 int warningcount = 0;
 int sorrycount = 0;
 
+/* The FUNCTION_DECL for the function currently being compiled,
+   or 0 if between functions.  */
+tree current_function_decl;
+
+/* Set to the FUNC_BEGIN label of the current function, or NULL_TREE
+   if none.  */
+tree current_function_func_begin_label;
+
 /* Pointer to function to compute the name to use to print a declaration.
    DECL is the declaration in question.
    VERBOSITY determines what information will be printed:
@@ -314,22 +397,22 @@ int sorrycount = 0;
      2: and any other information that might be interesting, such as function
         parameter types in C++.  */
 
-const char *(*decl_printable_name)     PROTO ((tree, int));
+const char *(*decl_printable_name)     PARAMS ((tree, int));
 
 /* Pointer to function to compute rtl for a language-specific tree code.  */
 
 typedef rtx (*lang_expand_expr_t)
-  PROTO ((union tree_node *, rtx, enum machine_mode,
+  PARAMS ((union tree_node *, rtx, enum machine_mode,
          enum expand_modifier modifier));
 
 lang_expand_expr_t lang_expand_expr = 0;
 
-tree (*lang_expand_constant) PROTO((tree)) = 0;
+tree (*lang_expand_constant) PARAMS ((tree)) = 0;
 
 /* Pointer to function to finish handling an incomplete decl at the
    end of compilation.  */
 
-void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
+void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
 
 /* Nonzero if generating code to do profiling.  */
 
@@ -351,6 +434,14 @@ int flag_test_coverage = 0;
 
 int flag_branch_probabilities = 0;
 
+/* Nonzero if basic blocks should be reordered. */
+
+int flag_reorder_blocks = 0;
+
+/* Nonzero if registers should be renamed */
+
+int flag_rename_registers = 0;
+
 /* Nonzero for -pedantic switch: warn about anything
    that standard spec forbids.  */
 
@@ -361,11 +452,6 @@ int pedantic = 0;
 
 int in_system_header = 0;
 
-/* Nonzero means do stupid register allocation.
-   Currently, this is 1 if `optimize' is 0.  */
-
-int obey_regdecls = 0;
-
 /* Don't print functions as they are compiled and don't print
    times taken by the various passes.  -quiet.  */
 
@@ -509,6 +595,10 @@ int flag_no_peephole = 0;
 
 int flag_fast_math = 0;
 
+/* Nonzero allows GCC to optimize sibling and tail recursive calls.  */
+
+int flag_optimize_sibling_calls = 0;
+
 /* Nonzero means the front end generally wants `errno' maintained by math
    operations, like built-in SQRT, unless overridden by flag_fast_math.  */
 
@@ -687,6 +777,9 @@ int flag_gnu_linker = 0;
 int flag_gnu_linker = 1;
 #endif
 
+/* Enable SSA.  */
+int flag_ssa = 0;
+
 /* Tag all structures with __attribute__(packed) */
 int flag_pack_struct = 0;
 
@@ -850,6 +943,8 @@ lang_independent_options f_options[] =
    "Defer popping functions args from stack until later" },
   {"omit-frame-pointer", &flag_omit_frame_pointer, 1,
    "When possible do not generate stack frames"},
+  {"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
+   "Optimize sibling and tail recursive calls" },
   {"cse-follow-jumps", &flag_cse_follow_jumps, 1,
    "When running CSE, follow jumps to their targets" },
   {"cse-skip-blocks", &flag_cse_skip_blocks, 1,
@@ -941,6 +1036,10 @@ lang_independent_options f_options[] =
    "Create data files needed by gcov" },
   {"branch-probabilities", &flag_branch_probabilities, 1,
    "Use profiling information for branch probabilities" },
+  {"reorder-blocks", &flag_reorder_blocks, 1,
+   "Reorder basic blocks to improve code placement" },
+  {"rename-registers", &flag_rename_registers, 1,
+   "Do the register renaming optimization pass"},
   {"fast-math", &flag_fast_math, 1,
    "Improve FP speed by violating ANSI & IEEE rules" },
   {"common", &flag_no_common, 0,
@@ -987,6 +1086,8 @@ lang_independent_options f_options[] =
    "Suppress output of instruction numbers and line number notes in debugging dumps"},
   {"instrument-functions", &flag_instrument_function_entry_exit, 1,
    "Instrument function entry/exit with profiling calls"},
+  {"ssa", &flag_ssa, 1,
+   "Enable SSA optimizations" },
   {"leading-underscore", &flag_leading_underscore, 1,
    "External symbols have a leading underscore" },
   {"ident", &flag_no_ident, 0,
@@ -1113,7 +1214,7 @@ documented_lang_options[] =
   { "-Wno-sign-compare", "" },
   { "-Wfloat-equal", "Warn about testing equality of floating point numbers" },
   { "-Wno-float-equal", "" },
-  { "-Wunknown-pragmas", "Warn about unrecognised pragmas" },
+  { "-Wunknown-pragmas", "Warn about unrecognized pragmas" },
   { "-Wno-unknown-pragmas", "" },
   { "-Wstrict-prototypes", "Warn about non-prototyped function decls" },
   { "-Wno-strict-prototypes", "" },
@@ -1223,14 +1324,14 @@ int warn_cast_align;
    characters.  The value N is in `id_clash_len'.  */
 
 int warn_id_clash;
-unsigned id_clash_len;
+int id_clash_len;
 
 /* Nonzero means warn about any objects definitions whose size is larger
    than N bytes.  Also want about function definitions whose returned
    values are larger than N bytes. The value N is in `larger_than_size'.  */
  
 int warn_larger_than;
-unsigned larger_than_size;
+HOST_WIDE_INT larger_than_size;
 
 /* Nonzero means warn if inline function is too large.  */
 
@@ -1312,119 +1413,7 @@ read_integral_parameter (p, pname, defval)
   return atoi (p);
 }
 
-
-/* Time accumulators, to count the total time spent in various passes.  */
-
-int parse_time;
-int varconst_time;
-int integration_time;
-int jump_time;
-int cse_time;
-int gcse_time;
-int loop_time;
-int cse2_time;
-int branch_prob_time;
-int flow_time;
-int combine_time;
-int regmove_time;
-int sched_time;
-int local_alloc_time;
-int global_alloc_time;
-int flow2_time;
-int peephole2_time;
-int sched2_time;
-int dbr_sched_time;
-int shorten_branch_time;
-int stack_reg_time;
-int final_time;
-int symout_time;
-int dump_time;
-int gc_time;
-int all_time;
 \f
-/* Return time used so far, in microseconds.  */
-
-long
-get_run_time ()
-{
-  if (quiet_flag)
-    return 0;
-
-#ifdef __BEOS__
-  return 0;
-#else /* not BeOS */
-#if defined (_WIN32) && !defined (__CYGWIN__)
-  if (clock() < 0)
-    return 0;
-  else
-    return (clock() * 1000);
-#else /* not _WIN32 */
-#ifdef _SC_CLK_TCK
-  {
-    static int tick;
-    struct tms tms;
-    if (tick == 0)
-      tick = 1000000 / sysconf(_SC_CLK_TCK);
-    times (&tms);
-    return (tms.tms_utime + tms.tms_stime) * tick;
-  }
-#else
-#ifdef USG
-  {
-    struct tms tms;
-#   if HAVE_SYSCONF && defined _SC_CLK_TCK
-#    define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
-#   else
-#    ifdef CLK_TCK
-#     define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
-#    else
-#     define TICKS_PER_SECOND HZ /* traditional UNIX */
-#    endif
-#   endif
-    times (&tms);
-    return (tms.tms_utime + tms.tms_stime) * (1000000 / TICKS_PER_SECOND);
-  }
-#else
-#ifndef VMS
-  {
-    struct rusage rusage;
-    getrusage (0, &rusage);
-    return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
-           + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
-  }
-#else /* VMS */
-  {
-    struct
-      {
-        int proc_user_time;
-        int proc_system_time;
-        int child_user_time;
-        int child_system_time;
-      } vms_times;
-    times ((void *) &vms_times);
-    return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
-  }
-#endif /* VMS */
-#endif /* USG */
-#endif  /* _SC_CLK_TCK */
-#endif /* _WIN32 */
-#endif /* __BEOS__ */
-}
-
-#define TIMEVAR(VAR, BODY)    \
-do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
-
-void
-print_time (str, total)
-     const char *str;
-     int total;
-{
-  fprintf (stderr,
-          "time in %s: %d.%06d (%.0f%%)\n",
-          str, total / 1000000, total % 1000000,
-          (double)total / (double)all_time * 100.0);
-}
-
 /* This is the default decl_printable_name function.  */
 
 static const char *
@@ -1436,6 +1425,7 @@ decl_name (decl, verbosity)
 }
 \f
 /* Mark P for GC.  Also mark main_input_filename and input_filename.  */
+
 static void
 mark_file_stack (p)
      void *p;
@@ -1556,7 +1546,7 @@ set_float_handler (handler)
 
 int
 do_float_handler (fn, data)
-  void (*fn) PROTO ((PTR));
+  void (*fn) PARAMS ((PTR));
   PTR data;
 {
   jmp_buf buf;
@@ -1708,87 +1698,92 @@ output_lang_identify (asm_out_file)
 }
 #endif
 
-/* Routine to open a dump file.  */
-static void
-open_dump_file (suffix, function_name)
-     const char *suffix;
-     const char *function_name;
+/* Routine to open a dump file.  Return true if the dump file is enabled.  */
+
+static int
+open_dump_file (index, decl)
+     enum dump_file_index index;
+     tree decl;
 {
-  char *dumpname;
+  char *dump_name;
+  const char *open_arg;
+  char seq[16];
 
-  TIMEVAR
-    (dump_time,
-     {
-       dumpname = concat (dump_base_name, suffix, NULL);
+  if (! dump_file[index].enabled)
+    return 0;
 
-       if (rtl_dump_file != NULL)
-        fclose (rtl_dump_file);
+  timevar_push (TV_DUMP);
+  if (rtl_dump_file != NULL)
+    fclose (rtl_dump_file);
   
-       rtl_dump_file = fopen (dumpname, "a");
-       
-       if (rtl_dump_file == NULL)
-        pfatal_with_name (dumpname);
-       
-       free (dumpname);
+  sprintf (seq, ".%02d.", index);
 
-       if (function_name)
-        fprintf (rtl_dump_file, "\n;; Function %s\n\n", function_name);
-     });
-  
-  return;
-}
+  if (! dump_file[index].initialized)
+    {
+      /* If we've not initialized the files, do so now.  */
+      if (graph_dump_format != no_graph
+         && dump_file[index].graph_dump_p)
+       {
+         dump_name = concat (seq, dump_file[index].extension, NULL);
+         clean_graph_dump_file (dump_base_name, dump_name);
+         free (dump_name);
+       }
+      dump_file[index].initialized = 1;
+      open_arg = "w";
+    }
+  else
+    open_arg = "a";
 
-/* Routine to close a dump file.  */
-static void
-close_dump_file (func, insns)
-     void (*func) PROTO ((FILE *, rtx));
-     rtx    insns;
-{
-  TIMEVAR
-    (dump_time,
-     {
-       if (func)
-        func (rtl_dump_file, insns);
-       
-       fflush (rtl_dump_file);
-       fclose (rtl_dump_file);
+  dump_name = concat (dump_base_name, seq,
+                     dump_file[index].extension, NULL);
+
+  rtl_dump_file = fopen (dump_name, open_arg);
+  if (rtl_dump_file == NULL)
+    pfatal_with_name (dump_name);
        
-       rtl_dump_file = NULL;
-     });
+  free (dump_name);
 
-  return;
-}
+  if (decl)
+    fprintf (rtl_dump_file, "\n;; Function %s\n\n",
+            decl_printable_name (decl, 2));
 
-/* Routine to dump rtl into a file.  */
-static void
-dump_rtl (suffix, decl, func, insns)
-     const char *suffix;
-     tree   decl;
-     void (*func) PROTO ((FILE *, rtx));
-     rtx    insns;
-{
-  open_dump_file (suffix, decl_printable_name (decl, 2));
-  close_dump_file (func, insns);
+  timevar_pop (TV_DUMP);
+  return 1;
 }
 
-/* Routine to empty a dump file.  */
+/* Routine to close a dump file.  */
+
 static void
-clean_dump_file (suffix)
-  const char *suffix;
+close_dump_file (index, func, insns)
+     enum dump_file_index index;
+     void (*func) PARAMS ((FILE *, rtx));
+     rtx    insns;
 {
-  char * const dumpname = concat (dump_base_name, suffix, NULL);
-
-  rtl_dump_file = fopen (dumpname, "w");
+  if (! rtl_dump_file)
+    return;
 
-  if (rtl_dump_file == NULL)
-    pfatal_with_name (dumpname);       
+  timevar_push (TV_DUMP);
+  if (insns
+      && graph_dump_format != no_graph
+      && dump_file[index].graph_dump_p)
+    {
+      char seq[16];
+      char *suffix;
 
-  free (dumpname);
+      sprintf (seq, ".%02d.", index);
+      suffix = concat (seq, dump_file[index].extension, NULL);
+      print_rtl_graph_with_bb (dump_base_name, suffix, insns);
+      free (suffix);
+    }
 
+  if (func && insns)
+    func (rtl_dump_file, insns);
+       
+  fflush (rtl_dump_file);
   fclose (rtl_dump_file);
+       
   rtl_dump_file = NULL;
-  
-  return;
+  timevar_pop (TV_DUMP);
 }
 
 /* Do any final processing required for the declarations in VEC, of
@@ -1949,6 +1944,7 @@ check_global_declarations (vec, len)
          && ! TREE_USED (DECL_NAME (decl)))
        warning_with_decl (decl, "`%s' defined but not used");
 
+      timevar_push (TV_SYMOUT);
 #ifdef SDB_DEBUGGING_INFO
       /* The COFF linker can move initialized global vars to the end.
         And that can screw up the symbol ordering.
@@ -1958,7 +1954,7 @@ check_global_declarations (vec, len)
          && TREE_PUBLIC (decl) && DECL_INITIAL (decl)
          && ! DECL_EXTERNAL (decl)
          && DECL_RTL (decl) != 0)
-       TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+       sdbout_symbol (decl, 0);
 
       /* Output COFF information for non-global
         file-scope initialized variables.  */
@@ -1968,7 +1964,7 @@ check_global_declarations (vec, len)
          && ! DECL_EXTERNAL (decl)
          && DECL_RTL (decl) != 0
          && GET_CODE (DECL_RTL (decl)) == MEM)
-       TIMEVAR (symout_time, sdbout_toplevel_data (decl));
+       sdbout_toplevel_data (decl);
 #endif /* SDB_DEBUGGING_INFO */
 #ifdef DWARF_DEBUGGING_INFO
       /* Output DWARF information for file-scope tentative data object
@@ -1978,7 +1974,7 @@ check_global_declarations (vec, len)
 
       if (write_symbols == DWARF_DEBUG
          && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
-       TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 1));
+       dwarfout_file_scope_decl (decl, 1);
 #endif
 #ifdef DWARF2_DEBUGGING_INFO
       /* Output DWARF2 information for file-scope tentative data object
@@ -1988,11 +1984,58 @@ check_global_declarations (vec, len)
 
       if (write_symbols == DWARF2_DEBUG
          && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)))
-       TIMEVAR (symout_time, dwarf2out_decl (decl));
+       dwarf2out_decl (decl);
 #endif
+      timevar_pop (TV_SYMOUT);
     }
 }
 
+/* Save the current INPUT_FILENAME and LINENO on the top entry in the
+   INPUT_FILE_STACK.  Push a new entry for FILE and LINE, and set the
+   INPUT_FILENAME and LINENO accordingly.  */
+
+void
+push_srcloc (file, line)
+     char *file;
+     int line;
+{
+  struct file_stack *fs;
+
+  if (input_file_stack)
+    {
+      input_file_stack->name = input_filename;
+      input_file_stack->line = lineno;
+    }
+
+  fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+  fs->name = input_filename = file;
+  fs->line = lineno = line;
+  fs->indent_level = 0;
+  fs->next = input_file_stack;
+  input_file_stack = fs;
+  input_file_stack_tick++;
+}
+
+/* Pop the top entry off the stack of presently open source files.
+   Restore the INPUT_FILENAME and LINENO from the new topmost entry on
+   the stack.  */
+
+void
+pop_srcloc ()
+{
+  struct file_stack *fs;
+  
+  fs = input_file_stack;
+  input_file_stack = fs->next;
+  free (fs);
+  input_file_stack_tick++;
+  /* The initial souce file is never popped.  */
+  if (!input_file_stack)
+    abort ();
+  input_filename = input_file_stack->name;
+  lineno = input_file_stack->line;
+}
+
 /* Compile an entire file of output from cpp, named NAME.
    Write a file of assembly output and various debugging dumps.  */
 
@@ -2001,38 +2044,17 @@ compile_file (name)
      char *name;
 {
   tree globals;
-  int start_time;
 
   int name_specified = name != 0;
 
   if (dump_base_name == 0)
     dump_base_name = name ? name : "gccdump";
 
-  parse_time = 0;
-  varconst_time = 0;
-  integration_time = 0;
-  jump_time = 0;
-  cse_time = 0;
-  gcse_time = 0;
-  loop_time = 0;
-  cse2_time = 0;
-  branch_prob_time = 0;
-  flow_time = 0;
-  combine_time = 0;
-  regmove_time = 0;
-  sched_time = 0;
-  local_alloc_time = 0;
-  global_alloc_time = 0;
-  flow2_time = 0;
-  peephole2_time = 0;
-  sched2_time = 0;
-  dbr_sched_time = 0;
-  shorten_branch_time = 0;
-  stack_reg_time = 0;
-  final_time = 0;
-  symout_time = 0;
-  dump_time = 0;
+  /* Start timing total execution time.  */
 
+  init_timevar ();
+  timevar_start (TV_TOTAL);
+  
   /* Initialize data in various passes.  */
 
   init_obstacks ();
@@ -2073,142 +2095,6 @@ compile_file (name)
        pfatal_with_name (aux_info_file_name);
     }
 
-  /* Clear the dump files.  */
-  if (rtl_dump)
-    clean_dump_file (".00.rtl");
-  if (jump_opt_dump)
-    {
-      clean_dump_file (".01.jump");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".01.jump");
-    }
-  if (cse_dump)
-    {
-      clean_dump_file (".02.cse");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".02.cse");
-    }
-  if (addressof_dump)
-    {
-      clean_dump_file (".03.addressof");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".03.addressof");
-    }
-  if (gcse_dump)
-    {
-      clean_dump_file (".04.gcse");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".04.gcse");
-    }
-  if (loop_dump)
-    {
-      clean_dump_file (".05.loop");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".05.loop");
-    }
-  if (cse2_dump)
-    {
-      clean_dump_file (".06.cse2");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".06.cse2");
-    }
-  if (branch_prob_dump)
-    {
-      clean_dump_file (".07.bp");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".07.bp");
-    }
-  if (flow_dump)
-    {
-      clean_dump_file (".08.flow");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".08.flow");
-    }
-  if (combine_dump)
-    {
-      clean_dump_file (".09.combine");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".09.combine");
-    }
-  if (regmove_dump)
-    {
-      clean_dump_file (".10.regmove");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".10.regmove");
-    }
-#ifdef INSN_SCHEDULING
-  if (sched_dump)
-    {
-      clean_dump_file (".11.sched");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".11.sched");
-    }
-#endif
-  if (local_reg_dump)
-    {
-      clean_dump_file (".12.lreg");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".12.lreg");
-    }
-  if (global_reg_dump)
-    {
-      clean_dump_file (".13.greg");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".13.greg");
-    }
-  if (flow2_dump)
-    {
-      clean_dump_file (".14.flow2");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".14.flow2");
-    }
-#ifdef HAVE_peephole2
-  if (peephole2_dump)
-    {
-      clean_dump_file (".15.peephole2");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".15.peephole2");
-    }
-#endif
-#ifdef INSN_SCHEDULING
-  if (sched2_dump)
-    {
-      clean_dump_file (".16.sched2");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".16.sched2");
-    }
-#endif
-  if (jump2_opt_dump)
-    {
-      clean_dump_file (".17.jump2");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".17.jump2");
-    }
-#ifdef MACHINE_DEPENDENT_REORG
-  if (mach_dep_reorg_dump)
-    {
-      clean_dump_file (".18.mach");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".18.mach");
-    }
-#endif
-#ifdef DELAY_SLOTS
-  if (dbr_sched_dump)
-    {
-      clean_dump_file (".19.dbr");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".19.dbr");
-    }
-#endif
-#ifdef STACK_REGS
-  if (stack_reg_dump)
-    {
-      clean_dump_file (".20.stack");
-      if (graph_dump_format != no_graph)
-       clean_graph_dump_file (dump_base_name, ".20.stack");
-    }
-#endif
-
   /* Open assembler code output file.  */
 
   if (flag_syntax_only)
@@ -2247,10 +2133,7 @@ compile_file (name)
   input_filename = name;
 
   /* Put an entry on the input file stack for the main input file.  */
-  input_file_stack
-    = (struct file_stack *) xmalloc (sizeof (struct file_stack));
-  input_file_stack->next = 0;
-  input_file_stack->name = input_filename;
+  push_srcloc (input_filename, 0);
 
   /* Perform language-specific initialization.
      This may set main_input_filename.  */
@@ -2343,19 +2226,18 @@ compile_file (name)
 
   /* If dbx symbol table desired, initialize writing it
      and output the predefined types.  */
+  timevar_push (TV_SYMOUT);
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
-    TIMEVAR (symout_time, dbxout_init (asm_out_file, main_input_filename,
-                                      getdecls ()));
+    dbxout_init (asm_out_file, main_input_filename, getdecls ());
 #endif
 #ifdef SDB_DEBUGGING_INFO
   if (write_symbols == SDB_DEBUG)
-    TIMEVAR (symout_time, sdbout_init (asm_out_file, main_input_filename,
-                                      getdecls ()));
+    sdbout_init (asm_out_file, main_input_filename, getdecls ());
 #endif
 #ifdef DWARF_DEBUGGING_INFO
   if (write_symbols == DWARF_DEBUG)
-    TIMEVAR (symout_time, dwarfout_init (asm_out_file, main_input_filename));
+    dwarfout_init (asm_out_file, main_input_filename);
 #endif
 #ifdef DWARF2_UNWIND_INFO
   if (dwarf2out_do_frame ())
@@ -2363,15 +2245,16 @@ compile_file (name)
 #endif
 #ifdef DWARF2_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
-    TIMEVAR (symout_time, dwarf2out_init (asm_out_file, main_input_filename));
+    dwarf2out_init (asm_out_file, main_input_filename);
 #endif
+  timevar_pop (TV_SYMOUT);
 
   /* Initialize yet another pass.  */
 
   init_final (main_input_filename);
   init_branch_prob (dump_base_name);
 
-  start_time = get_run_time ();
+  timevar_push (TV_PARSE);
 
   /* Call the parser, which parses the entire file
      (calling rest_of_compilation for each function).  */
@@ -2390,10 +2273,7 @@ compile_file (name)
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
 
-  parse_time += get_run_time () - start_time;
-
-  parse_time -= integration_time;
-  parse_time -= varconst_time;
+  timevar_pop (TV_PARSE);
 
   if (flag_syntax_only)
     goto finish_syntax;
@@ -2443,20 +2323,15 @@ compile_file (name)
   weak_finish ();
 
   /* Do dbx symbols */
+  timevar_push (TV_SYMOUT);
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
-    TIMEVAR (symout_time,
-            {
-              dbxout_finish (asm_out_file, main_input_filename);
-            });
+    dbxout_finish (asm_out_file, main_input_filename);
 #endif
 
 #ifdef DWARF_DEBUGGING_INFO
   if (write_symbols == DWARF_DEBUG)
-    TIMEVAR (symout_time,
-            {
-              dwarfout_finish ();
-            });
+    dwarfout_finish ();
 #endif
 
 #ifdef DWARF2_UNWIND_INFO
@@ -2466,29 +2341,27 @@ compile_file (name)
 
 #ifdef DWARF2_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
-    TIMEVAR (symout_time,
-            {
-              dwarf2out_finish ();
-            });
+    dwarf2out_finish ();
 #endif
+  timevar_pop (TV_SYMOUT);
 
   /* Output some stuff at end of file if nec.  */
 
   end_final (dump_base_name);
    
-  if (branch_prob_dump)
-    open_dump_file (".07.bp", NULL);
-   
-  TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
-   
-  if (branch_prob_dump)
-    close_dump_file (NULL, NULL_RTX);
+  if (flag_test_coverage || flag_branch_probabilities)
+    {
+      timevar_push (TV_DUMP);
+      open_dump_file (DFI_bp, NULL);
+      end_branch_prob (rtl_dump_file);
+      close_dump_file (DFI_bp, NULL, NULL_RTX);
+      timevar_pop (TV_DUMP);
+    }
    
 #ifdef ASM_FILE_END
   ASM_FILE_END (asm_out_file);
 #endif
 
-
   /* Language-specific end of compilation actions.  */
  finish_syntax:
   lang_finish ();
@@ -2502,11 +2375,12 @@ compile_file (name)
        unlink (aux_info_file_name);
     }
 
-  if (combine_dump)
+  if (optimize > 0 && open_dump_file (DFI_combine, NULL))
     {
-      open_dump_file (".09.combine", NULL);
-      TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
-      close_dump_file (NULL, NULL_RTX);
+      timevar_push (TV_DUMP);
+      dump_combine_total_stats (rtl_dump_file);
+      close_dump_file (DFI_combine, NULL, NULL_RTX);
+      timevar_pop (TV_DUMP);
     }
 
   /* Close non-debugging input and output files.  Take special care to note
@@ -2522,108 +2396,31 @@ compile_file (name)
   /* Do whatever is necessary to finish printing the graphs.  */
   if (graph_dump_format != no_graph)
     {
-      if (jump_opt_dump)
-       finish_graph_dump_file (dump_base_name, ".01.jump");
-      if (cse_dump)
-       finish_graph_dump_file (dump_base_name, ".02.cse");
-      if (addressof_dump)
-       finish_graph_dump_file (dump_base_name, ".03.addressof");
-      if (gcse_dump)
-       finish_graph_dump_file (dump_base_name, ".04.gcse");
-      if (loop_dump)
-       finish_graph_dump_file (dump_base_name, ".05.loop");
-      if (cse2_dump)
-       finish_graph_dump_file (dump_base_name, ".06.cse2");
-      if (branch_prob_dump)
-       finish_graph_dump_file (dump_base_name, ".07.bp");
-      if (flow_dump)
-       finish_graph_dump_file (dump_base_name, ".08.flow");
-      if (combine_dump)
-       finish_graph_dump_file (dump_base_name, ".09.combine");
-      if (regmove_dump)
-       finish_graph_dump_file (dump_base_name, ".10.regmove");
-#ifdef INSN_SCHEDULING
-      if (sched_dump)
-       finish_graph_dump_file (dump_base_name, ".11.sched");
-#endif
-      if (local_reg_dump)
-       finish_graph_dump_file (dump_base_name, ".12.lreg");
-      if (global_reg_dump)
-       finish_graph_dump_file (dump_base_name, ".13.greg");
-      if (flow2_dump)
-       finish_graph_dump_file (dump_base_name, ".14.flow2");
-#ifdef HAVE_peephole2
-      if (flow2_dump)
-       finish_graph_dump_file (dump_base_name, ".15.peephole2");
-#endif
-#ifdef INSN_SCHEDULING
-      if (sched2_dump)
-       finish_graph_dump_file (dump_base_name, ".16.sched2");
-#endif
-      if (jump2_opt_dump)
-       finish_graph_dump_file (dump_base_name, ".17.jump2");
-#ifdef MACHINE_DEPENDENT_REORG
-      if (mach_dep_reorg_dump)
-       finish_graph_dump_file (dump_base_name, ".18.mach");
-#endif
-#ifdef DELAY_SLOTS
-      if (dbr_sched_dump)
-       finish_graph_dump_file (dump_base_name, ".19.dbr");
-#endif
-#ifdef STACK_REGS
-      if (stack_reg_dump)
-       finish_graph_dump_file (dump_base_name, ".20.stack");
-#endif
+      int i;
+
+      for (i = 0; i < DFI_MAX; ++i)
+       if (dump_file[i].initialized && dump_file[i].graph_dump_p)
+         {
+           char seq[16];
+           char *suffix;
+
+           sprintf (seq, ".%02d.", i);
+           suffix = concat (seq, dump_file[i].extension, NULL);
+           finish_graph_dump_file (dump_base_name, suffix);
+           free (suffix);
+         }
     }
 
   /* Free up memory for the benefit of leak detectors.  */
   free_reg_info ();
 
+  /* Stop timing total execution time.  */
+  timevar_stop (TV_TOTAL);
+
   /* Print the times.  */
 
   if (! quiet_flag)
-    {
-      all_time = get_run_time ();
-
-      fprintf (stderr,"\n");
-
-      print_time ("parse", parse_time);
-      print_time ("integration", integration_time);
-      print_time ("jump", jump_time);
-      print_time ("cse", cse_time);
-      print_time ("gcse", gcse_time);
-      print_time ("loop", loop_time);
-      print_time ("cse2", cse2_time);
-      print_time ("branch-prob", branch_prob_time);
-      print_time ("flow", flow_time);
-      print_time ("combine", combine_time);
-      print_time ("regmove", regmove_time);
-#ifdef INSN_SCHEDULING
-      print_time ("sched", sched_time);
-#endif
-      print_time ("local-alloc", local_alloc_time);
-      print_time ("global-alloc", global_alloc_time);
-      print_time ("flow2", flow2_time);
-#ifdef HAVE_peephole2
-      print_time ("peephole2", peephole2_time);
-#endif
-#ifdef INSN_SCHEDULING
-      print_time ("sched2", sched2_time);
-#endif
-#ifdef DELAY_SLOTS
-      print_time ("dbranch", dbr_sched_time);
-#endif
-      print_time ("shorten-branch", shorten_branch_time);
-#ifdef STACK_REGS
-      print_time ("stack-reg", stack_reg_time);
-#endif
-      print_time ("final", final_time);
-      print_time ("varconst", varconst_time);
-      print_time ("symout", symout_time);
-      print_time ("dump", dump_time);
-      if (ggc_p)
-       print_time ("gc", gc_time);
-    }
+    timevar_print (stderr);
 }
 \f
 /* This is called from various places for FUNCTION_DECL, VAR_DECL,
@@ -2658,29 +2455,30 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
      but we need to treat them as if they were.  */
   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
       || TREE_CODE (decl) == FUNCTION_DECL)
-    TIMEVAR (varconst_time,
-            {
-              make_decl_rtl (decl, asmspec, top_level);
-              /* Initialized extern variable exists to be replaced
-                 with its value, or represents something that will be
-                 output in another file.  */
-              if (! (TREE_CODE (decl) == VAR_DECL
-                     && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
-                     && DECL_INITIAL (decl) != 0
-                     && DECL_INITIAL (decl) != error_mark_node))
-                /* Don't output anything
-                   when a tentative file-scope definition is seen.
-                   But at end of compilation, do output code for them.  */
-                if (! (! at_end && top_level
-                       && (DECL_INITIAL (decl) == 0
-                           || DECL_INITIAL (decl) == error_mark_node)))
-                  assemble_variable (decl, top_level, at_end, 0);
-              if (decl == last_assemble_variable_decl)
-                {
-                  ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
-                                             top_level, at_end);
-                }
-            });
+    {
+      timevar_push (TV_VARCONST);
+      make_decl_rtl (decl, asmspec, top_level);
+      /* Initialized extern variable exists to be replaced
+        with its value, or represents something that will be
+        output in another file.  */
+      if (! (TREE_CODE (decl) == VAR_DECL
+            && DECL_EXTERNAL (decl) && TREE_READONLY (decl)
+            && DECL_INITIAL (decl) != 0
+            && DECL_INITIAL (decl) != error_mark_node))
+       /* Don't output anything
+            when a tentative file-scope definition is seen.
+            But at end of compilation, do output code for them.  */
+       if (! (! at_end && top_level
+              && (DECL_INITIAL (decl) == 0
+                  || DECL_INITIAL (decl) == error_mark_node)))
+         assemble_variable (decl, top_level, at_end, 0);
+      if (decl == last_assemble_variable_decl)
+       {
+         ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
+                                    top_level, at_end);
+       }
+      timevar_pop (TV_VARCONST);
+    }
   else if (DECL_REGISTER (decl) && asmspec != 0)
     {
       if (decode_reg_name (asmspec) >= 0)
@@ -2694,12 +2492,20 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   else if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
           && TREE_CODE (decl) == TYPE_DECL)
-    TIMEVAR (symout_time, dbxout_symbol (decl, 0));
+    {
+      timevar_push (TV_SYMOUT);
+      dbxout_symbol (decl, 0);
+      timevar_pop (TV_SYMOUT);
+    }
 #endif
 #ifdef SDB_DEBUGGING_INFO
   else if (write_symbols == SDB_DEBUG && top_level
           && TREE_CODE (decl) == TYPE_DECL)
-    TIMEVAR (symout_time, sdbout_symbol (decl, 0));
+    {
+      timevar_push (TV_SYMOUT);
+      sdbout_symbol (decl, 0);
+      timevar_pop (TV_SYMOUT);
+    }
 #endif
 }
 
@@ -2715,14 +2521,16 @@ rest_of_type_compilation (type, toplev)
      int toplev ATTRIBUTE_UNUSED;
 #endif
 {
+  timevar_push (TV_SYMOUT);
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
   if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
-    TIMEVAR (symout_time, dbxout_symbol (TYPE_STUB_DECL (type), !toplev));
+    dbxout_symbol (TYPE_STUB_DECL (type), !toplev);
 #endif
 #ifdef SDB_DEBUGGING_INFO
   if (write_symbols == SDB_DEBUG)
-    TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev));
+    sdbout_symbol (TYPE_STUB_DECL (type), !toplev);
 #endif
+  timevar_pop (TV_SYMOUT);
 }
 
 /* DECL is an inline function, whose body is present, but which is not
@@ -2735,13 +2543,13 @@ rest_of_type_compilation (type, toplev)
 
 void
 note_deferral_of_defined_inline_function (decl)
-     tree decl;
+     tree decl ATTRIBUTE_UNUSED;
 {
 #ifdef DWARF_DEBUGGING_INFO
   /* Generate the DWARF info for the "abstract" instance of a function
      which we may later generate inlined and/or out-of-line instances
      of.  */
-  if (write_symbols == DWARF_DEBUG)
+  if (write_symbols == DWARF_DEBUG && DECL_INLINE (decl))
     {
       /* The front-end may not have set CURRENT_FUNCTION_DECL, but the
         DWARF code expects it to be set in this case.  Intuitively,
@@ -2772,27 +2580,30 @@ rest_of_compilation (decl)
      tree decl;
 {
   register rtx insns;
-  int start_time = get_run_time ();
   int tem;
   int failure = 0;
   int rebuild_label_notes_after_reload;
 
+  timevar_push (TV_REST_OF_COMPILATION);
+
   /* When processing delayed functions, prepare_function_start() won't
      have been run to re-initialize it.  */
   cse_not_expected = ! optimize;
 
-  /* First, remove any notes we don't need.  That will make iterating
+  /* First, make sure that NOTE_BLOCK is set correctly for each
+     NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note.  */
+  if (!cfun->x_whole_function_mode_p)
+    identify_blocks ();
+
+  /* Then remove any notes we don't need.  That will make iterating
      over the instruction sequence faster, and allow the garbage
      collector to reclaim the memory used by the notes.  */
-  remove_unncessary_notes ();
+  remove_unnecessary_notes ();
 
   /* In function-at-a-time mode, we do not attempt to keep the BLOCK
      tree in sensible shape.  So, we just recalculate it here.  */
   if (cfun->x_whole_function_mode_p)
-    {
-      find_loop_tree_blocks ();
-      unroll_block_trees ();
-    }
+    reorder_blocks ();
 
   /* If we are reconsidering an inline function
      at the end of compilation, skip the stuff for making it inline.  */
@@ -2819,43 +2630,41 @@ rest_of_compilation (decl)
 
       /* If requested, consider whether to make this function inline.  */
       if (DECL_INLINE (decl) || flag_inline_functions)
-       TIMEVAR (integration_time,
-                {
-                  lose = function_cannot_inline_p (decl);
-                  if (lose || ! optimize)
-                    {
-                      if (warn_inline && DECL_INLINE (decl))
-                        warning_with_decl (decl, lose);
-                      DECL_ABSTRACT_ORIGIN (decl) = 0;
-                      /* Don't really compile an extern inline function.
-                         If we can't make it inline, pretend
-                         it was only declared.  */
-                      if (DECL_EXTERNAL (decl))
-                        {
-                          DECL_INITIAL (decl) = 0;
-                          goto exit_rest_of_compilation;
-                        }
-                    }
-                  else
-                    /* ??? Note that this has the effect of making it look
-                       like "inline" was specified for a function if we choose
-                       to inline it.  This isn't quite right, but it's
-                       probably not worth the trouble to fix.  */
-                    inlinable = DECL_INLINE (decl) = 1;
-                });
+       {
+         timevar_push (TV_INTEGRATION);
+         lose = function_cannot_inline_p (decl);
+         timevar_pop (TV_INTEGRATION);
+         if (lose || ! optimize)
+           {
+             if (warn_inline && DECL_INLINE (decl))
+               warning_with_decl (decl, lose);
+             DECL_ABSTRACT_ORIGIN (decl) = 0;
+             /* Don't really compile an extern inline function.
+                If we can't make it inline, pretend
+                it was only declared.  */
+             if (DECL_EXTERNAL (decl))
+               {
+                 DECL_INITIAL (decl) = 0;
+                 goto exit_rest_of_compilation;
+               }
+           }
+         else
+           /* ??? Note that this has the effect of making it look
+                like "inline" was specified for a function if we choose
+                to inline it.  This isn't quite right, but it's
+                probably not worth the trouble to fix.  */
+           inlinable = DECL_INLINE (decl) = 1;
+       }
 
       insns = get_insns ();
 
       /* Dump the rtl code if we are dumping rtl.  */
 
-      if (rtl_dump)
+      if (open_dump_file (DFI_rtl, decl))
        {
-         open_dump_file (".00.rtl", decl_printable_name (decl, 2));
-         
          if (DECL_SAVED_INSNS (decl))
            fprintf (rtl_dump_file, ";; (integrable)\n\n");
-         
-         close_dump_file (print_rtl, insns);
+         close_dump_file (DFI_rtl, print_rtl, insns);
        }
 
       /* If function is inline, and we don't yet know whether to
@@ -2864,17 +2673,23 @@ rest_of_compilation (decl)
         for those functions that need to be output.  Also defer those
         functions that we are supposed to defer.  */
 
-      if (inlinable)
-       DECL_DEFER_OUTPUT (decl) = 1;
-
-      if (DECL_DEFER_OUTPUT (decl)
+      if (inlinable
          || (DECL_INLINE (decl)
              && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
                   && ! flag_keep_inline_functions)
                  || DECL_EXTERNAL (decl))))
-       {
-         DECL_DEFER_OUTPUT (decl) = 1;
+       DECL_DEFER_OUTPUT (decl) = 1;
 
+      if (DECL_INLINE (decl))
+       /* DWARF wants seperate debugging info for abstract and
+          concrete instances of all inline functions, including those
+          declared inline but not inlined, and those inlined even
+          though they weren't declared inline.  Conveniently, that's
+          what DECL_INLINE means at this point.  */
+       note_deferral_of_defined_inline_function (decl);
+
+      if (DECL_DEFER_OUTPUT (decl))
+       {
          /* If -Wreturn-type, we have to do a bit of compilation.
             However, if we just fall through we will call
             save_for_inline_copying() which results in excessive
@@ -2888,13 +2703,20 @@ rest_of_compilation (decl)
              int saved_optimize = optimize;
              optimize = 0;
              find_exception_handler_labels ();
-             jump_optimize (get_insns(), !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+             jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
                             !JUMP_AFTER_REGSCAN);
              optimize = saved_optimize;
            }
 
-         note_deferral_of_defined_inline_function (decl);
-         TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+         current_function_nothrow = nothrow_function_p ();
+         if (current_function_nothrow)
+           /* Now we know that this can't throw; set the flag for the benefit
+              of other functions later in this translation unit.  */
+           TREE_NOTHROW (current_function_decl) = 1;
+
+         timevar_push (TV_INTEGRATION);
+         save_for_inline_nocopy (decl);
+         timevar_pop (TV_INTEGRATION);
          DECL_SAVED_INSNS (decl)->inlinable = inlinable;
          goto exit_rest_of_compilation;
        }
@@ -2906,6 +2728,11 @@ rest_of_compilation (decl)
        goto exit_rest_of_compilation;
     }
 
+  init_EXPR_INSN_LIST_cache ();
+
+  if (ggc_p)
+    ggc_collect ();
+
   /* Initialize some variables used by the optimizers.  */
   init_function_for_compilation ();
 
@@ -2919,13 +2746,24 @@ rest_of_compilation (decl)
 
   /* Don't return yet if -Wreturn-type; we need to do jump_optimize.  */
   if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)
-    {
-      goto exit_rest_of_compilation;
-    }
+    goto exit_rest_of_compilation;
 
   /* Emit code to get eh context, if needed. */
   emit_eh_context ();
 
+  /* We may have potential sibling or tail recursion sites.  Select one
+     (of possibly multiple) methods of performing the call.  */
+  if (flag_optimize_sibling_calls)
+    {
+      timevar_push (TV_JUMP);
+      open_dump_file (DFI_sibling, decl);
+
+      optimize_sibling_and_tail_recursive_calls ();
+
+      close_dump_file (DFI_sibling, print_rtl, get_insns ());
+      timevar_pop (TV_JUMP);
+    }
+
 #ifdef FINALIZE_PIC
   /* If we are doing position-independent code generation, now
      is the time to output special prologues and epilogues.
@@ -2947,10 +2785,7 @@ rest_of_compilation (decl)
   insns = get_insns ();
 
   /* Copy any shared structure that should not be shared.  */
-
-  unshare_all_rtl (insns);
-
-  init_EXPR_INSN_LIST_cache ();
+  unshare_all_rtl (current_function_decl, insns);
 
 #ifdef SETJMP_VIA_SAVE_AREA
   /* This must be performed before virutal register instantiation.  */
@@ -2959,45 +2794,64 @@ rest_of_compilation (decl)
 #endif
 
   /* Instantiate all virtual registers.  */
-
-  instantiate_virtual_regs (current_function_decl, get_insns ());
-
-  /* See if we have allocated stack slots that are not directly addressable.
-     If so, scan all the insns and create explicit address computation
-     for all references to such slots.  */
-  /* fixup_stack_slots (); */
+  instantiate_virtual_regs (current_function_decl, insns);
 
   /* Find all the EH handlers.  */
   find_exception_handler_labels ();
 
-  if (jump_opt_dump)
-    open_dump_file (".01.jump", decl_printable_name (decl, 2));
+  open_dump_file (DFI_jump, decl);
 
   /* Always do one jump optimization pass to ensure that JUMP_LABEL fields
      are initialized and to compute whether control can drop off the end
      of the function.  */
-  TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
-  TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
-                                    JUMP_AFTER_REGSCAN));
 
-  /* Jump optimization, and the removal of NULL pointer checks, may
-     have reduced the number of instructions substantially.  CSE, and
-     future passes, allocate arrays whose dimensions involve the maximum
-     instruction UID, so if we can reduce the maximum UID we'll save big on
-     memory.  */
-  renumber_insns (rtl_dump_file);
+  timevar_push (TV_JUMP);
+  /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB.  Do this
+     before jump optimization switches branch directions.  */
+  expected_value_to_br_prob ();
 
-  /* Dump rtl code after jump, if we are doing that.  */
-  if (jump_opt_dump)
-    close_dump_file (print_rtl, insns);
+  reg_scan (insns, max_reg_num (), 0);
+  jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+                JUMP_AFTER_REGSCAN);
+
+  timevar_pop (TV_JUMP);
 
   /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
   if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
-    goto exit_rest_of_compilation;
+    {
+      close_dump_file (DFI_jump, print_rtl, insns);
+      goto exit_rest_of_compilation;
+    }
+
+  timevar_push (TV_JUMP);
 
-  /* Try to identify useless null pointer tests and delete them.  */
-  if (flag_delete_null_pointer_checks)
-    TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+  if (optimize > 0)
+    {
+      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+      cleanup_cfg (insns);
+
+      /* ??? Run if-conversion before delete_null_pointer_checks,
+         since the later does not preserve the CFG.  This should
+        be changed -- no since converting if's that are going to
+        be deleted.  */
+      timevar_push (TV_IFCVT);
+      if_convert (0);
+      timevar_pop (TV_IFCVT);
+
+      /* Try to identify useless null pointer tests and delete them.  */
+      if (flag_delete_null_pointer_checks)
+       delete_null_pointer_checks (insns);
+    }
+
+  /* Jump optimization, and the removal of NULL pointer checks, may
+     have reduced the number of instructions substantially.  CSE, and
+     future passes, allocate arrays whose dimensions involve the
+     maximum instruction UID, so if we can reduce the maximum UID
+     we'll save big on memory.  */
+  renumber_insns (rtl_dump_file);
+  timevar_pop (TV_JUMP);
+
+  close_dump_file (DFI_jump, print_rtl, insns);
 
   if (ggc_p)
     ggc_collect ();
@@ -3009,139 +2863,166 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
-      if (cse_dump)
-       open_dump_file (".02.cse", decl_printable_name (decl, 2));
+      open_dump_file (DFI_cse, decl);
+      timevar_push (TV_CSE);
 
-      TIMEVAR (cse_time, reg_scan (insns, max_reg_num (), 1));
+      reg_scan (insns, max_reg_num (), 1);
 
       if (flag_thread_jumps)
-       TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 1));
+       {
+         timevar_push (TV_JUMP);
+         thread_jumps (insns, max_reg_num (), 1);
+         timevar_pop (TV_JUMP);
+       }
+
+      tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
 
-      TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
-                                        0, rtl_dump_file));
       /* If we are not running the second CSE pass, then we are no longer
         expecting CSE to be run.  */
       cse_not_expected = !flag_rerun_cse_after_loop;
 
       if (tem || optimize > 1)
-       TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
-                                          !JUMP_NOOP_MOVES,
-                                          !JUMP_AFTER_REGSCAN));
+       {
+         timevar_push (TV_JUMP);
+         jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+                        !JUMP_AFTER_REGSCAN);
+         timevar_pop (TV_JUMP);
+       }
  
       /* Run this after jump optmizations remove all the unreachable code
         so that unreachable code will not keep values live.  */
-      TIMEVAR (cse_time, delete_trivially_dead_insns (insns, max_reg_num ()));
+      delete_trivially_dead_insns (insns, max_reg_num ());
 
       /* Try to identify useless null pointer tests and delete them.  */
       if (flag_delete_null_pointer_checks)
-       TIMEVAR (jump_time, delete_null_pointer_checks (get_insns ()));
+       {
+         timevar_push (TV_JUMP);
+         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+         cleanup_cfg (insns);
+
+         delete_null_pointer_checks (insns);
+         timevar_pop (TV_JUMP);
+       }
 
       /* The second pass of jump optimization is likely to have
          removed a bunch more instructions.  */
       renumber_insns (rtl_dump_file);
 
-      /* Dump rtl code after cse, if we are doing that.  */
-      if (cse_dump)
-       {
-         close_dump_file (print_rtl, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".02.cse", insns);
-       }
+      timevar_pop (TV_CSE);
+      close_dump_file (DFI_cse, print_rtl, insns);
     }
 
+  open_dump_file (DFI_addressof, decl);
+
   purge_addressof (insns);
   reg_scan (insns, max_reg_num (), 1);
 
-  if (addressof_dump)
-    {
-      dump_rtl (".03.addressof", decl, print_rtl, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".03.addressof", insns);
-    }
+  close_dump_file (DFI_addressof, print_rtl, insns);
 
   if (ggc_p)
     ggc_collect ();
 
+  if (optimize > 0 && flag_ssa)
+    {
+      /* Convert to SSA form.  */
+
+      timevar_push (TV_TO_SSA);
+      open_dump_file (DFI_ssa, decl);
+
+      find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+      cleanup_cfg (insns);
+      convert_to_ssa ();
+
+      close_dump_file (DFI_ssa, print_rtl_with_bb, insns);
+      timevar_pop (TV_TO_SSA);
+
+      /* Currently, there's nothing to do in SSA form.  */
+
+      /* Convert from SSA form.  */
+
+      timevar_push (TV_FROM_SSA);
+      open_dump_file (DFI_ussa, decl);
+
+      convert_from_ssa ();
+      /* New registers have been created.  Rescan their usage.  */
+      reg_scan (insns, max_reg_num (), 1);
+      /* Life analysis used in SSA adds log_links but these
+        shouldn't be there until the flow stage, so clear
+        them away.  */
+      clear_log_links (insns);
+
+      close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
+      timevar_pop (TV_FROM_SSA);
+
+      if (ggc_p)
+       ggc_collect ();
+    }
+
   /* Perform global cse.  */
 
   if (optimize > 0 && flag_gcse)
     {
-      if (gcse_dump)
-       open_dump_file (".04.gcse", decl_printable_name (decl, 2));
+      timevar_push (TV_GCSE);
+      open_dump_file (DFI_gcse, decl);
 
-      TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
+      find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
+      cleanup_cfg (insns);
+      tem = gcse_main (insns, rtl_dump_file);
 
       /* If gcse altered any jumps, rerun jump optimizations to clean
         things up.  */
       if (tem)
        {
-         TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
-                                            !JUMP_NOOP_MOVES,
-                                            !JUMP_AFTER_REGSCAN));
+         timevar_push (TV_JUMP);
+         jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
+                        !JUMP_AFTER_REGSCAN);
+         timevar_pop (TV_JUMP);
         }
 
-      if (gcse_dump)
-       {
-         close_dump_file (print_rtl, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".04.gcse", insns);
-       }
+      close_dump_file (DFI_gcse, print_rtl, insns);
+      timevar_pop (TV_GCSE);
 
       if (ggc_p)
        ggc_collect ();
     }
+
   /* Move constant computations out of loops.  */
 
   if (optimize > 0)
     {
-      if (loop_dump)
-       open_dump_file (".05.loop", decl_printable_name (decl, 2));
-       
-      TIMEVAR
-       (loop_time,
-        {
-          if (flag_rerun_loop_opt)
-            {
-              /* We only want to perform unrolling once.  */
-              
-              loop_optimize (insns, rtl_dump_file, 0, 0);
+      timevar_push (TV_LOOP);
+      open_dump_file (DFI_loop, decl);
+      
+      if (flag_rerun_loop_opt)
+       {
+         /* We only want to perform unrolling once.  */
               
-       
-              /* The first call to loop_optimize makes some instructions
-                 trivially dead.  We delete those instructions now in the
-                 hope that doing so will make the heuristics in loop work
-                 better and possibly speed up compilation.  */
-              delete_trivially_dead_insns (insns, max_reg_num ());
-
-              /* The regscan pass is currently necessary as the alias
-                 analysis code depends on this information.  */
-              reg_scan (insns, max_reg_num (), 1);
-            }
-          loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
-        });
+         loop_optimize (insns, rtl_dump_file, 0, 0);
 
-      /* Dump rtl code after loop opt, if we are doing that.  */
+         /* The first call to loop_optimize makes some instructions
+            trivially dead.  We delete those instructions now in the
+            hope that doing so will make the heuristics in loop work
+            better and possibly speed up compilation.  */
+         delete_trivially_dead_insns (insns, max_reg_num ());
 
-      if (loop_dump)
-       {
-         close_dump_file (print_rtl, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".05.loop", insns);
+         /* The regscan pass is currently necessary as the alias
+                 analysis code depends on this information.  */
+         reg_scan (insns, max_reg_num (), 1);
        }
+      loop_optimize (insns, rtl_dump_file, flag_unroll_loops, 1);
+
+      close_dump_file (DFI_loop, print_rtl, insns);
+      timevar_pop (TV_LOOP);
 
       if (ggc_p)
        ggc_collect ();
     }
 
-  /* ??? Well, nearly.  If HAVE_conditional_arithmetic, jump_optimize
-     has put off all if-conversion until "after CSE".  If we put this
-     off any longer we may miss out doing if-conversion entirely.  */
-  cse_not_expected = 1;
-
   if (optimize > 0)
     {
-      if (cse2_dump)
-       open_dump_file (".06.cse2", decl_printable_name (decl, 2));
+      timevar_push (TV_CSE2);
+      open_dump_file (DFI_cse2, decl);
 
       if (flag_rerun_cse_after_loop)
        {
@@ -3150,188 +3031,215 @@ rest_of_compilation (decl)
             the second CSE pass to do a better job.  Jump_optimize can change
             max_reg_num so we must rerun reg_scan afterwards.
             ??? Rework to not call reg_scan so often.  */
-         TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
-         TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
-                                            !JUMP_NOOP_MOVES,
-                                            JUMP_AFTER_REGSCAN));
+         timevar_push (TV_JUMP);
+
+         reg_scan (insns, max_reg_num (), 0);
+         jump_optimize (insns, !JUMP_CROSS_JUMP,
+                        !JUMP_NOOP_MOVES, JUMP_AFTER_REGSCAN);
+
+         timevar_push (TV_IFCVT);
+
+         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         cleanup_cfg (insns);
+         if_convert (0);
+
+         timevar_pop(TV_IFCVT);
+
+         timevar_pop (TV_JUMP);
          
-         TIMEVAR (cse2_time, reg_scan (insns, max_reg_num (), 0));
-         TIMEVAR (cse2_time, tem = cse_main (insns, max_reg_num (),
-                                             1, rtl_dump_file));
+         reg_scan (insns, max_reg_num (), 0);
+         tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+
          if (tem)
-           TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
-                                              !JUMP_NOOP_MOVES,
-                                              !JUMP_AFTER_REGSCAN));
+           {
+             timevar_push (TV_JUMP);
+             jump_optimize (insns, !JUMP_CROSS_JUMP,
+                            !JUMP_NOOP_MOVES, !JUMP_AFTER_REGSCAN);
+             timevar_pop (TV_JUMP);
+           }
        }
 
       if (flag_thread_jumps)
        {
          /* This pass of jump threading straightens out code
             that was kinked by loop optimization.  */
-         TIMEVAR (jump_time, reg_scan (insns, max_reg_num (), 0));
-         TIMEVAR (jump_time, thread_jumps (insns, max_reg_num (), 0));
+         timevar_push (TV_JUMP);
+         reg_scan (insns, max_reg_num (), 0);
+         thread_jumps (insns, max_reg_num (), 0);
+         timevar_pop (TV_JUMP);
        }
 
-      /* Dump rtl code after cse, if we are doing that.  */
-      if (cse2_dump)
-       {
-         close_dump_file (print_rtl, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".06.cse2", insns);
-       }
+      close_dump_file (DFI_cse2, print_rtl, insns);
+      timevar_pop (TV_CSE2);
 
       if (ggc_p)
        ggc_collect ();
     }
 
+  cse_not_expected = 1;
+
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
-      if (branch_prob_dump)
-       open_dump_file (".07.bp", decl_printable_name (decl, 2));
+      timevar_push (TV_BRANCH_PROB);
+      open_dump_file (DFI_bp, decl);
 
-      TIMEVAR
-       (branch_prob_time,
-        {
-          branch_prob (insns, rtl_dump_file);
-        });
+      branch_prob (insns, rtl_dump_file);
 
-      if (branch_prob_dump)
-       {
-         close_dump_file (print_rtl, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".07.bp", insns);
-       }
+      close_dump_file (DFI_bp, print_rtl, insns);
+      timevar_pop (TV_BRANCH_PROB);
 
       if (ggc_p)
        ggc_collect ();
     }
 
-  /* Now we choose between stupid (pcc-like) register allocation
-     (if we got the -noreg switch and not -opt)
-     and smart register allocation.  */
-
-  if (optimize > 0)            /* Stupid allocation probably won't work */
-    obey_regdecls = 0;         /* if optimizations being done.  */
-
   regclass_init ();
 
   /* Print function header into flow dump now
      because doing the flow analysis makes some of the dump.  */
 
-  if (flow_dump)
-    open_dump_file (".08.flow", decl_printable_name (decl, 2));
+  open_dump_file (DFI_flow, decl);
   
-  if (obey_regdecls)
-    {
-      TIMEVAR (flow_time,
-              {
-                regclass (insns, max_reg_num (), NULL);
-                stupid_life_analysis (insns, max_reg_num (),
-                                      rtl_dump_file);
-              });
-    }
-  else
+  /* Do control and data flow analysis; wrote some of the results to
+     the dump file.  */
+
+  timevar_push (TV_FLOW);
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  cleanup_cfg (insns);
+  if (optimize)
     {
-      /* Do control and data flow analysis,
-        and write some of the results to dump file.  */
+      struct loops loops;
 
-      TIMEVAR
-       (flow_time,
-        {
-          find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
-          calculate_loop_depth (rtl_dump_file);
-          life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
-        });
+      /* 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);
 
-      if (warn_uninitialized || extra_warnings)
-       {
-         uninitialized_vars_warning (DECL_INITIAL (decl));
-          if (extra_warnings)
-           setjmp_args_warning ();
-       }
-    }
+      /* Estimate using heuristics if no profiling info is available.  */
+      if (! flag_branch_probabilities)
+       estimate_probability (&loops);
 
-  /* Dump rtl after flow analysis.  */
+      if (rtl_dump_file)
+       flow_loops_dump (&loops, rtl_dump_file, 0);
+
+      flow_loops_free (&loops);
+    }
+  life_analysis (insns, rtl_dump_file, PROP_FINAL);
+  mark_constant_function ();
+  timevar_pop (TV_FLOW);
 
-  if (flow_dump)
+  if (warn_uninitialized || extra_warnings)
     {
-      close_dump_file (print_rtl_with_bb, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".08.flow", insns);
+      uninitialized_vars_warning (DECL_INITIAL (decl));
+      if (extra_warnings)
+       setjmp_args_warning ();
     }
 
+  close_dump_file (DFI_flow, print_rtl_with_bb, insns);
+
   if (ggc_p)
     ggc_collect ();
 
-  /* The first life analysis pass has finished.  From now on we can not
-     generate any new pseudos.  */
-  no_new_pseudos = 1;
-
   /* If -opt, try combining insns through substitution.  */
 
   if (optimize > 0)
     {
-      TIMEVAR (combine_time, combine_instructions (insns, max_reg_num ()));
+      int rebuild_jump_labels_after_combine = 0;
 
-      /* Dump rtl code after insn combination.  */
+      timevar_push (TV_COMBINE);
+      open_dump_file (DFI_combine, decl);
 
-      if (combine_dump)
+      rebuild_jump_labels_after_combine
+       = combine_instructions (insns, max_reg_num ());
+      
+      /* Combining insns may have turned an indirect jump into a
+        direct jump.  Rebuid the JUMP_LABEL fields of jumping
+        instructions.  */
+      if (rebuild_jump_labels_after_combine)
        {
-         dump_rtl (".09.combine", decl, print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".09.combine", insns);
+         timevar_push (TV_JUMP);
+         rebuild_jump_labels (insns);
+         timevar_pop (TV_JUMP);
+
+         timevar_push (TV_FLOW);
+         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         cleanup_cfg (insns);
+
+         /* Blimey.  We've got to have the CFG up to date for the call to
+            if_convert below.  However, the random deletion of blocks
+            without updating life info can wind up with Wierd Stuff in
+            global_live_at_end.  We then run sched1, which updates things
+            properly, discovers the wierdness and aborts.  */
+         update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+                           PROP_DEATH_NOTES);
+
+         timevar_pop (TV_FLOW);
        }
 
+      close_dump_file (DFI_combine, print_rtl_with_bb, insns);
+      timevar_pop (TV_COMBINE);
+
       if (ggc_p)
        ggc_collect ();
     }
 
+  /* Rerun if-conversion, as combine may have simplified things enough to
+     now meet sequence length restrictions.  */
+  if (optimize > 0)
+    {
+      timevar_push (TV_IFCVT);
+      open_dump_file (DFI_ce, decl);
+
+      if_convert (1);
+
+      close_dump_file (DFI_ce, print_rtl_with_bb, insns);
+      timevar_pop (TV_IFCVT);
+    }
+
   /* Register allocation pre-pass, to reduce number of moves
      necessary for two-address machines.  */
   if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
     {
-      if (regmove_dump)
-       open_dump_file (".10.regmove", decl_printable_name (decl, 2));
+      timevar_push (TV_REGMOVE);
+      open_dump_file (DFI_regmove, decl);
 
-      TIMEVAR (regmove_time, regmove_optimize (insns, max_reg_num (),
-                                              rtl_dump_file));
+      regmove_optimize (insns, max_reg_num (), rtl_dump_file);
 
-      if (regmove_dump)
-       {
-         close_dump_file (print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".10.regmove", insns);
-       }
+      close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
+      timevar_pop (TV_REGMOVE);
 
       if (ggc_p)
        ggc_collect ();
     }
 
-  /* Print function header into sched dump now
-     because doing the sched analysis makes some of the dump.  */
+  if (optimize && n_basic_blocks)
+    {
+      timevar_push (TV_GCSE);
+      optimize_mode_switching (NULL_PTR);
+      timevar_pop (TV_GCSE);
+    }
 
 #ifdef INSN_SCHEDULING
+
+  /* Print function header into sched dump now
+     because doing the sched analysis makes some of the dump.  */
   if (optimize > 0 && flag_schedule_insns)
     {
-      if (sched_dump)
-       open_dump_file (".11.sched", decl_printable_name (decl, 2));
+      timevar_push (TV_SCHED);
+      open_dump_file (DFI_sched, decl);
 
       /* Do control and data sched analysis,
         and write some of the results to dump file.  */
 
-      TIMEVAR (sched_time, schedule_insns (rtl_dump_file));
-
-      /* Dump rtl after instruction scheduling.  */
+      schedule_insns (rtl_dump_file);
 
-      if (sched_dump)
-       {
-         close_dump_file (print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".11.sched", insns);
-       }
+      close_dump_file (DFI_sched, print_rtl_with_bb, insns);
+      timevar_pop (TV_SCHED);
 
       if (ggc_p)
        ggc_collect ();
+
+      /* Register lifetime information is up to date.  From now on
+        we can not generate any new pseudos.  */
+      no_new_pseudos = 1;
     }
 #endif
 
@@ -3340,58 +3248,58 @@ rest_of_compilation (decl)
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
-  if (local_reg_dump)
-    open_dump_file (".12.lreg", decl_printable_name (decl, 2));
+  timevar_push (TV_LOCAL_ALLOC);
+  open_dump_file (DFI_lreg, decl);
 
-  /* Unless we did stupid register allocation,
-     allocate pseudo-regs that are used only within 1 basic block. 
+  /* Allocate pseudo-regs that are used only within 1 basic block. 
 
      RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
      jump optimizer after register allocation and reloading are finished.  */
 
-  if (!obey_regdecls)
-    TIMEVAR (local_alloc_time,
-            {
-              /* We recomputed reg usage as part of updating the rest
-                 of life info during sched.  */
-              if (! flag_schedule_insns)
-                recompute_reg_usage (insns, ! optimize_size);
-              regclass (insns, max_reg_num (), rtl_dump_file);
-              rebuild_label_notes_after_reload = local_alloc ();
-            });
-  else
-    rebuild_label_notes_after_reload = 0;
+  /* We recomputed reg usage as part of updating the rest
+     of life info during sched.  */
+  if (! flag_schedule_insns)
+    {
+      recompute_reg_usage (insns, ! optimize_size);
+
+      /* Register lifetime information is up to date.  From now on
+        we can not generate any new pseudos.  */
+      no_new_pseudos = 1;
+    }
+  regclass (insns, max_reg_num (), rtl_dump_file);
+  rebuild_label_notes_after_reload = local_alloc ();
 
-  /* Dump rtl code after allocating regs within basic blocks.  */
+  timevar_pop (TV_LOCAL_ALLOC);
 
-  if (local_reg_dump)
+  if (dump_file[DFI_lreg].enabled)
     {
-      TIMEVAR (dump_time, dump_flow_info (rtl_dump_file));
-      TIMEVAR (dump_time, dump_local_alloc (rtl_dump_file));
+      timevar_push (TV_DUMP);
+
+      dump_flow_info (rtl_dump_file);
+      dump_local_alloc (rtl_dump_file);
 
-      close_dump_file (print_rtl_with_bb, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".12.lreg", insns);
+      close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
+      timevar_pop (TV_DUMP);
     }
 
   if (ggc_p)
     ggc_collect ();
 
-  if (global_reg_dump)
-    open_dump_file (".13.greg", decl_printable_name (decl, 2));
+  timevar_push (TV_GLOBAL_ALLOC);
+  open_dump_file (DFI_greg, decl);
 
-  /* Unless we did stupid register allocation,
-     allocate remaining pseudo-regs, then do the reload pass
-     fixing up any insns that are invalid.  */
+  /* If optimizing, allocate remaining pseudo-regs.  Do the reload
+     pass fixing up any insns that are invalid.  */
 
-  TIMEVAR (global_alloc_time,
-          {
-            if (!obey_regdecls)
-              failure = global_alloc (rtl_dump_file);
-            else
-              failure = reload (insns, 0, rtl_dump_file);
-          });
+  if (optimize)
+    failure = global_alloc (rtl_dump_file);
+  else
+    {
+      build_insn_chain (insns);
+      failure = reload (insns, 0, rtl_dump_file);
+    }
 
+  timevar_pop (TV_GLOBAL_ALLOC);
 
   if (failure)
     goto exit_rest_of_compilation;
@@ -3401,50 +3309,65 @@ rest_of_compilation (decl)
 
   /* Do a very simple CSE pass over just the hard registers.  */
   if (optimize > 0)
-    reload_cse_regs (insns);
+    {
+      timevar_push (TV_RELOAD_CSE_REGS);
+      reload_cse_regs (insns);
+      timevar_pop (TV_RELOAD_CSE_REGS); 
+    }
+
+  /* If optimizing, then go ahead and split insns now since we are about
+     to recompute flow information anyway.  */
+  if (optimize > 0)
+    split_all_insns (0);
 
   /* Register allocation and reloading may have turned an indirect jump into
      a direct jump.  If so, we must rebuild the JUMP_LABEL fields of
      jumping instructions.  */
   if (rebuild_label_notes_after_reload)
-    TIMEVAR (jump_time, rebuild_jump_labels (insns));
+    {
+      timevar_push (TV_JUMP);
 
-  /* 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.  */
+      rebuild_jump_labels (insns);
 
-  thread_prologue_and_epilogue_insns (insns);
+      timevar_pop (TV_JUMP);
+    }
 
-  /* If optimizing and we are performing instruction scheduling after
-     reload, then go ahead and split insns now since we are about to
-     recompute flow information anyway.
+  if (dump_file[DFI_greg].enabled)
+    {
+      timevar_push (TV_DUMP);
 
-     reload_cse_regs may expose more splitting opportunities, expecially
-     for double-word operations.  */
-  if (optimize > 0 && flag_schedule_insns_after_reload)
-    split_all_insns (0);
+      dump_global_regs (rtl_dump_file);
 
-  if (global_reg_dump)
-    {
-      TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
-      close_dump_file (print_rtl_with_bb, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".13.greg", insns);
+      close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+      timevar_pop (TV_DUMP);
     }
 
   /* Re-create the death notes which were deleted during reload.  */
-  if (flow2_dump)
-    open_dump_file (".14.flow2", decl_printable_name (decl, 2));
-  
+  timevar_push (TV_FLOW2);
+  open_dump_file (DFI_flow2, decl);
+
+  jump_optimize_minimal (insns);
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+  /* 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 (insns);
+
   if (optimize)
     {
-      TIMEVAR
-       (flow2_time,
-        {
-          find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
-          life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
-        });
+      cleanup_cfg (insns);
+      life_analysis (insns, rtl_dump_file, PROP_FINAL);
+
+      /* This is kind of heruistics.  We need to run combine_stack_adjustments
+         even for machines with possibly nonzero RETURN_POPS_ARGS
+         and ACCUMULATE_OUTGOING_ARGS.  We expect that only ports having
+         push instructions will have popping returns.  */
+#ifndef PUSH_ROUNDING
+      if (!ACCUMULATE_OUTGOING_ARGS)
+#endif
+       combine_stack_adjustments ();
 
       if (ggc_p)
        ggc_collect ();
@@ -3452,49 +3375,46 @@ rest_of_compilation (decl)
 
   flow2_completed = 1;
 
-  if (flow2_dump)
+  close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
+  timevar_pop (TV_FLOW2);
+
+  if (optimize > 0)
     {
-      close_dump_file (print_rtl_with_bb, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".14.flow2", insns);
+      timevar_push (TV_IFCVT2);
+      open_dump_file (DFI_ce2, decl);
+
+      if_convert (1);
+
+      close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
+      timevar_pop (TV_IFCVT2);
     }
 
 #ifdef HAVE_peephole2
   if (optimize > 0 && flag_peephole2)
     {
-      if (peephole2_dump)
-       open_dump_file (".15.peephole2", decl_printable_name (decl, 2));
+      timevar_push (TV_PEEPHOLE2);
+      open_dump_file (DFI_peephole2, decl);
 
-      TIMEVAR (peephole2_time, peephole2_optimize (rtl_dump_file));
+      peephole2_optimize (rtl_dump_file);
 
-      if (peephole2_dump)
-       {
-         close_dump_file (print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".15.peephole2", insns);
-       }
+      close_dump_file (DFI_peephole2, print_rtl_with_bb, insns);
+      timevar_pop (TV_PEEPHOLE2);
     }
 #endif
 
 #ifdef INSN_SCHEDULING
   if (optimize > 0 && flag_schedule_insns_after_reload)
     {
-      if (sched2_dump)
-       open_dump_file (".16.sched2", decl_printable_name (decl, 2));
+      timevar_push (TV_SCHED2);
+      open_dump_file (DFI_sched2, decl);
 
       /* Do control and data sched analysis again,
         and write some more of the results to dump file.  */
 
-      TIMEVAR (sched2_time, schedule_insns (rtl_dump_file));
-
-      /* Dump rtl after post-reorder instruction scheduling.  */
+      schedule_insns (rtl_dump_file);
 
-      if (sched2_dump)
-       {
-         close_dump_file (print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".16.sched2", insns);
-       }
+      close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
+      timevar_pop (TV_SCHED2);
 
       if (ggc_p)
        ggc_collect ();
@@ -3506,43 +3426,55 @@ rest_of_compilation (decl)
     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
 #endif
 
-  /* One more attempt to remove jumps to .+1
-     left by dead-store-elimination.
-     Also do cross-jumping this time
-     and delete no-op move insns.  */
+  if (optimize > 0 && flag_reorder_blocks)
+    {
+      timevar_push (TV_REORDER_BLOCKS);
+      open_dump_file (DFI_bbro, decl);
+
+      reorder_basic_blocks ();
+
+      close_dump_file (DFI_bbro, print_rtl_with_bb, insns);
+      timevar_pop (TV_REORDER_BLOCKS);
+    }    
+
+  if (optimize > 0 && flag_rename_registers)
+    {
+      timevar_push (TV_RENAME_REGISTERS);
+      open_dump_file (DFI_rnreg, decl);
+
+      regrename_optimize ();
+
+      close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
+      timevar_pop (TV_RENAME_REGISTERS);
+    }    
+
+  /* One more attempt to remove jumps to .+1 left by dead-store elimination. 
+     Also do cross-jumping this time and delete no-op move insns.  */
 
   if (optimize > 0)
     {
-      TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
-                                        JUMP_NOOP_MOVES,
-                                        !JUMP_AFTER_REGSCAN));
+      timevar_push (TV_JUMP);
+      open_dump_file (DFI_jump2, decl);
 
-      /* Dump rtl code after jump, if we are doing that.  */
+      jump_optimize (insns, JUMP_CROSS_JUMP, JUMP_NOOP_MOVES, 
+                    !JUMP_AFTER_REGSCAN);
 
-      if (jump2_opt_dump)
-       {
-         dump_rtl (".17.jump2", decl, print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".17.jump2", insns);
-       }
+      /* CFG no longer kept up to date.  */
+
+      close_dump_file (DFI_jump2, print_rtl_with_bb, insns);
+      timevar_pop (TV_JUMP);
     }
 
   /* If a machine dependent reorganization is needed, call it.  */
 #ifdef MACHINE_DEPENDENT_REORG
-  if (mach_dep_reorg_dump)
-    open_dump_file (".18.mach", decl_printable_name (decl, 2));
+  open_dump_file (DFI_mach, decl);
 
-   MACHINE_DEPENDENT_REORG (insns);
+  MACHINE_DEPENDENT_REORG (insns);
 
-   if (mach_dep_reorg_dump)
-     {
-       close_dump_file (print_rtl_with_bb, insns);
-       if (graph_dump_format != no_graph)
-        print_rtl_graph_with_bb (dump_base_name, ".18.mach", insns);
-     }
+  close_dump_file (DFI_mach, print_rtl_with_bb, insns);
 
-   if (ggc_p)
-     ggc_collect ();
+  if (ggc_p)
+    ggc_collect ();
 #endif
 
   /* If a scheduling pass for delayed branches is to be done,
@@ -3551,89 +3483,83 @@ rest_of_compilation (decl)
 #ifdef DELAY_SLOTS
   if (optimize > 0 && flag_delayed_branch)
     {
-      if (dbr_sched_dump)
-       open_dump_file (".19.dbr", decl_printable_name (decl, 2));
+      timevar_push (TV_DBR_SCHED);
+      open_dump_file (DFI_dbr, decl);
 
-      TIMEVAR
-       (dbr_sched_time,
-        {
-           dbr_schedule (insns, rtl_dump_file);
-        });
+      dbr_schedule (insns, rtl_dump_file);
 
-      if (dbr_sched_dump)
-       {
-         close_dump_file (print_rtl_with_bb, insns);
-         if (graph_dump_format != no_graph)
-           print_rtl_graph_with_bb (dump_base_name, ".19.dbr", insns);
-       }
-    }
+      close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+      timevar_pop (TV_DBR_SCHED);
 
-   if (ggc_p)
-     ggc_collect ();
+      if (ggc_p)
+       ggc_collect ();
+    }
 #endif
 
   /* Shorten branches. 
 
      Note this must run before reg-stack because of death note (ab)use
      in the ia32 backend.  */
-  TIMEVAR (shorten_branch_time,
-          {
-            shorten_branches (get_insns ());
-          });
+  timevar_push (TV_SHORTEN_BRANCH);
+  shorten_branches (get_insns ());
+  timevar_pop (TV_SHORTEN_BRANCH);
 
 #ifdef STACK_REGS
-  if (stack_reg_dump)
-    open_dump_file (".20.stack", decl_printable_name (decl, 2));
+  timevar_push (TV_REG_STACK);
+  open_dump_file (DFI_stack, decl);
 
-  TIMEVAR (stack_reg_time, reg_to_stack (insns, rtl_dump_file));
+  reg_to_stack (insns, rtl_dump_file);
 
-  if (stack_reg_dump)
-    {
-      close_dump_file (print_rtl_with_bb, insns);
-      if (graph_dump_format != no_graph)
-       print_rtl_graph_with_bb (dump_base_name, ".20.stack", insns);
-    }
+  close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+  timevar_pop (TV_REG_STACK);
 
-   if (ggc_p)
-     ggc_collect ();
+  if (ggc_p)
+    ggc_collect ();
 #endif
 
+  current_function_nothrow = nothrow_function_p ();
+  if (current_function_nothrow)
+    /* Now we know that this can't throw; set the flag for the benefit
+       of other functions later in this translation unit.  */
+    TREE_NOTHROW (current_function_decl) = 1;
+
   /* Now turn the rtl into assembler code.  */
 
-  TIMEVAR (final_time,
-          {
-            rtx x;
-            char *fnname;
+  timevar_push (TV_FINAL);
+  {
+    rtx x;
+    const char *fnname;
 
-            /* Get the function's name, as described by its RTL.
+    /* Get the function's name, as described by its RTL.
                This may be different from the DECL_NAME name used
                in the source file.  */
 
-            x = DECL_RTL (decl);
-            if (GET_CODE (x) != MEM)
-              abort ();
-            x = XEXP (x, 0);
-            if (GET_CODE (x) != SYMBOL_REF)
-              abort ();
-            fnname = XSTR (x, 0);
-
-            assemble_start_function (decl, fnname);
-            final_start_function (insns, asm_out_file, optimize);
-            final (insns, asm_out_file, optimize, 0);
-            final_end_function (insns, asm_out_file, optimize);
-            assemble_end_function (decl, fnname);
-            if (! quiet_flag)
-              fflush (asm_out_file);
+    x = DECL_RTL (decl);
+    if (GET_CODE (x) != MEM)
+      abort ();
+    x = XEXP (x, 0);
+    if (GET_CODE (x) != SYMBOL_REF)
+      abort ();
+    fnname = XSTR (x, 0);
+
+    assemble_start_function (decl, fnname);
+    final_start_function (insns, asm_out_file, optimize);
+    final (insns, asm_out_file, optimize, 0);
+    final_end_function (insns, asm_out_file, optimize);
+    assemble_end_function (decl, fnname);
+    if (! quiet_flag)
+      fflush (asm_out_file);
 
             /* Release all memory allocated by flow.  */
-            free_basic_block_vars (0);
+    free_basic_block_vars (0);
 
-            /* Release all memory held by regsets now */
-            regset_release_memory ();
-          });
+    /* Release all memory held by regsets now */
+    regset_release_memory ();
+  }
+  timevar_pop (TV_FINAL);
 
-   if (ggc_p)
-     ggc_collect ();
+  if (ggc_p)
+    ggc_collect ();
 
   /* Write DBX symbols if requested */
 
@@ -3645,20 +3571,22 @@ rest_of_compilation (decl)
      for those inline functions that need to have out-of-line copies
      generated.  During that call, we *will* be routed past here.  */
 
+  timevar_push (TV_SYMOUT);
 #ifdef DBX_DEBUGGING_INFO
   if (write_symbols == DBX_DEBUG)
-    TIMEVAR (symout_time, dbxout_function (decl));
+    dbxout_function (decl);
 #endif
 
 #ifdef DWARF_DEBUGGING_INFO
   if (write_symbols == DWARF_DEBUG)
-    TIMEVAR (symout_time, dwarfout_file_scope_decl (decl, 0));
+    dwarfout_file_scope_decl (decl, 0);
 #endif
 
 #ifdef DWARF2_DEBUGGING_INFO
   if (write_symbols == DWARF2_DEBUG)
-    TIMEVAR (symout_time, dwarf2out_decl (decl));
+    dwarf2out_decl (decl);
 #endif
+  timevar_pop (TV_SYMOUT);
 
  exit_rest_of_compilation:
 
@@ -3674,24 +3602,25 @@ rest_of_compilation (decl)
   flow2_completed = 0;
   no_new_pseudos = 0;
 
-  TIMEVAR (final_time,
-          {
-             /* Clear out the insn_length contents now that they are no
-                longer valid.  */
-             init_insn_lengths ();
+  timevar_push (TV_FINAL);
+
+  /* Clear out the insn_length contents now that they are no
+     longer valid.  */
+  init_insn_lengths ();
 
-             /* Clear out the real_constant_chain before some of the rtx's
+  /* Clear out the real_constant_chain before some of the rtx's
                 it runs through become garbage.  */
-             clear_const_double_mem ();
+  clear_const_double_mem ();
 
-             /* Cancel the effect of rtl_in_current_obstack.  */
-             resume_temporary_allocation ();
+  /* Cancel the effect of rtl_in_current_obstack.  */
+  resume_temporary_allocation ();
 
-             /* Show no temporary slots allocated.  */
-             init_temp_slots ();
+  /* Show no temporary slots allocated.  */
+  init_temp_slots ();
 
-             free_basic_block_vars (0);
-          });
+  free_basic_block_vars (0);
+
+  timevar_pop (TV_FINAL);
 
   /* Make sure volatile mem refs aren't considered valid operands for
      arithmetic insns.  We must call this here if this is a nested inline
@@ -3713,10 +3642,7 @@ rest_of_compilation (decl)
   if (ggc_p)
     ggc_collect ();
 
-  /* The parsing time is all the time spent in yyparse
-     *except* what is spent in this function.  */
-
-  parse_time -= get_run_time () - start_time;
+  timevar_pop (TV_REST_OF_COMPILATION);
 }
 \f
 static void
@@ -3785,7 +3711,7 @@ display_help ()
   printf ("  -d[letters]             Enable dumps from specific passes of the compiler\n");
   printf ("  -dumpbase <file>        Base name to be used for dumps from specific passes\n");
 #if defined INSN_SCHEDULING
-  printf ("  -sched-verbose=<number> Set the verbosity level of the scheduler\n");
+  printf ("  -fsched-verbose=<number> Set the verbosity level of the scheduler\n");
 #endif
   printf ("  --help                  Display this information\n");
 
@@ -3903,130 +3829,48 @@ static void
 decode_d_option (arg)
      const char * arg;
 {
-  while (* arg)
-    switch (* arg ++)
+  int i, c, matched;
+
+  while (*arg)
+    switch (c = *arg++)
       {
       case 'a':
-       branch_prob_dump = 1;
-       combine_dump = 1;
-#ifdef DELAY_SLOTS
-       dbr_sched_dump = 1;
-#endif
-       flow_dump = 1;
-       flow2_dump = 1;
-       global_reg_dump = 1;
-       jump_opt_dump = 1;
-       addressof_dump = 1;
-       jump2_opt_dump = 1;
-       local_reg_dump = 1;
-       loop_dump = 1;
-       regmove_dump = 1;
-       rtl_dump = 1;
-       cse_dump = 1;
-       cse2_dump = 1;
-       gcse_dump = 1;
-       sched_dump = 1;
-       sched2_dump = 1;
-#ifdef STACK_REGS
-       stack_reg_dump = 1;
-#endif
-#ifdef MACHINE_DEPENDENT_REORG
-       mach_dep_reorg_dump = 1;
-#endif
-       peephole2_dump = 1;
+       for (i = 0; i < DFI_MAX; ++i)
+         dump_file[i].enabled = 1;
        break;
       case 'A':
        flag_debug_asm = 1;
        break;
-      case 'b':
-       branch_prob_dump = 1;
-       break;
-      case 'c':
-       combine_dump = 1;
-       break;
-#ifdef DELAY_SLOTS
-      case 'd':
-       dbr_sched_dump = 1;
-       break;
-#endif
-      case 'f':
-       flow_dump = 1;
-       break;
-      case 'F':
-       addressof_dump = 1;
-       break;
-      case 'g':
-       global_reg_dump = 1;
-       break;
-      case 'G':
-       gcse_dump = 1;
-       break;
-      case 'j':
-       jump_opt_dump = 1;
-       break;
-      case 'J':
-       jump2_opt_dump = 1;
-       break;
-#ifdef STACK_REGS                  
-      case 'k':
-       stack_reg_dump = 1;
-       break;
-#endif
-      case 'l':
-       local_reg_dump = 1;
-       break;
-      case 'L':
-       loop_dump = 1;
-       break;
       case 'm':
        flag_print_mem = 1;
        break;
-#ifdef MACHINE_DEPENDENT_REORG
-      case 'M':
-       mach_dep_reorg_dump = 1;
-       break;
-#endif
       case 'p':
        flag_print_asm_name = 1;
        break;
-      case 'r':
-       rtl_dump = 1;
-       break;
-      case 'R':
-       sched2_dump = 1;
-       break;
-      case 's':
-       cse_dump = 1;
-       break;
-      case 'S':
-       sched_dump = 1;
-       break;
-      case 't':
-       cse2_dump = 1;
-       break;
-      case 'N':
-       regmove_dump = 1;
-       break;
       case 'v':
        graph_dump_format = vcg;
        break;
-      case 'w':
-       flow2_dump = 1;
-       break;
       case 'x':
        rtl_dump_and_exit = 1;
        break;
       case 'y':
        set_yydebug (1);
        break;
-      case 'z':
-       peephole2_dump = 1;
-       break;
       case 'D':        /* These are handled by the preprocessor.  */
       case 'I':
        break;
+
       default:
-       warning ("unrecognised gcc debugging option: %c", arg[-1]);
+       matched = 0;
+       for (i = 0; i < DFI_MAX; ++i)
+         if (c == dump_file[i].debug_switch)
+           {
+             dump_file[i].enabled = 1;
+             matched = 1;
+           }
+
+       if (! matched)
+         warning ("unrecognized gcc debugging option: %c", c);
        break;
       }
 }
@@ -4075,8 +3919,8 @@ decode_f_option (arg)
   else if (!strncmp (arg, "align-loops=", 12))
     align_loops = read_integral_parameter (arg + 12, arg - 2, align_loops);
   else if (!strncmp (arg, "align-functions=", 16))
-    align_functions =
-      read_integral_parameter (arg + 16, arg - 2, align_functions);
+    align_functions
+      read_integral_parameter (arg + 16, arg - 2, align_functions);
   else if (!strncmp (arg, "align-jumps=", 12))
     align_jumps = read_integral_parameter (arg + 12, arg - 2, align_jumps);
   else if (!strncmp (arg, "align-labels=", 13))
@@ -4102,7 +3946,7 @@ decode_f_option (arg)
     stack_limit_rtx = NULL_RTX;
   else if (!strcmp (arg, "preprocessed"))
     /* Recognise this switch but do nothing.  This prevents warnings
-       about an unrecognised switch if cpplib has not been linked in.  */
+       about an unrecognized switch if cpplib has not been linked in.  */
     ;
   else
     return 0;
@@ -4113,6 +3957,7 @@ decode_f_option (arg)
 /* Parse a -W... comand line switch.  ARG is the value after the -W.
    It is safe to access 'ARG - 2' to generate the full switch name.
    Return the number of strings consumed.  */
+
 static int
 decode_W_option (arg)
      const char * arg;
@@ -4139,23 +3984,17 @@ decode_W_option (arg)
 
   if (!strncmp (arg, "id-clash-", 9))
     {
-      const int id_clash_val = read_integral_parameter (arg + 9, arg - 2, -1);
+      id_clash_len = read_integral_parameter (arg + 9, arg - 2, -1);
       
-      if (id_clash_val != -1)
-       {
-         id_clash_len = id_clash_val;
-         warn_id_clash = 1;
-       }
+      if (id_clash_len != -1)
+       warn_id_clash = 1;
     }
   else if (!strncmp (arg, "larger-than-", 12))
     {
-      const int larger_than_val =
-       read_integral_parameter (arg + 12, arg - 2, -1);
-      if (larger_than_val != -1)
-       {
-         larger_than_size = larger_than_val;
-         warn_larger_than = 1;
-       }
+      larger_than_size = read_integral_parameter (arg + 12, arg - 2, -1);
+
+      if (larger_than_size != -1)
+       warn_larger_than = 1;
     }
   else
     return 0;
@@ -4293,13 +4132,13 @@ ignoring option `%s' due to invalid debug level specification",
    number of strings that have already been decoded in a language
    specific fashion before this function was invoked.  */
    
-static unsigned
+static unsigned int
 independent_decode_option (argc, argv, strings_processed)
      int argc;
-     char ** argv;
-     unsigned strings_processed ATTRIBUTE_UNUSED;
+     char **argv;
+     unsigned int strings_processed;
 {
-  char * arg = argv[0];
+  char *arg = argv[0];
   
   if (arg[0] != '-' || arg[1] == 0)
     {
@@ -4322,7 +4161,7 @@ independent_decode_option (argc, argv, strings_processed)
   if (* arg == 'Y')
     arg ++;
   
-  switch (* arg)
+  switch (*arg)
     {
     default:
       return 0;
@@ -4339,7 +4178,10 @@ independent_decode_option (argc, argv, strings_processed)
       return decode_f_option (arg + 1);
            
     case 'g':
-      return decode_g_option (arg + 1);
+      if (strings_processed == 0)
+       return decode_g_option (arg + 1);
+      else
+       return strings_processed;
 
     case 'd':
       if (!strcmp (arg, "dumpbase"))
@@ -4485,7 +4327,7 @@ independent_decode_option (argc, argv, strings_processed)
    Exit code is 35 if can't open files, 34 if fatal error,
    33 if had nonfatal errors, else success.  */
 
-extern int main PROTO ((int, char **));
+extern int main PARAMS ((int, char **));
 
 int
 main (argc, argv)
@@ -4535,6 +4377,8 @@ main (argc, argv)
   ggc_add_root (&input_file_stack, 1, sizeof input_file_stack,
                mark_file_stack);
   ggc_add_rtx_root (&stack_limit_rtx, 1);
+  ggc_add_tree_root (&current_function_decl, 1);
+  ggc_add_tree_root (&current_function_func_begin_label, 1);
 
   /* Perform language-specific options intialization.  */
   lang_init_options ();
@@ -4572,8 +4416,6 @@ main (argc, argv)
        }
     }
 
-  obey_regdecls = (optimize == 0);
-
   if (optimize >= 1)
     {
       flag_defer_pop = 1;
@@ -4588,6 +4430,7 @@ main (argc, argv)
 
   if (optimize >= 2)
     {
+      flag_optimize_sibling_calls = 1;
       flag_cse_follow_jumps = 1;
       flag_cse_skip_blocks = 1;
       flag_gcse = 1;
@@ -4636,8 +4479,8 @@ main (argc, argv)
   /* Perform normal command line switch decoding.  */
   for (i = 1; i < argc;)
     {
-      unsigned lang_processed;
-      unsigned indep_processed;
+      unsigned int lang_processed;
+      unsigned int indep_processed;
 
       /* Give the language a chance to decode the option for itself.  */
       lang_processed = lang_decode_option (argc - i, argv + i);
@@ -4645,7 +4488,7 @@ main (argc, argv)
       /* Now see if the option also has a language independent meaning.
         Some options are both language specific and language independent,
         eg --help.  It is possible that there might be options that should
-        only be decoded in a language independent way if the were not
+        only be decoded in a language independent way if they were not
         decoded in a langauge specific way, which is why 'lang_processed'
         is passed in.  */
       indep_processed = independent_decode_option (argc - i, argv + i,
@@ -4688,7 +4531,7 @@ main (argc, argv)
                }
            }
          else
-           error ("Unrecognised option `%s'", argv[i]);
+           error ("Unrecognized option `%s'", argv[i]);
          
          i++;
        }
@@ -5080,3 +4923,27 @@ debug_undef (lineno, buffer)
     dwarf2out_undef (lineno, buffer);
 #endif /* DWARF2_DEBUGGING_INFO */
 }
+
+/* Returns nonzero if it is appropriate not to emit any debugging
+   information for BLOCK, because it doesn't contain any instructions.
+   This may not be the case for blocks containing nested functions, since
+   we may actually call such a function even though the BLOCK information
+   is messed up.  */
+
+int
+debug_ignore_block (block)
+     tree block ATTRIBUTE_UNUSED;
+{
+  /* Never delete the BLOCK for the outermost scope
+     of the function; we can refer to names from
+     that scope even if the block notes are messed up.  */
+  if (is_body_block (block))
+    return 0;
+
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG)
+    return dwarf2out_ignore_block (block);
+#endif
+
+  return 1;
+}