about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddhesh@redhat.com>2013-04-30 14:17:57 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2013-04-30 14:17:57 +0530
commitf0ee064b7dcdbde6b28002a63be4b86c86e235b9 (patch)
tree9f8bf86a28d538c1158913afc8f734eb6339b44e
parentd569c6eeb48219993063f956e516704281602f7d (diff)
downloadglibc-f0ee064b7dcdbde6b28002a63be4b86c86e235b9.tar.gz
glibc-f0ee064b7dcdbde6b28002a63be4b86c86e235b9.tar.xz
glibc-f0ee064b7dcdbde6b28002a63be4b86c86e235b9.zip
Allow multiple input domains to be run in the same benchmark program
Some math functions have distinct performance characteristics in
specific domains of inputs, where some inputs return via a fast path
while other inputs require multiple precision calculations, that too
at different precision levels.  The way to implement different domains
was to have a separate source file and benchmark definition, resulting
in separate programs.

This clutters up the benchmark, so this change allows these domains to
be consolidated into the same input file.  To do this, the input file
format is now enhanced to allow comments with a preceding # and
directives with two # at the begining of a line.  A directive that
looks like:

tells the benchmark generation script that what follows is a different
domain of inputs.  The value of the 'name' directive (in this case,
foo) is used in the output.  The two input domains are then executed
sequentially and their results collated separately.  with the above
directive, there would be two lines in the result that look like:

func(): ....
func(foo): ...
-rw-r--r--ChangeLog26
-rw-r--r--benchtests/Makefile45
-rw-r--r--benchtests/atan-inputs6
-rw-r--r--benchtests/bench-modf.c12
-rw-r--r--benchtests/bench-skeleton.c79
-rw-r--r--benchtests/cos-inputs8
-rw-r--r--benchtests/exp-inputs4
-rw-r--r--benchtests/pow-inputs4
-rw-r--r--benchtests/sin-inputs10
-rw-r--r--benchtests/slowatan-inputs3
-rw-r--r--benchtests/slowatan.c19
-rw-r--r--benchtests/slowcos-inputs5
-rw-r--r--benchtests/slowcos.c19
-rw-r--r--benchtests/slowexp-inputs1
-rw-r--r--benchtests/slowexp.c19
-rw-r--r--benchtests/slowpow-inputs1
-rw-r--r--benchtests/slowpow.c19
-rw-r--r--benchtests/slowsin-inputs7
-rw-r--r--benchtests/slowsin.c19
-rw-r--r--benchtests/slowtan-inputs1
-rw-r--r--benchtests/slowtan.c19
-rw-r--r--benchtests/tan-inputs4
-rwxr-xr-xscripts/bench.pl105
23 files changed, 204 insertions, 231 deletions
diff --git a/ChangeLog b/ChangeLog
index 07ec4d05e2..afeadd7525 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,31 @@
 2013-04-30  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
+	* benchtests/Makefile (bench): Remove slow benchmarks.
+	* benchtests/atan-inputs: Add slow benchmark inputs.
+	* benchtests/bench-modf.c (NUM_VARIANTS): Define.
+	(BENCH_FUNC): Accept variant offset.
+	(VARIANT): Define.
+	* benchtests/bench-skeleton.c (main): Run benchmark for each
+	variant.
+	* benchtests/cos-inputs: Add slow benchmark inputs.
+	* benchtests/exp-inputs: Likewise.
+	* benchtests/pow-inputs: Likewise.
+	* benchtests/sin-inputs: Likewise.
+	* benchtests/slowatan-inputs: Remove.
+	* benchtests/slowatan.c: Remove.
+	* benchtests/slowcos-inputs: Remove.
+	* benchtests/slowcos.c: Remove.
+	* benchtests/slowexp-inputs: Remove.
+	* benchtests/slowexp.c: Remove.
+	* benchtests/slowpow-inputs: Remove.
+	* benchtests/slowpow.c: Remove.
+	* benchtests/slowsin-inputs: Remove.
+	* benchtests/slowsin.c: Remove.
+	* benchtests/slowtan-inputs: Remove.
+	* benchtests/slowtan.c: Remove.
+	* benchtests/tan-inputs: Add slow benchmark inputs.
+	* scripts/bench.pl: Parse comments and directives.
+
 	* benchtests/Makefile: Remove *-ITER.  Define BENCH_DURATION
 	in CPPFLAGS.
 	($(objpfx)bench-%.c): Remove *-ITER.
