hangeLog:
authorsamuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Apr 2000 00:59:40 +0000 (00:59 +0000)
committersamuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Apr 2000 00:59:40 +0000 (00:59 +0000)
* Makefile.in (OBJS): Add timevar.o.
(toplev.o): Depend on timevar.h.
(ggc-simple.o): Likewise.
(ggc-page.o): Likewise.
(timevar.o): New rule.
(timevar.h): New rule.

* timevar.h: New file.
* timevar.c: Likewise.
* timevar.def: Likewise.

* toplev.h (gc_time, parse_time, varconst_time): Remove.
* toplev.c: Use timevar_push and timevar_pop instead of TIMEVAR
throughout.
(TIMEVAR): Remove macro.
(gc_time, parse_time, varconst_time, integration_time, jump_time,
cse_time, gcse_time, loop_time, cse2_time, branch_prob_time,
flow_time, combine_time, regmove_time, sched_time,
local_alloc_time, global_alloc_time, flow2_time, peephole2_time,
sched2_time, dbr_sched_time, reorder_blocks_time,
rename_registers_time, shorten_branch_time, stack_reg_time,
to_ssa_time, from_ssa_time, final_time, symout_time, dump_time,
all_time): Remove.
(compile_file): Don't initialize time variables.  Call
init_timevar and start TV_TOTAL timer.  Call timevar_print instead
of many calls to print_time.
(rest_of_compilation): Add timing for reload_cse_regs.
(get_run_time): Removed to timevar.c.
(print_time): Likewise.
(get_run_time): Implement using TV_TOTAL time variable.
(print_time): Get total run time from get_run_time.
* ggc-page.c (ggc_collect): Push and pop TV_GC instead of
computing elapsed time explicitly.
* ggc-simple.c (ggc_collect): Likewise.
(gc_time): Remove declaration.

cp/ChangeLog:

* lex.c (my_get_run_time): Remove.
(init_filename_times): Use get_run_time instead of my_get_run_time.
(check_newline): Likewise.
(dump_time_statistics): Likewise.
* decl2.c (finish_file): Push and pop timevar TV_VARCONST instead
of computing elapsed time explicitly.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33496 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/lex.c
gcc/ggc-page.c
gcc/ggc-simple.c
gcc/timevar.c [new file with mode: 0644]
gcc/timevar.def [new file with mode: 0644]
gcc/timevar.h [new file with mode: 0644]
gcc/toplev.c
gcc/toplev.h

index fc52ec7..35d7605 100644 (file)
@@ -1,3 +1,41 @@
+2000-04-27  Alex Samuel  <samuel@codesourcery.com>
+
+       * Makefile.in (OBJS): Add timevar.o.
+       (toplev.o): Depend on timevar.h.
+       (ggc-simple.o): Likewise.
+       (ggc-page.o): Likewise.
+       (timevar.o): New rule.
+       (timevar.h): New rule.
+
+       * timevar.h: New file.
+       * timevar.c: Likewise.
+       * timevar.def: Likewise.
+
+       * toplev.h (gc_time, parse_time, varconst_time): Remove.
+       * toplev.c: Use timevar_push and timevar_pop instead of TIMEVAR
+       throughout.
+       (TIMEVAR): Remove macro.
+       (gc_time, parse_time, varconst_time, integration_time, jump_time,
+       cse_time, gcse_time, loop_time, cse2_time, branch_prob_time,
+       flow_time, combine_time, regmove_time, sched_time,
+       local_alloc_time, global_alloc_time, flow2_time, peephole2_time,
+       sched2_time, dbr_sched_time, reorder_blocks_time,
+       rename_registers_time, shorten_branch_time, stack_reg_time,
+       to_ssa_time, from_ssa_time, final_time, symout_time, dump_time,
+       all_time): Remove.
+       (compile_file): Don't initialize time variables.  Call
+       init_timevar and start TV_TOTAL timer.  Call timevar_print instead
+       of many calls to print_time.
+       (rest_of_compilation): Add timing for reload_cse_regs.
+       (get_run_time): Removed to timevar.c.
+       (print_time): Likewise.
+       (get_run_time): Implement using TV_TOTAL time variable.
+       (print_time): Get total run time from get_run_time. 
+       * ggc-page.c (ggc_collect): Push and pop TV_GC instead of
+       computing elapsed time explicitly.
+       * ggc-simple.c (ggc_collect): Likewise.
+       (gc_time): Remove declaration.
+       
 2000-04-27  Mark Mitchell  <mark@codesourcery.com>
 
        * calls.c (combine_pending_stack_adjustment_and_call): New function.
index 50856b8..e3c13f0 100644 (file)
@@ -684,7 +684,7 @@ OBJS = diagnostic.o \
  profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
  mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o hash.o \
  predict.o lists.o ggc-common.o $(GGC) simplify-rtx.o ssa.o bb-reorder.o \
- sibcall.o conflict.o
+ sibcall.o conflict.o timevar.o
 
 # GEN files are listed separately, so they can be built before doing parallel
 #  makes for cc1 or cc1plus.  Otherwise sequent parallel make attempts to load
@@ -1470,10 +1470,10 @@ ggc-common.o: ggc-common.c $(CONFIG_H) $(RTL_H) $(TREE_H) \
        flags.h $(GGC_H) varray.h hash.h
 
 ggc-simple.o: ggc-simple.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h \
-       $(GGC_H) varray.h
+       $(GGC_H) varray.h timevar.h
 
 ggc-page.o: ggc-page.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h toplev.h \
-       $(GGC_H) varray.h
+       $(GGC_H) varray.h timevar.h
 
 ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_H) $(GGC_H)
 
@@ -1505,7 +1505,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) function.h \
    flags.h input.h insn-attr.h xcoffout.h defaults.h output.h \
    insn-codes.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h dwarfout.h \
    dwarf2out.h sdbout.h dbxout.h $(EXPR_H) $(BASIC_BLOCK_H) graph.h loop.h \
-   except.h regs.h $(lang_options_files)
+   except.h regs.h timevar.h $(lang_options_files)
        $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
          -DTARGET_NAME=\"$(target_alias)\" \
          -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
@@ -1658,6 +1658,8 @@ lists.o: lists.c $(CONFIG_H) system.h toplev.h $(RTL_H) $(GGC_H)
 bb-reorder.o : bb-reorder.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
    insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
    $(RECOG_H) insn-flags.h function.h except.h $(EXPR_H)
+timevar.o : timevar.c $(CONFIG_H) system.h timevar.h timevar.def
+timevar.h : timevar.def
 
 regrename.o : regrename.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h \
    insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h \
