diff options
author | samuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-04-28 00:59:40 +0000 |
---|---|---|
committer | samuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-04-28 00:59:40 +0000 |
commit | 74d2af64d63318d222416bac013bb32cbabb725c (patch) | |
tree | 721fcd61f706b846a8cfad4302cec9e16abe799a /gcc/timevar.c | |
parent | d31bba8b87a06bf99851897c356d5c1161aebd4f (diff) | |
download | gcc-74d2af64d63318d222416bac013bb32cbabb725c.tar.gz |
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
Diffstat (limited to 'gcc/timevar.c')
-rw-r--r-- | gcc/timevar.c | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/gcc/timevar.c b/gcc/timevar.c new file mode 100644 index 00000000000..61fc92d21ce --- /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 <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)); +} + |