diff --git a/benchtests/Makefile b/benchtests/Makefile
index 9d25d6933a..19e1be6f4b 100644
--- a/benchtests/Makefile
+++ b/benchtests/Makefile
@@ -39,15 +39,12 @@
 #   See pow-inputs for an example.
 
 subdir := benchtests
-bench := exp pow rint sin cos tan atan modf \
-	 slowexp slowpow slowsin slowcos slowtan slowatan
+bench := exp pow rint sin cos tan atan modf
 
-# exp function fast path: sysdeps/ieee754/dbl-64/e_exp.c
 exp-ARGLIST = double
 exp-RET = double
 LDFLAGS-bench-exp = -lm
 
-# pow function fast path: sysdeps/ieee754/dbl-64/e_pow.c
 pow-ARGLIST = double:double
 pow-RET = double
 LDFLAGS-bench-pow = -lm
@@ -56,62 +53,22 @@ rint-ARGLIST = double
 rint-RET = double
 LDFLAGS-bench-rint = -lm
 
-# exp function slowest path: sysdeps/ieee754/dbl-64/mpexp.c
-slowexp-ARGLIST = double
-slowexp-RET = double
-slowexp-INCLUDE = slowexp.c
-LDFLAGS-bench-slowexp = -lm
-
-# sin function fast path: sysdeps/ieee754/dbl-64/s_sin.c
 sin-ARGLIST = double
 sin-RET = double
 LDFLAGS-bench-sin = -lm
 
-# cos function fast path: sysdeps/ieee754/dbl-64/s_sin.c
 cos-ARGLIST = double
 cos-RET = double
 LDFLAGS-bench-cos = -lm
 
-# tan function fast path: sysdeps/ieee754/dbl-64/s_tan.c
 tan-ARGLIST = double
 tan-RET = double
 LDFLAGS-bench-tan = -lm
 
-# atan function fast path: sysdeps/ieee754/dbl-64/s_atan.c
 atan-ARGLIST = double
 atan-RET = double
 LDFLAGS-bench-atan = -lm
 
-# pow function slowest path: sysdeps/ieee754/dbl-64/slowpow.c
-slowpow-ARGLIST = double:double
-slowpow-RET = double
-slowpow-INCLUDE = slowpow.c
-LDFLAGS-bench-slowpow = -lm
-
-# sin function slowest path: sysdeps/ieee754/dbl-64/sincos32.c
-slowsin-ARGLIST = double
-slowsin-RET = double
-slowsin-INCLUDE = slowsin.c
-LDFLAGS-bench-slowsin = -lm
-
-# cos function slowest path: sysdeps/ieee754/dbl-64/sincos32.c
-slowcos-ARGLIST = double
-slowcos-RET = double
-slowcos-INCLUDE = slowcos.c
-LDFLAGS-bench-slowcos = -lm
-
-# tan function slowest path: sysdeps/ieee754/dbl-64/mptan.c
-slowtan-ARGLIST = double
-slowtan-RET = double
-slowtan-INCLUDE = slowtan.c
-LDFLAGS-bench-slowtan = -lm
-
-# atan function slowest path: sysdeps/ieee754/dbl-64/mpatan.c
-slowatan-ARGLIST = double
-slowatan-RET = double
-slowatan-INCLUDE = slowatan.c
-LDFLAGS-bench-slowatan = -lm
-
 
 
 # Rules to build and execute the benchmarks.  Do not put any benchmark
diff --git a/benchtests/atan-inputs b/benchtests/atan-inputs
index c685db3b97..4a2cf3aca3 100644
--- a/benchtests/atan-inputs
+++ b/benchtests/atan-inputs
@@ -1,3 +1,9 @@
 0x1.000000c5cba86p0
 0x1.000001883003ap0
 0x1.00000dfb2b674p0