index f835725..fdad422 100644 (file)
@@ -1,3 +1,12 @@
+2000-04-27  Alex Samuel  <samuel@codesourcery.com>
+
+       * lex.c (my_get_run_time): Remove.
+       (init_filename_times): Use get_run_time instead of my_get_run_time.
+       (check_newline): Likewise.
+       (dump_time_statistics): Likewise.
+       * decl2.c (finish_file): Push and pop timevar TV_VARCONST instead
+       of computing elapsed time explicitly.
+
 2000-04-26  Mark Mitchell  <mark@codesourcery.com>
 
        * cp-tree.h (TREE_READONLY_DECL_P): Use DECL_P.
index dd89057..99473a8 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dwarf2out.h"
 #include "dwarfout.h"
 #include "ggc.h"
+#include "timevar.h"
 
 #if USE_CPPLIB
 #include "cpplib.h"
@@ -3429,7 +3430,6 @@ generate_ctor_and_dtor_functions_for_priority (n, data)
 void
 finish_file ()
 {
-  long start_time, this_time;
   tree vars;
   int reconsider;
   size_t i;
@@ -3463,7 +3463,7 @@ finish_file ()
      generating the intiailzer for an object may cause templates to be
      instantiated, etc., etc.  */
 
-  start_time = get_run_time ();
+  timevar_push (TV_VARCONST);
 
   if (new_abi_rtti_p ())
     emit_support_tinfos ();
@@ -3686,9 +3686,7 @@ finish_file ()
   if (back_end_hook)
     (*back_end_hook) (global_namespace);
 
-  this_time = get_run_time ();
-  parse_time -= this_time - start_time;
-  varconst_time += this_time - start_time;
+  timevar_pop (TV_VARCONST);
 
   if (flag_detailed_statistics)
     {
index 7dc6d30..ba32971 100644 (file)
@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "ggc.h"
 #include "tm_p.h"
+#include "timevar.h"
 
 #ifdef MULTIBYTE_CHARS
 #include "mbchar.h"
@@ -56,7 +57,6 @@ static int check_newline PARAMS ((void));
 static int whitespace_cr               PARAMS ((int));
 static int skip_white_space PARAMS ((int));
 static void finish_defarg PARAMS ((void));
-static int my_get_run_time PARAMS ((void));
 static int interface_strcmp PARAMS ((const char *));
 static int readescape PARAMS ((int *));
 static char *extend_token_buffer PARAMS ((const char *));
@@ -388,17 +388,6 @@ get_time_identifier (name)
     }
   return time_identifier;
 }
