aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorno-author <no-author@gcc.gnu.org>2000-04-28 13:51:55 +0000
committerno-author <no-author@gcc.gnu.org>2000-04-28 13:51:55 +0000
commit9a430f9174dda082a7906cfae9399ba698515261 (patch)
tree85607f5e7a0716ae5204ddfa12484045c5869bc5
parentd583b266d30c1a2c77471aee0f59e991f959609d (diff)
This commit was manufactured by cvs2svn to create branch
'condexec-branch'. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/condexec-branch@33510 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20000427-1.c9
-rw-r--r--gcc/timevar.c503
-rw-r--r--gcc/timevar.def73
-rw-r--r--gcc/timevar.h86
-rw-r--r--libiberty/aclocal.m471
-rw-r--r--libiberty/strncmp.c28
6 files changed, 770 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/compile/20000427-1.c b/gcc/testsuite/gcc.c-torture/compile/20000427-1.c
new file mode 100644
index 00000000000..dc51419cf01
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20000427-1.c
@@ -0,0 +1,9 @@
+int lwidth;
+int lheight;
+void ConvertFor3dDriver (int requirePO2, int maxAspect)
+{
+ int oldw = lwidth, oldh = lheight;
+
+ lheight = FindNearestPowerOf2 (lheight);
+ while (lwidth/lheight > maxAspect) lheight += lheight;
+}
diff --git a/gcc/timevar.c b/gcc/timevar.c
new file mode 100644
index 00000000000..756365bad5a
--- /dev/null
+++ b/gcc/timevar.c
@@ -0,0 +1,503 @@
+/* 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 "flags.h"
+#include "timevar.h"
+
+/* See timevar.h for an explanation of timing variables. */
+
+/* This macro evaluates to non-zero if timing variables are enabled. */
+#define TIMEVAR_ENABLE (!quiet_flag)
+
+/* 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;
+
+ /* The name of this timing variable. */
+ const char *name;
+
+ /* Non-zero if this timing variable is running as a standalone
+ timer. */
+ unsigned standalone : 1;
+
+ /* Non-zero if this timing variable was ever started or pushed onto
+ the timing stack. */
+ unsigned used : 1;
+};
+
+/* 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;
+
+/* A list of unused (i.e. allocated and subsequently popped)
+ timevar_stack_def instances. */
+static struct timevar_stack_def *unused_stack_instances;
+
+/* 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 (now)
+ struct timevar_time_def *now;
+{
+ now->user = 0;
+ now->sys = 0;
+ now->wall = 0;
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+#ifdef __BEOS__
+ /* Nothing. */
+#else /* not BeOS */
+#if defined (_WIN32) && !defined (__CYGWIN__)
+ if (clock () >= 0)
+ now->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);
+ now->wall = times (&tms) * tick;
+ now->user = tms.tms_utime * tick;
+ now->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
+ now->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
+ now->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
+ now->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);
+ now->user
+ = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
+ now->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;
+ now->wall = times ((void *) &vms_times) * 10000;
+ now->user = vms_times.proc_user_time * 10000;
+ now->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 ()
+{
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* 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;
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
+ /* 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;
+
+ /* See if we have a previously-allocated stack instance. If so,
+ take it off the list. If not, malloc a new one. */
+ if (unused_stack_instances != NULL)
+ {
+ context = unused_stack_instances;
+ unused_stack_instances = unused_stack_instances->next;
+ }
+ else
+ context = (struct timevar_stack_def *)
+ xmalloc (sizeof (struct timevar_stack_def));
+
+ /* Fill it in and put it on the stack. */
+ 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 *popped = stack;
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ 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 (&popped->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;
+
+ /* Take the item off the stack. */
+ stack = stack->next;
+
+ /* Don't delete the stack element; instead, add it to the list of
+ unused elements for later use. */
+ popped->next = unused_stack_instances;
+ unused_stack_instances = popped;
+}
+
+/* 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];
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
+ /* 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;
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ /* 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;
+
+ if (!TIMEVAR_ENABLE)
+ return;
+
+ 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;
+
+ /* Don't print timing variables that were never used. */
+ if (!tv->used)
+ 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 00000000000..865d074df6a
--- /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 <samuel@codesourcery.com>
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* This file contains timing variable definitions, used by timevar.h
+ and timevar.c.
+
+ Syntax:
+
+ DEFTIMEVAR (id, name)
+
+ where ID is the enumeral value used to identify the timing
+ variable, and NAME is a character string describing its purpose. */
+
+/* The total execution time. */
+DEFTIMEVAR (TV_TOTAL , "total time")
+
+/* Time spent garbage-collecting. */
+DEFTIMEVAR (TV_GC , "garbage collection")
+
+/* Time spent generating dump files. */
+DEFTIMEVAR (TV_DUMP , "dump files")
+
+/* Timing in various stages of the compiler. */
+DEFTIMEVAR (TV_PARSE , "parser")
+DEFTIMEVAR (TV_VARCONST , "varconst")
+DEFTIMEVAR (TV_INTEGRATION , "integration")
+DEFTIMEVAR (TV_JUMP , "jump")
+DEFTIMEVAR (TV_CSE , "CSE")
+DEFTIMEVAR (TV_GCSE , "global CSE")
+DEFTIMEVAR (TV_LOOP , "loop analysis")
+DEFTIMEVAR (TV_CSE2 , "CSE 2")
+DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
+DEFTIMEVAR (TV_FLOW , "flow analysis")
+DEFTIMEVAR (TV_COMBINE , "combiner")
+DEFTIMEVAR (TV_REGMOVE , "regmove")
+DEFTIMEVAR (TV_SCHED , "scheduling")
+DEFTIMEVAR (TV_LOCAL_ALLOC , "local alloc")
+DEFTIMEVAR (TV_GLOBAL_ALLOC , "global alloc")
+DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs")
+DEFTIMEVAR (TV_FLOW2 , "flow 2")
+DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2")
+DEFTIMEVAR (TV_SCHED2 , "schedulding 2")
+DEFTIMEVAR (TV_DBR_SCHED , "delay branch sched")
+DEFTIMEVAR (TV_REORDER_BLOCKS , "reorder blocks")
+DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers")
+DEFTIMEVAR (TV_SHORTEN_BRANCH , "shorten branches")
+DEFTIMEVAR (TV_REG_STACK , "reg stack")
+DEFTIMEVAR (TV_TO_SSA , "convert to SSA")
+DEFTIMEVAR (TV_FROM_SSA , "convert from SSA")
+DEFTIMEVAR (TV_FINAL , "final")
+DEFTIMEVAR (TV_SYMOUT , "symout")
+
+/* Everything else in rest_of_compilation not included above. */
+DEFTIMEVAR (TV_REST_OF_COMPILATION , "rest of compilation")
diff --git a/gcc/timevar.h b/gcc/timevar.h
new file mode 100644
index 00000000000..c7fcfa70456
--- /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 <samuel@codesourcery.com>
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Timing variables are used to measure elapsed time in various
+ portions of the compiler. Each measures elapsed user, system, and
+ wall-clock time, as appropriate to and supported by the host
+ system.
+
+ Timing variables are defined using the DEFTIMEVAR macro in
+ timevar.def. Each has an enumeral identifier, used when referring
+ to the timing variable in code, and a character string name.
+
+ Timing variables can be used in two ways:
+
+ - On the timing stack, using timevar_push and timevar_pop.
+ Timing variables may be pushed onto the stack; elapsed time is
+ attributed to the topmost timing variable on the stack. When
+ another variable is pushed on, the previous topmost variable is
+ `paused' until the pushed variable is popped back off.
+
+ - As a standalone timer, using timevar_start and timevar_stop.
+ All time elapsed between the two calls is attributed to the
+ variable.
+*/
+
+/* This structure stores the various varieties of time that can be
+ measured. Times are stored in microseconds. The time may be an
+ absolute time or a time difference; in the former case, the time
+ base is undefined, except that the difference between two times
+ produces a valid time difference. */
+
+struct timevar_time_def
+{
+ /* User time in this process. */
+ long user;
+
+ /* System time (if applicable for this host platform) in this
+ process. */
+ long sys;
+
+ /* Wall clock time. */
+ long wall;
+};
+
+/* An enumeration of timing variable indentifiers. Constructed from
+ the contents of timevar.def. */
+
+#define DEFTIMEVAR(identifier__, name__) \
+ identifier__,
+typedef enum
+{
+#include "timevar.def"
+ TIMEVAR_LAST
+}
+timevar_id_t;
+#undef DEFTIMEVAR
+
+extern void init_timevar PARAMS ((void));
+extern void timevar_push PARAMS ((timevar_id_t));
+extern void timevar_pop PARAMS ((timevar_id_t));
+extern void timevar_start PARAMS ((timevar_id_t));
+extern void timevar_stop PARAMS ((timevar_id_t));
+extern void timevar_get PARAMS ((timevar_id_t, struct timevar_time_def *));
+extern void timevar_print PARAMS ((FILE *));
+
+/* Provided for backward compatibility. */
+extern long get_run_time PARAMS ((void));
+extern void print_time PARAMS ((const char *, long));
diff --git a/libiberty/aclocal.m4 b/libiberty/aclocal.m4
new file mode 100644
index 00000000000..b6a38d60522
--- /dev/null
+++ b/libiberty/aclocal.m4
@@ -0,0 +1,71 @@
+dnl See whether strncmp reads past the end of its string parameters.
+dnl On some versions of SunOS4 at least, strncmp reads a word at a time
+dnl but erroneously reads past the end of strings. This can cause
+dnl a SEGV in some cases.
+AC_DEFUN(libiberty_AC_FUNC_STRNCMP,
+[AC_REQUIRE([AC_FUNC_MMAP])
+AC_CACHE_CHECK([for working strncmp], ac_cv_func_strncmp_works,
+[AC_TRY_RUN([
+/* Test by Jim Wilson and Kaveh Ghazi.
+ Check whether strncmp reads past the end of its string parameters. */
+#include <sys/types.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#else
+#define MAP_ANON MAP_FILE
+#endif
+#endif
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#define MAP_LEN 0x10000
+
+main ()
+{
+#if defined(HAVE_MMAP) || defined(HAVE_MMAP_ANYWHERE)
+ char *p;
+ int dev_zero;
+
+ dev_zero = open ("/dev/zero", O_RDONLY);
+ if (dev_zero < 0)
+ exit (1);
+
+ p = (char *) mmap (0, MAP_LEN, PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, dev_zero, 0);
+ if (p == (char *)-1)
+ exit (2);
+ else
+ {
+ char *string = "__si_type_info";
+ char *q = (char *) p + MAP_LEN - strlen (string) - 2;
+ char *r = (char *) p + 0xe;
+
+ strcpy (q, string);
+ strcpy (r, string);
+ strncmp (r, q, 14);
+ }
+#endif /* HAVE_MMAP || HAVE_MMAP_ANYWHERE */
+ exit (0);
+}
+], ac_cv_func_strncmp_works=yes, ac_cv_func_strncmp_works=no,
+ ac_cv_func_strncmp_works=no)
+rm -f core core.* *.core])
+if test $ac_cv_func_strncmp_works = no ; then
+ LIBOBJS="$LIBOBJS strncmp.o"
+fi
+])
diff --git a/libiberty/strncmp.c b/libiberty/strncmp.c
new file mode 100644
index 00000000000..b3b9de16b10
--- /dev/null
+++ b/libiberty/strncmp.c
@@ -0,0 +1,28 @@
+/* strncmp -- compare two strings, stop after n bytes.
+ This function is in the public domain. */
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+int
+strncmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ register unsigned char u1, u2;
+
+ while (n-- > 0)
+ {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+ return 0;
+}