+# atan slowest path at 768 bits
+# Implemented in sysdeps/ieee754/dbl-64/mpatan.c
+## name: 768bits
+0x1.000000c5cba87p0
+0x1.000001883003bp0
+0x1.00000dfb2b675p0
diff --git a/benchtests/bench-modf.c b/benchtests/bench-modf.c
index 90a5255291..7fae7dc6ac 100644
--- a/benchtests/bench-modf.c
+++ b/benchtests/bench-modf.c
@@ -17,7 +17,7 @@
 
 extern double modf (double, double *);
 
-#define CALL_BENCH_FUNC(j, i) modf ( in[j].arg0, &i);
+#define CALL_BENCH_FUNC(j, i) modf (in[j].arg0, &i);
 
 struct args
 {
@@ -28,11 +28,17 @@ struct args
   { -42.42 }
 };
 
-#define NUM_SAMPLES (sizeof (in) / sizeof (struct args))
+#define NUM_VARIANTS 1
+#define NUM_SAMPLES(v) (sizeof (in) / sizeof (struct args))
 
 static volatile double ret = 0.0;
-#define BENCH_FUNC(j) ({double iptr; ret =  CALL_BENCH_FUNC (j, iptr);})
+#define BENCH_FUNC(v, j) \
+({									      \
+  double iptr;								      \
+  ret =  CALL_BENCH_FUNC (j, iptr);					      \
+})
 
 #define FUNCNAME "modf"
+#define VARIANT(v) FUNCNAME "()"
 
 #include "bench-skeleton.c"
diff --git a/benchtests/bench-skeleton.c b/benchtests/bench-skeleton.c
index bbd151b0ec..7359184ba8 100644
--- a/benchtests/bench-skeleton.c
+++ b/benchtests/bench-skeleton.c
@@ -25,12 +25,11 @@
 #define TIMESPEC_AFTER(a, b) \
   (((a).tv_sec == (b).tv_sec) ?						      \
      ((a).tv_nsec > (b).tv_nsec) :					      \
-        ((a).tv_sec > (b).tv_sec))
+	((a).tv_sec > (b).tv_sec))
 int
 main (int argc, char **argv)
 {
   unsigned long i, k;
-  uint64_t total = 0, max = 0, min = 0x7fffffffffffffff;
   struct timespec start, end, runtime;
 
   memset (&runtime, 0, sizeof (runtime));
@@ -45,53 +44,57 @@ main (int argc, char **argv)
      but it's better than having nothing at all.  */
   unsigned long iters = 1000 * start.tv_nsec;
 
-  /* Run for approxmately DURATION seconds.  */
-  clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
-  runtime.tv_sec += DURATION;
-
-  double d_total_i = 0;
-  while (1)
+  for (int v = 0; v < NUM_VARIANTS; v++)
     {
-      for (i = 0; i < NUM_SAMPLES; i++)
-	{
-	  clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start);
-	  for (k = 0; k < iters; k++)
-	    BENCH_FUNC(i);
-	  clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end);
+      /* Run for approximately DURATION seconds.  */
+      clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
+      runtime.tv_sec += DURATION;
 
-	  uint64_t cur = (end.tv_nsec - start.tv_nsec
-			 + ((end.tv_sec - start.tv_sec)
-			    * (uint64_t) 1000000000));
+      double d_total_i = 0;
+      uint64_t total = 0, max = 0, min = 0x7fffffffffffffff;
+      while (1)
+	{
+	  for (i = 0; i < NUM_SAMPLES (v); i++)
+	    {
+	      clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &start);
+	      for (k = 0; k < iters; k++)
+		BENCH_FUNC (v, i);
+	      clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &end);
 
-	  if (cur > max)
-	    max = cur;
+	      uint64_t cur = (end.tv_nsec - start.tv_nsec
+			      + ((end.tv_sec - start.tv_sec)
+				 * (uint64_t) 1000000000));
 
-	  if (cur < min)
-	    min = cur;
+	      if (cur > max)
+		max = cur;
 
-	  total += cur;
+	      if (cur < min)
+		min = cur;
 
-	  d_total_i += iters;
-	}
+	      total += cur;
 