-
-static inline int
-my_get_run_time ()
-{
-  int old_quiet_flag = quiet_flag;
-  int this_time;
-  quiet_flag = 0;
-  this_time = get_run_time ();
-  quiet_flag = old_quiet_flag;
-  return this_time;
-}
 \f
 /* Table indexed by tree code giving a string containing a character
    classifying the tree code.  Possibilities are
@@ -488,7 +477,7 @@ init_filename_times ()
   if (flag_detailed_statistics)
     {
       header_time = 0;
-      body_time = my_get_run_time ();
+      body_time = get_run_time ();
       TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) 
        = body_time;
     }
@@ -2390,7 +2379,7 @@ linenum:
      is charged against header time, and body time starts back at 0.  */
   if (flag_detailed_statistics)
     {
-      int this_time = my_get_run_time ();
+      int this_time = get_run_time ();
       tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
       header_time += this_time - body_time;
       TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
@@ -5086,7 +5075,7 @@ void
 dump_time_statistics ()
 {
   register tree prev = 0, decl, next;
-  int this_time = my_get_run_time ();
+  int this_time = get_run_time ();
   TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
     += this_time - body_time;
 
index 7fc8b2c..924e952 100644 (file)
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "varray.h"
 #include "flags.h"
 #include "ggc.h"
+#include "timevar.h"
 
 #ifdef HAVE_MMAP_ANYWHERE
 #include <sys/mman.h>
@@ -1101,8 +1102,6 @@ poison_pages ()
 void
 ggc_collect ()
 {
-  long time;
-
   /* Avoid frequent unnecessary work by skipping collection if the
      total allocations haven't expanded much since the last
      collection.  */
@@ -1111,7 +1110,7 @@ ggc_collect ()
     return;
 #endif
 
-  time = get_run_time ();
+  timevar_push (TV_GC);
   if (!quiet_flag)
     fprintf (stderr, " {GC %luk -> ", (unsigned long) G.allocated / 1024);
 
@@ -1136,14 +1135,10 @@ ggc_collect ()
   if (G.allocated_last_gc < GGC_MIN_LAST_ALLOCATED)
     G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
 
-  time = get_run_time () - time;
-  gc_time += time;
+  timevar_pop (TV_GC);
 
   if (!quiet_flag)
-    {
-      fprintf (stderr, "%luk in %.3f}", 
-              (unsigned long) G.allocated / 1024, time * 1e-6);
-    }
+    fprintf (stderr, "%luk}", (unsigned long) G.allocated / 1024);
 }
 
 /* Print allocation statistics.  */
index 6d1545c..b7b6a66 100644 (file)
@@ -26,6 +26,7 @@
 #include "flags.h"
 #include "varray.h"
 #include "ggc.h"
+#include "timevar.h"
 
 #ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
@@ -58,7 +59,6 @@
 /* Constants for general use.  */
 
 char *empty_string;
-extern int gc_time;
 
 #ifndef HOST_BITS_PER_PTR
 #define HOST_BITS_PER_PTR  HOST_BITS_PER_LONG
@@ -339,8 +339,6 @@ sweep_objs (root)
 void
 ggc_collect ()
 {
-  int time;
-
 #ifndef GGC_ALWAYS_COLLECT
   if (G.allocated < GGC_MIN_EXPAND_FOR_GC * G.allocated_last_gc)
     return;
@@ -350,7 +348,7 @@ ggc_collect ()
   debug_ggc_balance ();
 #endif
 
-  time = get_run_time ();
+  timevar_push (TV_GC);
   if (!quiet_flag)
     fprintf (stderr, " {GC %luk -> ", (unsigned long)G.allocated / 1024);
 
@@ -365,14 +363,10 @@ ggc_collect ()
   if (G.allocated_last_gc < GGC_MIN_LAST_ALLOCATED)
     G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
 
-  time = get_run_time () - time;
-  gc_time += time;
+  timevar_pop (TV_GC);
 
   if (!quiet_flag)
-    {
-      fprintf (stderr, "%luk in %.3f}", 
-              (unsigned long) G.allocated / 1024, time * 1e-6);
-    }
+    fprintf (stderr, "%luk}", (unsigned long) G.allocated / 1024);
 
 #ifdef GGC_BALANCE
   debug_ggc_balance ();
diff --git a/gcc/timevar.c b/gcc/timevar.c
new file mode 100644 (file)
index 0000000..61fc92d
--- /dev/null
@@ -0,0 +1,448 @@
+/* Timing variables for measuring compiler performance.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Alex Samuel <samuel@codesourcery.com>
+
+   This file is part of GNU CC.
+
+   GNU CC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#include "timevar.h"
+
+/* See timevar.h for an explanation of timing variables.  */
+
+/* A timing variable.  */
+
+struct timevar_def
+{
+  /* Elapsed time for this variable.  */
+  struct timevar_time_def elapsed;
+
+  /* If this variable is timed independently of the timing stack,
+     using timevar_start, this contains the start time.  */
+  struct timevar_time_def start_time;
+
+  /* Non-zero if this timing variable is running as a standalone
+     timer.  */
+  int standalone;
+
+  /* The name of this timing variable.  */
+  const char *name;
+};
+
+/* An element on the timing stack.  Elapsed time is attributed to the
+   topmost timing variable on the stack.  */
+
+struct timevar_stack_def
+{
+  /* The timing variable at this stack level.  */
+  struct timevar_def *timevar;
+
+  /* The next lower timing variable context in the stack.  */
+  struct timevar_stack_def *next;
+};
+
+/* Declared timing variables.  Constructed from the contents of
+   timevar.def.  */
+static struct timevar_def timevars[TIMEVAR_LAST];
+
+/* The top of the timing stack.  */
+static struct timevar_stack_def *stack;
+
+/* The time at which the topmost element on the timing stack was
+   pushed.  Time elapsed since then is attributed to the topmost
+   element.  */
+static struct timevar_time_def start_time;
+
+static void get_time
+  PARAMS ((struct timevar_time_def *));
+static void timevar_add
+  PARAMS ((struct timevar_time_def *, struct timevar_time_def *));
+static void timevar_accumulate
+  PARAMS ((struct timevar_time_def *, struct timevar_time_def *, 
+          struct timevar_time_def *));
+
+/* Fill the current times into TIME.  The definition of this function
+   also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
+   HAVA_WALL_TIME macros.  */
+
+static void
+get_time (time)
+     struct timevar_time_def *time;
+{
+  time->user = 0;
+  time->sys  = 0;
+  time->wall = 0;
+
+#ifdef __BEOS__
+  /* Nothing.  */
+#else /* not BeOS */
+#if defined (_WIN32) && !defined (__CYGWIN__)
+  if (clock () >= 0)
+    time->user = clock () * 1000;
+#define HAVE_USER_TIME
+
+#else /* not _WIN32 */
+#ifdef _SC_CLK_TCK
+  {
+    static int tick;
+    struct tms tms;
+    if (tick == 0)
+      tick = 1000000 / sysconf (_SC_CLK_TCK);
+    time->wall = times (&tms) * tick;
+    time->user = tms.tms_utime * tick;
+    time->sys = tms.tms_stime * tick;
+  }
+#define HAVE_USER_TIME
+#define HAVE_SYS_TIME
+#define HAVE_WALL_TIME
+
+#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
+    time->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
+    time->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
+    time->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
+  }
+#define HAVE_USER_TIME
+#define HAVE_SYS_TIME
+#define HAVE_WALL_TIME
+
+#else
+#ifndef VMS
+  {
+    struct rusage rusage;
+    getrusage (0, &rusage);
+    time->user 
+      = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
+    time->sys 
+      = rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
+  }
+#define HAVE_USER_TIME
+#define HAVE_SYS_TIME
+
+#else /* VMS */
+  {
+    struct
+      {
+        int proc_user_time;
+        int proc_system_time;
+        int child_user_time;
+        int child_system_time;
+      } vms_times;
+    time->wall = times ((void *) &vms_times) * 10000;
+    time->user = vms_times.proc_user_time * 10000;
+    time->sys = vms_times.proc_system_time * 10000;
+  }
+#define HAVE_USER_TIME
+#define HAVE_SYS_TIME
+#define HAVE_WALL_TIME
+
+#endif /* VMS */
+#endif /* USG */
+#endif  /* _SC_CLK_TCK */
+#endif /* _WIN32 */
+#endif /* __BEOS__ */
+}  
+
+/* Add ELAPSED to TIMER.  */
+
+static void
+timevar_add (timer, elapsed)
+     struct timevar_time_def *timer;
+     struct timevar_time_def *elapsed;
+{
+  timer->user += elapsed->user;
+  timer->sys += elapsed->sys;
+  timer->wall += elapsed->wall;
+}
+
+/* Add the difference between STOP_TIME and START_TIME to TIMER.  */
+
+static void 
+timevar_accumulate (timer, start_time, stop_time)
+  struct timevar_time_def *timer;
+  struct timevar_time_def *start_time;
+  struct timevar_time_def *stop_time;
+{
+  timer->user += stop_time->user - start_time->user;
+  timer->sys += stop_time->sys - start_time->sys;
+  timer->wall += stop_time->wall - start_time->wall;
+}
+
+/* Initialize timing variables.  */
+
+void
+init_timevar (void)
+{
+  /* Zero all elapsed times.  */
+  memset ((void *) timevars, 0, sizeof (timevars));
+
+  /* Initialize the names of timing variables.  */
+#define DEFTIMEVAR(identifer__, name__) \
+  timevars[identifer__].name = name__;
+#include "timevar.def"
+#undef DEFTIMEVAR
+}
+
+/* Push TIMEVAR onto the timing stack.  No further elapsed time is
+   attributed to the previous topmost timing variable on the stack;
+   subsequent elapsed time is attributed to TIMEVAR, until it is
+   popped or another element is pushed on top. 
+
+   TIMEVAR cannot be running as a standalone timer.  */
+
+void
+timevar_push (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+  struct timevar_stack_def *context;
+  struct timevar_time_def now;
+
+  /* Can't push a standalone timer.  */
+  if (tv->standalone)
+    abort ();
+
+  /* What time is it?  */
+  get_time (&now);
+
+  /* If the stack isn't empty, attribute the current elapsed time to
+     the old topmost element.  */
+  if (stack)
+    timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
+
+  /* Reset the start time; from now on, time is attributed to
+     TIMEVAR. */
+  start_time = now;
+
+  /* Create a new stack element, and push it.  */
+  context = (struct timevar_stack_def *) 
+    xmalloc (sizeof (struct timevar_stack_def));
+  context->timevar = tv;
+  context->next = stack;
+  stack = context;
+}
+
+/* Pop the topmost timing variable element off the timing stack.  The
+   popped variable must be TIMEVAR.  Elapsed time since the that
+   element was pushed on, or since it was last exposed on top of the
+   stack when the element above it was popped off, is credited to that
+   timing variable.  */
+
+void
+timevar_pop (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_time_def now;
+  struct timevar_stack_def *next = stack->next;
+
+  if (&timevars[timevar] != stack->timevar)
+    abort ();
+
+  /* What time is it?  */
+  get_time (&now);
+
+  /* Attribute the elapsed time to the element we're popping.  */
+  timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
+
+  /* Reset the start time; from now on, time is attributed to the
+     element just exposed on the stack.  */
+  start_time = now;
+
+  /* Remove the stack element.  */
+  free (stack);
+  stack = next;
+}
+
+/* Start timing TIMEVAR independently of the timing stack.  Elapsed
+   time until timevar_stop is called for the same timing variable is
+   attributed to TIMEVAR.  */
+
+void
+timevar_start (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+
+  /* Don't allow the same timing variable to be started more than
+     once.  */
+  if (tv->standalone)
+    abort ();
+  tv->standalone = 1;
+
+  get_time (&tv->start_time);
+}
+
+/* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
+   is attributed to it.  */
+
+void
+timevar_stop (timevar)
+     timevar_id_t timevar;
+{
+  struct timevar_def *tv = &timevars[timevar];
+  struct timevar_time_def now;
+
+  /* TIMEVAR must have been started via timevar_start.  */
+  if (!tv->standalone)
+    abort ();
+
+  get_time (&now);
+  timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
+}
+
+/* Fill the elapsed time for TIMEVAR into ELAPSED.  Returns
+   update-to-date information even if TIMEVAR is currently running.  */
+
+void
+timevar_get (timevar, elapsed)
+     timevar_id_t timevar;
+     struct timevar_time_def *elapsed;
+{
+  struct timevar_def *tv = &timevars[timevar];
+
+  *elapsed = tv->elapsed;
+
+  /* Is TIMEVAR currently running as a standalone timer?  */
+  if (tv->standalone)
+    /* Add the time elapsed since the it was started.  */
+    timevar_add (elapsed, &tv->start_time);
+
+  /* Is TIMEVAR at the top of the timer stack?  */
+  if (stack->timevar == tv)
+    /* Add the elapsed time since it was pushed.  */
+    timevar_add (elapsed, &start_time);
+}
+
+/* Summarize timing variables to FP.  The timing variable TV_TOTAL has
+   a special meaning -- it's considered to be the total elapsed time,
+   for normalizing the others, and is displayed last.  */
+
+void
+timevar_print (fp)
+     FILE *fp;
+{
+  /* Only print stuff if we have some sort of time information.  */
+#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
+  timevar_id_t id;
+  struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
+
+  fprintf (fp, "\nExecution times (seconds)\n");
+  for (id = 0; id < TIMEVAR_LAST; ++id)
+    {
+      struct timevar_def *tv = &timevars[id];
+
+      /* Don't print the total execution time here; that goes at the
+        end.  */
+      if (id == TV_TOTAL)
+       continue;
+
+      /* The timing variable name.  */
+      fprintf (fp, " %-22s:", tv->name);
+
+#ifdef HAVE_USER_TIME
+      /* Print user-mode time for this process.  */
+      fprintf (fp, "%4ld.%02ld (%2.0f%%) usr", 
+              tv->elapsed.user / 1000000, 
+              (tv->elapsed.user % 1000000) / 10000,
+              (total->user == 0) ? 0.0 
+              : (100.0 * tv->elapsed.user / (double) total->user));
+#endif /* HAVE_USER_TIME */
+
+#ifdef HAVE_SYS_TIME
+      /* Print system-mode time for this process.  */
+      fprintf (fp, "%4ld.%02ld (%2.0f%%) sys", 
+              tv->elapsed.sys / 1000000, 
+              (tv->elapsed.sys % 1000000) / 10000,
+              (total->sys == 0) ? 0.0 
+              : (100.0 * tv->elapsed.sys / (double) total->sys));
+#endif /* HAVE_SYS_TIME */
+
+#ifdef HAVE_WALL_TIME
+      /* Print wall clock time elapsed.  */
+      fprintf (fp, "%4ld.%02ld (%2.0f%%) wall", 
+              tv->elapsed.wall / 1000000, 
+              (tv->elapsed.wall % 1000000) / 10000,
+              (total->wall == 0) ? 0.0 
+              : (100.0 * tv->elapsed.wall / (double) total->wall));
+#endif /* HAVE_WALL_TIME */
+
+      fprintf (fp, "\n");
+    }
+
+  /* Print total time.  */
+  fprintf (fp, " TOTAL                 :");
+#ifdef HAVE_USER_TIME
+  fprintf (fp, "%4ld.%02ld          ", 
+          total->user / 1000000, (total->user % 1000000) / 10000);
+#endif 
+#ifdef HAVE_SYS_TIME
+  fprintf (fp, "%4ld.%02ld          ", 
+          total->sys  / 1000000, (total->sys  % 1000000) / 10000);
+#endif
+#ifdef HAVE_WALL_TIME
+  fprintf (fp, "%4ld.%02ld\n",
+          total->wall / 1000000, (total->wall % 1000000) / 10000);
+#endif
+  
+#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) 
+         || defined (HAVE_WALL_TIME) */
+}
+
+/* Returns time (user + system) used so far by the compiler process,
+   in microseconds.  */
+
+long
+get_run_time ()
+{
+  struct timevar_time_def total_elapsed;
+  timevar_get (TV_TOTAL, &total_elapsed);
+  return total_elapsed.user + total_elapsed.sys;
+}
+
+/* Prints a message to stderr stating that time elapsed in STR is
+   TOTAL (given in microseconds).  */
+
+void
+print_time (str, total)
+     const char *str;
+     long total;
+{
+  long all_time = get_run_time ();
+  fprintf (stderr,
+          "time in %s: %ld.%06ld (%ld%%)\n",
+          str, total / 1000000, total % 1000000,
+          all_time == 0 ? 0
+          : (long) (((100.0 * (double) total) / (double) all_time) + .5));
+}
+
diff --git a/gcc/timevar.def b/gcc/timevar.def
new file mode 100644 (file)
index 0000000..865d074
--- /dev/null
@@ -0,0 +1,73 @@
+/* This file contains the definitions for timing variables used to
+   measure run-time performance of the compiler.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Alex Samuel <samuel@codesourcery.com>
+
+   This file is part of GNU CC.
+
+   GNU CC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This file contains timing variable definitions, used by timevar.h
+   and timevar.c.
+
+   Syntax:
+
+     DEFTIMEVAR (id, name)
+
+   where ID is the enumeral value used to identify the timing
+   variable, and NAME is a character string describing its purpose.  */
+
+/* The total execution time.  */
+DEFTIMEVAR (TV_TOTAL                 , "total time")
+
+/* Time spent garbage-collecting.  */
+DEFTIMEVAR (TV_GC                    , "garbage collection")
+
+/* Time spent generating dump files.  */
+DEFTIMEVAR (TV_DUMP                  , "dump files")
+
+/* Timing in various stages of the compiler.  */
+DEFTIMEVAR (TV_PARSE                 , "parser")
+DEFTIMEVAR (TV_VARCONST              , "varconst")
+DEFTIMEVAR (TV_INTEGRATION           , "integration")
+DEFTIMEVAR (TV_JUMP                  , "jump")
+DEFTIMEVAR (TV_CSE                   , "CSE")
+DEFTIMEVAR (TV_GCSE                  , "global CSE")
+DEFTIMEVAR (TV_LOOP                  , "loop analysis")
+DEFTIMEVAR (TV_CSE2                  , "CSE 2")
+DEFTIMEVAR (TV_BRANCH_PROB           , "branch prediction")
+DEFTIMEVAR (TV_FLOW                  , "flow analysis")
+DEFTIMEVAR (TV_COMBINE               , "combiner")
+DEFTIMEVAR (TV_REGMOVE               , "regmove")
+DEFTIMEVAR (TV_SCHED                 , "scheduling")
+DEFTIMEVAR (TV_LOCAL_ALLOC           , "local alloc")
+DEFTIMEVAR (TV_GLOBAL_ALLOC          , "global alloc")
+DEFTIMEVAR (TV_RELOAD_CSE_REGS       , "reload CSE regs")
+DEFTIMEVAR (TV_FLOW2                 , "flow 2")
+DEFTIMEVAR (TV_PEEPHOLE2             , "peephole 2")
+DEFTIMEVAR (TV_SCHED2                , "schedulding 2")
+DEFTIMEVAR (TV_DBR_SCHED             , "delay branch sched")
+DEFTIMEVAR (TV_REORDER_BLOCKS        , "reorder blocks")
+DEFTIMEVAR (TV_RENAME_REGISTERS      , "rename registers")
+DEFTIMEVAR (TV_SHORTEN_BRANCH        , "shorten branches")
+DEFTIMEVAR (TV_REG_STACK             , "reg stack")
+DEFTIMEVAR (TV_TO_SSA                , "convert to SSA")
+DEFTIMEVAR (TV_FROM_SSA              , "convert from SSA")
+DEFTIMEVAR (TV_FINAL                 , "final")
+DEFTIMEVAR (TV_SYMOUT                , "symout")
+
+/* Everything else in rest_of_compilation not included above.  */
+DEFTIMEVAR (TV_REST_OF_COMPILATION   , "rest of compilation")
diff --git a/gcc/timevar.h b/gcc/timevar.h
new file mode 100644 (file)
index 0000000..c7fcfa7
--- /dev/null
@@ -0,0 +1,86 @@
+/* Timing variables for measuring compiler performance.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Alex Samuel <samuel@codesourcery.com>
+
+   This file is part of GNU CC.
+
+   GNU CC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU CC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Timing variables are used to measure elapsed time in various
+   portions of the compiler.  Each measures elapsed user, system, and
+   wall-clock time, as appropriate to and supported by the host
+   system.
+
+   Timing variables are defined using the DEFTIMEVAR macro in
+   timevar.def.  Each has an enumeral identifier, used when referring
+   to the timing variable in code, and a character string name.
+
+   Timing variables can be used in two ways:
+
+     - On the timing stack, using timevar_push and timevar_pop.
+       Timing variables may be pushed onto the stack; elapsed time is
+       attributed to the topmost timing variable on the stack.  When
+       another variable is pushed on, the previous topmost variable is
+       `paused' until the pushed variable is popped back off.
+
+     - As a standalone timer, using timevar_start and timevar_stop.
+       All time elapsed between the two calls is attributed to the
+       variable.  
+*/
+   
+/* This structure stores the various varieties of time that can be
+   measured.  Times are stored in microseconds.  The time may be an
+   absolute time or a time difference; in the former case, the time
+   base is undefined, except that the difference between two times
+   produces a valid time difference.  */
+
+struct timevar_time_def
+{
+  /* User time in this process.  */
+  long user;
+
+  /* System time (if applicable for this host platform) in this
+     process.  */
+  long sys;
+
+  /* Wall clock time.  */
+  long wall;
+};
+
+/* An enumeration of timing variable indentifiers.  Constructed from
+   the contents of timevar.def.  */
+
+#define DEFTIMEVAR(identifier__, name__) \
+    identifier__, 
+typedef enum
+{
+#include "timevar.def"
+  TIMEVAR_LAST
+}
+timevar_id_t;
+#undef DEFTIMEVAR
+
+extern void init_timevar PARAMS ((void));
+extern void timevar_push PARAMS ((timevar_id_t));
+extern void timevar_pop PARAMS ((timevar_id_t));
+extern void timevar_start PARAMS ((timevar_id_t));
+extern void timevar_stop PARAMS ((timevar_id_t));
+extern void timevar_get PARAMS ((timevar_id_t, struct timevar_time_def *));
+extern void timevar_print PARAMS ((FILE *));
+
+/* Provided for backward compatibility.  */
+extern long get_run_time PARAMS ((void));
+extern void print_time PARAMS ((const char *, long));
index 65f7ee8..e175a40 100644 (file)
@@ -60,6 +60,7 @@ Boston, MA 02111-1307, USA.  */
 #include "graph.h"
 #include "loop.h"
 #include "regs.h"
+#include "timevar.h"
 
 #ifndef ACCUMULATE_OUTGOING_ARGS
 #define ACCUMULATE_OUTGOING_ARGS 0
@@ -1402,130 +1403,7 @@ read_integral_parameter (p, pname, defval)
   return atoi (p);
 }
 
-
-/* Time accumulators, to count the total time spent in various passes.
-   The first three are used in other files; the latter two only here.  */
-
-long gc_time;
-long parse_time;
-long varconst_time;
-
-static long integration_time;
-static long jump_time;
-static long cse_time;
-static long gcse_time;
-static long loop_time;
-static long cse2_time;
-static long branch_prob_time;
-static long flow_time;
-static long combine_time;
-static long regmove_time;
-static long sched_time;
-static long local_alloc_time;
-static long global_alloc_time;
-static long flow2_time;
-static long peephole2_time;
-static long sched2_time;
-static long dbr_sched_time;
-static long reorder_blocks_time;
-static long rename_registers_time;
-static long shorten_branch_time;
-static long stack_reg_time;
-static long to_ssa_time;
-static long from_ssa_time;
-static long final_time;
-static long symout_time;
-static long dump_time;
-static long 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 {                                   \
-  long otime = get_run_time ();                \
-  BODY;                                        \
-  VAR += get_run_time () - otime;      \
-} while (0)
-
-void
-print_time (str, total)
-     const char *str;
-     long total;
-{
-  fprintf (stderr,
-          "time in %s: %ld.%06ld (%ld%%)\n",
-          str, total / 1000000, total % 1000000,
-          all_time == 0 ? 0
-          : (long) (((100.0 * (double) total) / (double) all_time) + .5));
-}
-
 /* This is the default decl_printable_name function.  */
 
 static const char *
@@ -1824,44 +1702,42 @@ open_dump_file (index, decl)
   if (! dump_file[index].enabled)
     return 0;
 
-  TIMEVAR
-    (dump_time,
-      {
-       if (rtl_dump_file != NULL)
-         fclose (rtl_dump_file);
+  timevar_push (TV_DUMP);
+  if (rtl_dump_file != NULL)
+    fclose (rtl_dump_file);
   
-       sprintf (seq, ".%02d.", index);
+  sprintf (seq, ".%02d.", index);
 
-       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";
+  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";
 
-       dump_name = concat (dump_base_name, seq,
-                           dump_file[index].extension, NULL);
+  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 = fopen (dump_name, open_arg);
+  if (rtl_dump_file == NULL)
+    pfatal_with_name (dump_name);
        
-       free (dump_name);
+  free (dump_name);
 
-       if (decl)
-         fprintf (rtl_dump_file, "\n;; Function %s\n\n",
-                  decl_printable_name (decl, 2));
-      });
-  
+  if (decl)
+    fprintf (rtl_dump_file, "\n;; Function %s\n\n",
+            decl_printable_name (decl, 2));
+
+  timevar_pop (TV_DUMP);
   return 1;
 }
 
