summaryrefslogtreecommitdiff
path: root/gcc/timevar.c
diff options
context:
space:
mode:
authorsamuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-04-28 00:59:40 +0000
committersamuel <samuel@138bc75d-0d04-0410-961f-82ee72b054a4>2000-04-28 00:59:40 +0000
commit74d2af64d63318d222416bac013bb32cbabb725c (patch)
tree721fcd61f706b846a8cfad4302cec9e16abe799a /gcc/timevar.c
parentd31bba8b87a06bf99851897c356d5c1161aebd4f (diff)
downloadgcc-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.c448
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));
+}
+