-      struct timespec curtime;
+	      d_total_i += iters;
+	    }
+	  struct timespec curtime;
 
-      memset (&curtime, 0, sizeof (curtime));
-      clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
-      if (TIMESPEC_AFTER (curtime, runtime))
-	goto done;
-    }
+	  memset (&curtime, 0, sizeof (curtime));
+	  clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
+	  if (TIMESPEC_AFTER (curtime, runtime))
+	    goto done;
+	}
 
-  double d_total_s;
-  double d_iters;
+      double d_total_s;
+      double d_iters;
 
- done:
-  d_total_s = total * 1e-9;
-  d_iters = iters;
+    done:
+      d_total_s = total * 1e-9;
+      d_iters = iters;
 
-  printf (FUNCNAME ": ITERS:%g: TOTAL:%gs, MAX:%gns, MIN:%gns, %g iter/s\n",
-	  d_total_i, d_total_s, max / d_iters, min / d_iters,
-	  d_total_i / d_total_s);
+      printf ("%s: ITERS:%g: TOTAL:%gs, MAX:%gns, MIN:%gns, %g iter/s\n",
+	      VARIANT (v),
+	      d_total_i, d_total_s, max / d_iters, min / d_iters,
+	      d_total_i / d_total_s);
+    }
 
   return 0;
 }
diff --git a/benchtests/cos-inputs b/benchtests/cos-inputs
index 98f4122aa1..82a40609cd 100644
--- a/benchtests/cos-inputs
+++ b/benchtests/cos-inputs
@@ -3,3 +3,11 @@
 0x1.00000162a932ap0
 0x1.000002d452a11p0
 0x1.000005bc7d86cp0
+# cos slow path at 768 bits
+# Implemented in sysdeps/ieee754/dbl-64/sincos32.c
+## name: 768bits
+0x1.000000cf4a2a2p0
+0x1.0000010b239a9p0
+0x1.00000162a932bp0
+0x1.000002d452a10p0
+0x1.000005bc7d86dp0
diff --git a/benchtests/exp-inputs b/benchtests/exp-inputs
index d81cc0710e..e9d33a3d1c 100644
--- a/benchtests/exp-inputs
+++ b/benchtests/exp-inputs
@@ -1 +1,5 @@
 42
+# Slowest path with computation in 768 bit precision.
+# Implemented in: sysdeps/ieee754/dbl-64/mpexp.c
+## name: 768bits
+708.00096423260981737257679924368858
diff --git a/benchtests/pow-inputs b/benchtests/pow-inputs
index 2f7cc03b52..dad65059aa 100644
--- a/benchtests/pow-inputs
+++ b/benchtests/pow-inputs
@@ -1 +1,5 @@
 42.0, 42.0
+# pow slowest path at 768 bits
+# Implemented in sysdeps/ieee754/dbl-64/slowpow.c
+## name: 768bits
+1.0000000000000020, 1.5
diff --git a/benchtests/sin-inputs b/benchtests/sin-inputs
index 620cea8d98..08192d8f09 100644
--- a/benchtests/sin-inputs
+++ b/benchtests/sin-inputs
@@ -5,3 +5,13 @@
 4.0
 4.7
 5.9