@@ -1876,30 +1752,28 @@ close_dump_file (index, func, insns)
   if (! rtl_dump_file)
     return;
 
-  TIMEVAR
-    (dump_time,
-      {
-       if (insns
-           && graph_dump_format != no_graph
-           && dump_file[index].graph_dump_p)
-         {
-           char seq[16];
-           char *suffix;
+  timevar_push (TV_DUMP);
+  if (insns
+      && graph_dump_format != no_graph
+      && dump_file[index].graph_dump_p)
+    {
+      char seq[16];
+      char *suffix;
 
-           sprintf (seq, ".%02d.", index);
-           suffix = concat (seq, dump_file[index].extension, NULL);
-           print_rtl_graph_with_bb (dump_base_name, suffix, insns);
-           free (suffix);
-         }
+      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);
+  if (func && insns)
+    func (rtl_dump_file, insns);
        
-       fflush (rtl_dump_file);
-       fclose (rtl_dump_file);
+  fflush (rtl_dump_file);
+  fclose (rtl_dump_file);
        
-       rtl_dump_file = NULL;
-     });
+  rtl_dump_file = NULL;
+  timevar_pop (TV_DUMP);
 }
 
 /* Do any final processing required for the declarations in VEC, of
@@ -2060,6 +1934,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.
@@ -2069,7 +1944,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.  */
@@ -2079,7 +1954,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
@@ -2089,7 +1964,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
@@ -2099,8 +1974,9 @@ 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);
     }
 }
 
