From 74d2af64d63318d222416bac013bb32cbabb725c Mon Sep 17 00:00:00 2001 From: samuel Date: Fri, 28 Apr 2000 00:59:40 +0000 Subject: [PATCH] hangeLog: * 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 --- gcc/ChangeLog | 38 +++ gcc/Makefile.in | 10 +- gcc/cp/ChangeLog | 9 + gcc/cp/decl2.c | 8 +- gcc/cp/lex.c | 19 +- gcc/ggc-page.c | 13 +- gcc/ggc-simple.c | 14 +- gcc/timevar.c | 448 +++++++++++++++++++++++++ gcc/timevar.def | 73 ++++ gcc/timevar.h | 86 +++++ gcc/toplev.c | 999 ++++++++++++++++++++++++------------------------------- gcc/toplev.h | 4 - 12 files changed, 1101 insertions(+), 620 deletions(-) create mode 100644 gcc/timevar.c create mode 100644 gcc/timevar.def create mode 100644 gcc/timevar.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc52ec7..35d7605 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2000-04-27 Alex Samuel + + * 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 * calls.c (combine_pending_stack_adjustment_and_call): New function. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 50856b8..e3c13f0 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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 \ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f835725..fdad422 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2000-04-27 Alex Samuel + + * 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 * cp-tree.h (TREE_READONLY_DECL_P): Use DECL_P. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index dd89057..99473a8 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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) { diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 7dc6d30..ba32971 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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; -} /* 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; diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 7fc8b2c..924e952 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -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 @@ -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. */ diff --git a/gcc/ggc-simple.c b/gcc/ggc-simple.c index 6d1545c..b7b6a66 100644 --- a/gcc/ggc-simple.c +++ b/gcc/ggc-simple.c @@ -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 index 0000000..61fc92d --- /dev/null +++ b/gcc/timevar.c @@ -0,0 +1,448 @@ +/* Timing variables for measuring compiler performance. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Alex Samuel + + 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 +#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 index 0000000..865d074 --- /dev/null +++ b/gcc/timevar.def @@ -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 + + 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 index 0000000..c7fcfa7 --- /dev/null +++ b/gcc/timevar.h @@ -0,0 +1,86 @@ +/* Timing variables for measuring compiler performance. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Alex Samuel + + 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)); diff --git a/gcc/toplev.c b/gcc/toplev.c index 65f7ee8..e175a40 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -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; -/* 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); } /* 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); } static void diff --git a/gcc/toplev.h b/gcc/toplev.h index 470b209..e5a06ff 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -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)); -- 2.7.4