+# sin slowest path at 768 bits
+# Implemented in sysdeps/ieee754/dbl-64/sincos32.c
+## name: 768bits
+0.93340582292648832662962377071381
+2.3328432680770916363144351635128
+3.7439477503636453548097051680088
+3.9225160069792437411706487182528
+4.0711651639931289992091478779912
+4.7858438478542097982426639646292
+5.9840767662578002727968851104379
diff --git a/benchtests/slowatan-inputs b/benchtests/slowatan-inputs
deleted file mode 100644
index e557a3cb26..0000000000
--- a/benchtests/slowatan-inputs
+++ /dev/null
@@ -1,3 +0,0 @@
-0x1.000000c5cba87p0
-0x1.000001883003bp0
-0x1.00000dfb2b675p0
diff --git a/benchtests/slowatan.c b/benchtests/slowatan.c
deleted file mode 100644
index 9a11d30bd4..0000000000
--- a/benchtests/slowatan.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowatan.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowatan atan
diff --git a/benchtests/slowcos-inputs b/benchtests/slowcos-inputs
deleted file mode 100644
index b7eb235367..0000000000
--- a/benchtests/slowcos-inputs
+++ /dev/null
@@ -1,5 +0,0 @@
-0x1.000000cf4a2a2p0
-0x1.0000010b239a9p0
-0x1.00000162a932bp0
-0x1.000002d452a10p0
-0x1.000005bc7d86dp0
diff --git a/benchtests/slowcos.c b/benchtests/slowcos.c
deleted file mode 100644
index 9f56234afa..0000000000
--- a/benchtests/slowcos.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowcos.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowcos cos
diff --git a/benchtests/slowexp-inputs b/benchtests/slowexp-inputs
deleted file mode 100644
index a2086baa86..0000000000
--- a/benchtests/slowexp-inputs
+++ /dev/null
@@ -1 +0,0 @@
-708.00096423260981737257679924368858
diff --git a/benchtests/slowexp.c b/benchtests/slowexp.c
deleted file mode 100644
index 92ac5e9b4c..0000000000
--- a/benchtests/slowexp.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowexp.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowexp exp
diff --git a/benchtests/slowpow-inputs b/benchtests/slowpow-inputs
deleted file mode 100644
index dbb1270b75..0000000000
--- a/benchtests/slowpow-inputs
+++ /dev/null
@@ -1 +0,0 @@
-1.0000000000000020, 1.5
diff --git a/benchtests/slowpow.c b/benchtests/slowpow.c
deleted file mode 100644
index 08f436d2a4..0000000000
--- a/benchtests/slowpow.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowpow.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowpow pow
diff --git a/benchtests/slowsin-inputs b/benchtests/slowsin-inputs
deleted file mode 100644
index 39daf80b3b..0000000000
--- a/benchtests/slowsin-inputs
+++ /dev/null
@@ -1,7 +0,0 @@
-0.93340582292648832662962377071381
-2.3328432680770916363144351635128
-3.7439477503636453548097051680088
-3.9225160069792437411706487182528
-4.0711651639931289992091478779912
-4.7858438478542097982426639646292
-5.9840767662578002727968851104379
diff --git a/benchtests/slowsin.c b/benchtests/slowsin.c
deleted file mode 100644
index b6809bdd7b..0000000000
--- a/benchtests/slowsin.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowsin.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowsin sin
diff --git a/benchtests/slowtan-inputs b/benchtests/slowtan-inputs
deleted file mode 100644
index 74a7eab3f9..0000000000
--- a/benchtests/slowtan-inputs
+++ /dev/null
@@ -1 +0,0 @@
-0x1.dffffffffff1fp-22
diff --git a/benchtests/slowtan.c b/benchtests/slowtan.c
deleted file mode 100644
index 583f16f0d1..0000000000
--- a/benchtests/slowtan.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Define slowtan.
-   Copyright (C) 2013 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#define slowtan tan
diff --git a/benchtests/tan-inputs b/benchtests/tan-inputs
index 4369d75776..629414fc73 100644
--- a/benchtests/tan-inputs
+++ b/benchtests/tan-inputs
@@ -1 +1,5 @@
 0x1.dffffffffff1ep-22