@@ -2158,42 +2034,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;
-  reorder_blocks_time = 0;
-  rename_registers_time = 0;
-  shorten_branch_time = 0;
-  stack_reg_time = 0;
-  to_ssa_time = 0;
-  from_ssa_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 ();
@@ -2365,19 +2216,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 ())
@@ -2385,15 +2235,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).  */
@@ -2412,10 +2263,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;
@@ -2465,20 +2313,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
@@ -2488,11 +2331,9 @@ 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.  */
 
@@ -2500,11 +2341,11 @@ compile_file (name)
    
   if (flag_test_coverage || flag_branch_probabilities)
     {
+      timevar_push (TV_DUMP);
       open_dump_file (DFI_bp, NULL);
-   
-      TIMEVAR (dump_time, end_branch_prob (rtl_dump_file));
-   
+      end_branch_prob (rtl_dump_file);
       close_dump_file (DFI_bp, NULL, NULL_RTX);
+      timevar_pop (TV_DUMP);
     }
    
 #ifdef ASM_FILE_END
@@ -2526,8 +2367,10 @@ compile_file (name)
 
   if (optimize > 0 && open_dump_file (DFI_combine, NULL))
     {
-      TIMEVAR (dump_time, dump_combine_total_stats (rtl_dump_file));
+      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
@@ -2561,55 +2404,13 @@ compile_file (name)
   /* 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 ("to ssa", to_ssa_time);
-      print_time ("from ssa", from_ssa_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 ("bbro", reorder_blocks_time);
-      print_time ("rnreg", rename_registers_time);
-      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,
@@ -2644,29 +2445,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)
@@ -2680,12 +2482,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
 }
 
@@ -2701,14 +2511,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));
+    symout_time, 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
@@ -2758,11 +2570,12 @@ 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;
@@ -2807,30 +2620,31 @@ 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 ();
 
@@ -2883,7 +2697,9 @@ rest_of_compilation (decl)
            TREE_NOTHROW (current_function_decl) = 1;
 
          note_deferral_of_defined_inline_function (decl);
-         TIMEVAR (integration_time, save_for_inline_nocopy (decl));
+         timevar_push (TV_INTEGRATION);
+         save_for_inline_nocopy (decl);
+         timevar_pop (TV_INTEGRATION);
          DECL_SAVED_INSNS (decl)->inlinable = inlinable;
          goto exit_rest_of_compilation;
        }
@@ -2922,13 +2738,15 @@ rest_of_compilation (decl)
      (of possibly multiple) methods of performing the call.  */
   if (flag_optimize_sibling_calls)
     {
+      timevar_push (TV_JUMP);
       open_dump_file (DFI_sibling, decl);
 
-      TIMEVAR (jump_time, optimize_sibling_and_tail_recursive_calls ());
+      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.
@@ -2969,16 +2787,17 @@ rest_of_compilation (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,
-          {
-            /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB.  Do this
-               before jump optimization switches branch directions.  */
-            expected_value_to_br_prob ();
 
-            reg_scan (insns, max_reg_num (), 0);
-            jump_optimize (insns, !JUMP_CROSS_JUMP, !JUMP_NOOP_MOVES,
-                           JUMP_AFTER_REGSCAN);
-          });
+  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 ();
+
+  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))
@@ -2987,23 +2806,22 @@ rest_of_compilation (decl)
       goto exit_rest_of_compilation;
     }
 
-  TIMEVAR (jump_time,
-          {
-            /* Try to identify useless null pointer tests and delete them.  */
-            if (flag_delete_null_pointer_checks)
-              {
-                find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-                cleanup_cfg (insns);
-                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_push (TV_JUMP);
+  /* Try to identify useless null pointer tests and delete them.  */
+  if (flag_delete_null_pointer_checks)
+    {
+      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+      cleanup_cfg (insns);
+      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);
 
@@ -3018,41 +2836,52 @@ rest_of_compilation (decl)
   if (optimize > 0)
     {
       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);
+       }
 
-      TIMEVAR (cse_time, tem = cse_main (insns, max_reg_num (),
-                                        0, rtl_dump_file));
+      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,
-                {
-                  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-                  cleanup_cfg (insns);
-                  delete_null_pointer_checks (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);
 
+      timevar_pop (TV_CSE);
       close_dump_file (DFI_cse, print_rtl, insns);
     }
 
@@ -3068,33 +2897,35 @@ rest_of_compilation (decl)
 
   if (optimize > 0 && flag_ssa)
     {
+      /* Convert to SSA form.  */
+
+      timevar_push (TV_TO_SSA);
       open_dump_file (DFI_ssa, decl);
 
-      TIMEVAR (to_ssa_time,
-              {
-                find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
-                cleanup_cfg (insns);
-                convert_to_ssa ();
-              });
+      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);
 
-      open_dump_file (DFI_ussa, decl);
+      /* Currently, there's nothing to do in SSA form.  */
 
-      TIMEVAR (from_ssa_time,
-              {
-                convert_from_ssa ();
+      /* Convert from SSA form.  */
 
-                /* New registers have been created.  Rescan their usage.  */
-                reg_scan (insns, max_reg_num (), 1);
+      timevar_push (TV_FROM_SSA);
+      open_dump_file (DFI_ussa, decl);
 
-                /* 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);
-              });
+      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 ();
@@ -3104,25 +2935,25 @@ rest_of_compilation (decl)
 
   if (optimize > 0 && flag_gcse)
     {
+      timevar_push (TV_GCSE);
       open_dump_file (DFI_gcse, decl);
 
-      TIMEVAR (gcse_time,
-              {
-                find_basic_blocks (insns, max_reg_num(), rtl_dump_file);
-                cleanup_cfg (insns);
-                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);
         }
 
       close_dump_file (DFI_gcse, print_rtl, insns);
+      timevar_pop (TV_GCSE);
 
       if (ggc_p)
        ggc_collect ();
@@ -3132,31 +2963,29 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
+      timevar_push (TV_LOOP);
       open_dump_file (DFI_loop, decl);
-
-      TIMEVAR
-       (loop_time,
-        {
-          if (flag_rerun_loop_opt)
-            {
-              /* We only want to perform unrolling once.  */
+      
+      if (flag_rerun_loop_opt)
+       {
+         /* We only want to perform unrolling once.  */
               
-              loop_optimize (insns, rtl_dump_file, 0, 0);
+         loop_optimize (insns, rtl_dump_file, 0, 0);
 
-              /* 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 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
+         /* 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);
-        });
+         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 ();
@@ -3169,6 +2998,7 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
+      timevar_push (TV_CSE2);
       open_dump_file (DFI_cse2, decl);
 
       if (flag_rerun_cse_after_loop)
@@ -3178,38 +3008,36 @@ 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);
-                    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_pop (TV_JUMP);
          
-         TIMEVAR (cse2_time,
-                  {
-                    reg_scan (insns, max_reg_num (), 0);
-                    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);
-                    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);
        }
 
       close_dump_file (DFI_cse2, print_rtl, insns);
+      timevar_pop (TV_CSE2);
 
       if (ggc_p)
        ggc_collect ();
@@ -3217,14 +3045,13 @@ rest_of_compilation (decl)
 
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
+      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);
 
       close_dump_file (DFI_bp, print_rtl, insns);
+      timevar_pop (TV_BRANCH_PROB);
 
       if (ggc_p)
        ggc_collect ();
@@ -3240,31 +3067,29 @@ rest_of_compilation (decl)
   /* Do control and data flow analysis; wrote some of the results to
      the dump file.  */
 
-  TIMEVAR
-    (flow_time,
-     {
-       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-       cleanup_cfg (insns);
-       if (optimize)
-        {
-          struct loops loops;
+  timevar_push (TV_FLOW);
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  cleanup_cfg (insns);
+  if (optimize)
+    {
+      struct loops loops;
 
-          /* 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);
+      /* 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);
 
-          /* Estimate using heuristics if no profiling info is available.  */
-          if (! flag_branch_probabilities)
-            estimate_probability (&loops);
+      /* Estimate using heuristics if no profiling info is available.  */
+      if (! flag_branch_probabilities)
+       estimate_probability (&loops);
 
-          if (rtl_dump_file)
-            flow_loops_dump (&loops, rtl_dump_file, 0);
+      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 ();
-     });
+      flow_loops_free (&loops);
+    }
+  life_analysis (insns, rtl_dump_file, PROP_FINAL);
+  mark_constant_function ();
+  timevar_pop (TV_FLOW);
 
   if (warn_uninitialized || extra_warnings)
     {
@@ -3288,23 +3113,24 @@ rest_of_compilation (decl)
     {
       int rebuild_jump_labels_after_combine = 0;
 
+      timevar_push (TV_COMBINE);
       open_dump_file (DFI_combine, decl);
 
-      TIMEVAR (combine_time, 
-              {
-                rebuild_jump_labels_after_combine
-                  = combine_instructions (insns, max_reg_num ());
-              });
+      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)
        {
-         TIMEVAR (jump_time, rebuild_jump_labels (insns));
+         timevar_push (TV_JUMP);
+         rebuild_jump_labels (insns);
+         timevar_pop (TV_JUMP);
        }
 
       close_dump_file (DFI_combine, print_rtl_with_bb, insns);
+      timevar_pop (TV_COMBINE);
 
       if (ggc_p)
        ggc_collect ();
@@ -3314,12 +3140,13 @@ rest_of_compilation (decl)
      necessary for two-address machines.  */
   if (optimize > 0 && (flag_regmove || flag_expensive_optimizations))
     {
+      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);
 
       close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
+      timevar_pop (TV_REGMOVE);
 
       if (ggc_p)
        ggc_collect ();
@@ -3327,7 +3154,9 @@ rest_of_compilation (decl)
 
   if (optimize && n_basic_blocks)
     {
-      TIMEVAR (gcse_time, optimize_mode_switching (NULL_PTR));
+      timevar_push (TV_GCSE);
+      optimize_mode_switching (NULL_PTR);
+      timevar_pop (TV_GCSE);
     }
 
 #ifdef INSN_SCHEDULING
@@ -3336,14 +3165,16 @@ rest_of_compilation (decl)
      because doing the sched analysis makes some of the dump.  */
   if (optimize > 0 && flag_schedule_insns)
     {
+      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));
+      schedule_insns (rtl_dump_file);
 
       close_dump_file (DFI_sched, print_rtl_with_bb, insns);
+      timevar_pop (TV_SCHED);
 
       if (ggc_p)
        ggc_collect ();
@@ -3355,6 +3186,7 @@ rest_of_compilation (decl)
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
+  timevar_push (TV_LOCAL_ALLOC);
   open_dump_file (DFI_lreg, decl);
 
   /* Allocate pseudo-regs that are used only within 1 basic block. 
@@ -3362,45 +3194,44 @@ rest_of_compilation (decl)
      RUN_JUMP_AFTER_RELOAD records whether or not we need to rerun the
      jump optimizer after register allocation and reloading are finished.  */
 
-  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 ();
-          });
+  /* 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 ();
+
+  timevar_pop (TV_LOCAL_ALLOC);
 
   if (dump_file[DFI_lreg].enabled)
     {
-      TIMEVAR (dump_time,
-              {
-                dump_flow_info (rtl_dump_file);
-                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 (DFI_lreg, print_rtl_with_bb, insns);
+      timevar_pop (TV_DUMP);
     }
 
   if (ggc_p)
     ggc_collect ();
 
+  timevar_push (TV_GLOBAL_ALLOC);
   open_dump_file (DFI_greg, decl);
 
   /* If optimizing, allocate remaining pseudo-regs.  Do the reload
      pass fixing up any insns that are invalid.  */
 
-  TIMEVAR (global_alloc_time,
-          {
-            if (optimize)
-              failure = global_alloc (rtl_dump_file);
-            else
-              {
-                build_insn_chain (insns);
-                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;
@@ -3410,7 +3241,11 @@ 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.  */
@@ -3421,22 +3256,30 @@ rest_of_compilation (decl)
      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);
+
+      rebuild_jump_labels (insns);
+
+      timevar_pop (TV_JUMP);
+    }
 
   if (dump_file[DFI_greg].enabled)
     {
-      TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
+      timevar_push (TV_DUMP);
+
+      dump_global_regs (rtl_dump_file);
+
       close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+      timevar_pop (TV_DUMP);
     }
 
   /* Re-create the death notes which were deleted during reload.  */
+  timevar_push (TV_FLOW2);
   open_dump_file (DFI_flow2, decl);
-  
-  TIMEVAR (flow2_time,
-          {
-            jump_optimize_minimal (insns);
-            find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-          });
+
+  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
@@ -3446,11 +3289,8 @@ rest_of_compilation (decl)
 
   if (optimize)
     {
-      TIMEVAR (flow2_time,
-              {
-                cleanup_cfg (insns);
-                life_analysis (insns, rtl_dump_file, PROP_FINAL);
-              });
+      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
@@ -3459,7 +3299,7 @@ rest_of_compilation (decl)
 #ifndef PUSH_ROUNDING
       if (!ACCUMULATE_OUTGOING_ARGS)
 #endif
-       TIMEVAR (flow2_time, { combine_stack_adjustments (); });
+       combine_stack_adjustments ();
 
       if (ggc_p)
        ggc_collect ();
@@ -3468,29 +3308,34 @@ rest_of_compilation (decl)
   flow2_completed = 1;
 
   close_dump_file (DFI_flow2, print_rtl_with_bb, insns);
+  timevar_pop (TV_FLOW2);
 
 #ifdef HAVE_peephole2
   if (optimize > 0 && flag_peephole2)
     {
-      open_dump_file (DFI_peephole2, decl);
+      timevar_push (TV_PEEPHOLE2);
 
-      TIMEVAR (peephole2_time, peephole2_optimize (rtl_dump_file));
+      open_dump_file (DFI_peephole2, decl);
+      peephole2_optimize (rtl_dump_file);
 
       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)
     {
+      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));
+      schedule_insns (rtl_dump_file);
 
       close_dump_file (DFI_sched2, print_rtl_with_bb, insns);
+      timevar_pop (TV_SCHED2);
 
       if (ggc_p)
        ggc_collect ();
@@ -3504,20 +3349,24 @@ rest_of_compilation (decl)
 
   if (optimize > 0 && flag_reorder_blocks)
     {
+      timevar_push (TV_REORDER_BLOCKS);
       open_dump_file (DFI_bbro, decl);
 
-      TIMEVAR (reorder_blocks_time, reorder_basic_blocks ());
+      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);
 
-      TIMEVAR (rename_registers_time, regrename_optimize ());
+      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. 
@@ -3525,13 +3374,14 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
+      timevar_push (TV_JUMP);
       open_dump_file (DFI_jump2, decl);
 
-      TIMEVAR (jump_time, jump_optimize (insns, JUMP_CROSS_JUMP,
-                                        JUMP_NOOP_MOVES,
-                                        !JUMP_AFTER_REGSCAN));
+      jump_optimize (insns, JUMP_CROSS_JUMP, JUMP_NOOP_MOVES, 
+                    !JUMP_AFTER_REGSCAN);
 
       close_dump_file (DFI_jump2, print_rtl_with_bb, insns);
+      timevar_pop (TV_JUMP);
     }
 
   /* If a machine dependent reorganization is needed, call it.  */
@@ -3552,15 +3402,13 @@ rest_of_compilation (decl)
 #ifdef DELAY_SLOTS
   if (optimize > 0 && flag_delayed_branch)
     {
+      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);
 
       close_dump_file (DFI_dbr, print_rtl_with_bb, insns);
+      timevar_pop (TV_DBR_SCHED);
 
       if (ggc_p)
        ggc_collect ();
@@ -3571,14 +3419,18 @@ rest_of_compilation (decl)
 
      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
+  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);
 
   close_dump_file (DFI_stack, print_rtl_with_bb, insns);
+  timevar_pop (TV_REG_STACK);
 
   if (ggc_p)
     ggc_collect ();
@@ -3592,37 +3444,38 @@ rest_of_compilation (decl)
 
   /* Now turn the rtl into assembler code.  */
 
-  TIMEVAR (final_time,
-          {
-            rtx x;
-            const 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 ();
@@ -3637,20 +3490,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:
 
@@ -3666,24 +3521,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
@@ -3705,10 +3561,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
index 470b209..e5a06ff 100644 (file)
@@ -26,10 +26,6 @@ union tree_node;
 struct rtx_def;
 #endif
 
-extern long gc_time;
-extern long parse_time;
-extern long varconst_time;
-
 extern int read_integral_parameter     PARAMS ((const char *, const char *,
                                                const int));
 extern int count_error                 PARAMS ((int));