+# tan slowest path at 768 bits
+# Implemented in sysdeps/ieee754/dbl-64/mptan.c
+## name: 768bits
+0x1.dffffffffff1fp-22
diff --git a/scripts/bench.pl b/scripts/bench.pl
index 5856cfa397..dcc5ead727 100755
--- a/scripts/bench.pl
+++ b/scripts/bench.pl
@@ -42,15 +42,28 @@ if (@ARGV == 3) {
 
 my $decl = "extern $ret $func (";
 
+# Function has no arguments.
 if (@args == 0 || $args[0] eq "void") {
   print "$decl void);\n";
-  print "#define CALL_BENCH_FUNC(j) $func();\n";
-  print "#define NUM_SAMPLES (1)\n";
+  print "#define CALL_BENCH_FUNC(i,j) $func();\n";
+  print "#define NUM_VARIANTS (1)\n";
+  print "#define NUM_SAMPLES(v) (1)\n";
+  print "#define VARIANT(v) FUNCNAME \"()\"\n"
 }
+# The function has arguments, so parse them and populate the inputs.
 else {
   my $num = 0;
-  my $bench_func = "#define CALL_BENCH_FUNC(j) $func (";
-  my $struct = "struct args {";
+  my $bench_func = "#define CALL_BENCH_FUNC(v, i) $func (";
+
+  my $struct =
+    "struct _variants
+    {
+      const char *name;
+      int count;
+      struct args *in;
+    };\n";
+
+  my $arg_struct = "struct args {";
 
   foreach $arg (@args) {
     if ($num > 0) {
@@ -58,24 +71,87 @@ else {
       $decl = "$decl,";
     }
 
-    $struct = "$struct $arg arg$num;";
-    $bench_func = "$bench_func in[j].arg$num";
+    $arg_struct = "$arg_struct $arg arg$num;";
+    $bench_func = "$bench_func variants[v].in[i].arg$num";
     $decl = "$decl $arg";
     $num = $num + 1;
   }
 
-  print "$decl);\n";
-  print "$bench_func);\n";
-  print "$struct } in[] = {";
+  $arg_struct = $arg_struct . "};\n";
+  $decl = $decl . ");\n";
+  $bench_func = $bench_func . ");\n";
+
+  # We create a hash of inputs for each variant of the test.
+  my $variant = "";
+  my @curvals;
+  my %vals;
 
   open INPUTS, "<$func-inputs" or die $!;
 
-  while (<INPUTS>) {
+  LINE:while (<INPUTS>) {
     chomp;
-    print "{$_},\n";
+
+    # New variant.
+    if (/^## (\w+): (\w+)/) {
+      #We only identify Name for now.
+      if ($1 ne "name") {
+        next LINE;
+      }
+
+      # Save values in the last variant.
+      my @copy = @curvals;
+      $vals{$variant} = \@copy;
+
+      # Prepare for the next.
+      $variant=$2;
+      undef @curvals;
+      next LINE;
+    }
+
+    # Skip over comments.
+    if (/^#/) {
+      next LINE;
+    }
+    push (@curvals, $_);
   }
-  print "};\n";
-  print "#define NUM_SAMPLES (sizeof (in) / sizeof (struct args))\n"
+
+  $vals{$variant} = \@curvals;
+
+  # Print the definitions and macros.
+  print $decl;
+  print $bench_func;
+  print $arg_struct;
+  print $struct;
+
+  my $c = 0;
+  my $key;
+
+  # Print the input arrays.
+  foreach $key (keys %vals) {
+    my @arr = @{$vals{$key}};
+
+    print "struct args in" . $c . "[" . @arr . "] = {\n";
+    foreach (@arr) {
+      print "{$_},\n";
+    }
+    print "};\n\n";
+    $c += 1;
+  }
+
+  # The variants.  Each variant then points to the appropriate input array we
+  # defined above.
+  print "struct _variants variants[" . (keys %vals) . "] = {\n";
+  $c = 0;
+  foreach $key (keys %vals) {
+    print "{\"$func($key)\", " . @{$vals{$key}} . ", in$c},\n";
+    $c += 1;
+  }
+  print "};\n\n";
+
+  # Finally, print the last set of macros.
+  print "#define NUM_VARIANTS $c\n";
+  print "#define NUM_SAMPLES(i) (variants[i].count)\n";
+  print "#define VARIANT(i) (variants[i].name)\n";
 }
 
 # In some cases not storing a return value seems to result in the function call
@@ -85,7 +161,8 @@ if ($ret ne "void") {
   $getret = "ret = ";
 }
 
-print "#define BENCH_FUNC(j) ({$getret CALL_BENCH_FUNC (j);})\n";
+# And we're done.
+print "#define BENCH_FUNC(i, j) ({$getret CALL_BENCH_FUNC (i, j);})\n";
 
 print "#define FUNCNAME \"$func\"\n";
 print "#include \"bench-skeleton.c\"\n";