Speed up math/test-tgmath2.c

Message ID 1477354555.8523.78.camel@caviumnetworks.com
State New, archived
Headers

Commit Message

Steve Ellcey Oct. 25, 2016, 12:15 a.m. UTC
  The test math/test-tgmath2.c takes a long time to compile with newer
versions of GCC due to variable tracking.  There was some discussion a
while back about using -fno-var-tracking on this test but that was not
considered to be the correct solution, it was thought that breaking up
the test into smaller pieces in order to speed up compilation was a
better solution.  Here is a patch that does that.  It does not break it
up into multiple tests but it breaks up the test function into multiple
functions so that there isn't one single giant function that gives the
GCC variable tracking phase a fit.

On a box where the original version takes 18 minutes to compile using a
pre-release GCC 7.0, the modified version compiles in 3 minutes.  GCC
5.4 took about 2.5 minutes on the same machine.

Original discussion:

https://sourceware.org/ml/libc-alpha/2012-10/msg00430.html


Does this seem like a reasonable way to speed up this test?


2016-10-24  Steve Ellcey  <sellcey@caviumnetworks.com>

        * math/test-tgmath2.c: Split up test function.
  

Comments

Steve Ellcey Nov. 4, 2016, 5:22 p.m. UTC | #1
Ping on this patch to speed up the compilation of math/test-tgmath2.c
when using the latest GCC.

Steve Ellcey
sellcey@caviumnetworks.com


On Mon, 2016-10-24 at 17:15 -0700, Steve Ellcey wrote:
> The test math/test-tgmath2.c takes a long time to compile with newer
> versions of GCC due to variable tracking.  There was some discussion a
> while back about using -fno-var-tracking on this test but that was not
> considered to be the correct solution, it was thought that breaking up
> the test into smaller pieces in order to speed up compilation was a
> better solution.  Here is a patch that does that.  It does not break it
> up into multiple tests but it breaks up the test function into multiple
> functions so that there isn't one single giant function that gives the
> GCC variable tracking phase a fit.
> 
> On a box where the original version takes 18 minutes to compile using a
> pre-release GCC 7.0, the modified version compiles in 3 minutes.  GCC
> 5.4 took about 2.5 minutes on the same machine.
> 
> Original discussion:
> 
> https://sourceware.org/ml/libc-alpha/2012-10/msg00430.html
> 
> 
> Does this seem like a reasonable way to speed up this test?
> 
> 
> 2016-10-24  Steve Ellcey  <sellcey@caviumnetworks.com>
> 
>         * math/test-tgmath2.c: Split up test function.
> 
> 
> diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
> index b376fd6..4d828fe 100644
> --- a/math/test-tgmath2.c
> +++ b/math/test-tgmath2.c
> @@ -89,12 +89,6 @@ enum
>  int count;
>  int counts[Tlast][C_last];
>  
> -int
> -test (const int Vint4, const long long int Vllong4)
> -{
> -  int result = 0;
> -  int quo = 0;
> -
>  #define FAIL(str) \
>    do								
> \
>      {								
> \
> @@ -138,6 +132,11 @@ test (const int Vint4, const long long int
> Vllong4)
>    while (0)
>  #define TEST(expr, type, fn) TEST2(expr, type, type, fn)
>  
> +int
> +test_cos (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    TEST (cos (vfloat1), float, cos);
>    TEST (cos (vdouble1), double, cos);
>    TEST (cos (vldouble1), ldouble, cos);
> @@ -155,6 +154,14 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST (cos (Vcdouble1), cdouble, cos);
>    TEST (cos (Vcldouble1), cldouble, cos);
>  
> +  return result;
> +}
> +
> +int
> +test_fabs (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    TEST (fabs (vfloat1), float, fabs);
>    TEST (fabs (vdouble1), double, fabs);
>    TEST (fabs (vldouble1), ldouble, fabs);
> @@ -180,6 +187,13 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST (fabs (Vcdouble1), double, cabs);
>    TEST (fabs (Vcldouble1), ldouble, cabs);
>  
> +  return result;
> +}
> +
> +int
> +test_conj (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
>    TEST (conj (vfloat1), cfloat, conj);
>    TEST (conj (vdouble1), cdouble, conj);
>    TEST (conj (vldouble1), cldouble, conj);
> @@ -197,6 +211,14 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST (conj (Vcdouble1), cdouble, conj);
>    TEST (conj (Vcldouble1), cldouble, conj);
>  
> +  return result;
> +}
> +
> +int
> +test_expm1 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    TEST (expm1 (vfloat1), float, expm1);
>    TEST (expm1 (vdouble1), double, expm1);
>    TEST (expm1 (vldouble1), ldouble, expm1);
> @@ -208,6 +230,13 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST (expm1 (Vint1), double, expm1);
>    TEST (expm1 (Vllong1), double, expm1);
>  
> +  return result;
> +}
> +
> +int
> +test_lrint (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
>    TEST2 (lrint (vfloat1), float, long int, lrint);
>    TEST2 (lrint (vdouble1), double, long int, lrint);
>    TEST2 (lrint (vldouble1), ldouble, long int, lrint);
> @@ -219,6 +248,14 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST2 (lrint (Vint1), double, long int, lrint);
>    TEST2 (lrint (Vllong1), double, long int, lrint);
>  
> +  return result;
> +}
> +
> +int
> +test_ldexp (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    TEST (ldexp (vfloat1, 6), float, ldexp);
>    TEST (ldexp (vdouble1, 6), double, ldexp);
>    TEST (ldexp (vldouble1, 6), ldouble, ldexp);
> @@ -230,6 +267,9 @@ test (const int Vint4, const long long int
> Vllong4)
>    TEST (ldexp (Vint1, 6), double, ldexp);
>    TEST (ldexp (Vllong1, 6), double, ldexp);
>  
> +  return result;
> +}
> +
>  #define FIRST(x, y) (y, x)
>  #define SECOND(x, y) (x, y)
>  #define NON_LDBL_TEST(fn, argm, arg, type, fnt) \
> @@ -307,25 +347,82 @@ test (const int Vint4, const long long int
> Vllong4)
>    NON_LDBL_CTEST (fn, FIRST, Vcdouble2, cdouble, fnt); \
>    NON_LDBL_CTEST (fn, SECOND, Vcdouble2, cdouble, fnt);
>  
> +int
> +test_atan2 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    BINARY_TEST (atan2, atan2);
>  
> +  return result;
> +}
> +
> +int
> +test_remquo (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +  int quo = 0;
> +
>  #define my_remquo(x, y) remquo (x, y, &quo)
>    BINARY_TEST (my_remquo, remquo);
>  #undef my_remquo
>  
> +  return result;
> +}
> +
> +int
> +test_pow (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>    BINARY_CTEST (pow, pow);
>  
> -  /* Testing all arguments of fma would be just too expensive,
> -     so test just some.  */
> +  return result;
> +}
> +
> +/* Testing all arguments of fma would be just too expensive,
> +   so test just some.  */
> +
> +int
> +test_fma_1 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>  #define my_fma(x, y) fma (x, y, vfloat3)
>    BINARY_TEST (my_fma, fma);
>  #undef my_fma
> +
> +  return result;
> +}
> +
> +int
> +test_fma_2 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>  #define my_fma(x, y) fma (x, vfloat3, y)
>    BINARY_TEST (my_fma, fma);
>  #undef my_fma
> +
> +  return result;
> +}
> +
> +int
> +test_fma_3 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
> +
>  #define my_fma(x, y) fma (Vfloat3, x, y)
>    BINARY_TEST (my_fma, fma);
>  #undef my_fma
> +
> +  return result;
> +}
> +
> +int
> +test_fma_4 (const int Vint4, const long long int Vllong4)
> +{
> +  int result = 0;
>    TEST (fma (vdouble1, Vdouble2, vllong3), double, fma);
>    TEST (fma (vint1, Vint2, vint3), double, fma);
>    TEST (fma (Vldouble1, vldouble2, Vldouble3), ldouble, fma);
> @@ -337,7 +434,19 @@ test (const int Vint4, const long long int
> Vllong4)
>  static int
>  do_test (void)
>  {
> -  return test (vint1, vllong1);
> +  return test_cos (vint1, vllong1)
> +	 + test_fabs (vint1, vllong1)
> +	 + test_conj (vint1, vllong1)
> +	 + test_expm1 (vint1, vllong1)
> +	 + test_lrint (vint1, vllong1)
> +	 + test_ldexp (vint1, vllong1)
> +	 + test_atan2 (vint1, vllong1)
> +	 + test_remquo (vint1, vllong1)
> +	 + test_pow (vint1, vllong1)
> +	 + test_fma_1 (vint1, vllong1)
> +	 + test_fma_2 (vint1, vllong1)
> +	 + test_fma_3 (vint1, vllong1)
> +	 + test_fma_4 (vint1, vllong1);
>  }
>  
>  /* Now generate the three functions.  */
  
Joseph Myers Nov. 4, 2016, 5:25 p.m. UTC | #2
On Fri, 4 Nov 2016, Steve Ellcey wrote:

> > +  return test_cos (vint1, vllong1)
> > +	 + test_fabs (vint1, vllong1)
> > +	 + test_conj (vint1, vllong1)
> > +	 + test_expm1 (vint1, vllong1)
> > +	 + test_lrint (vint1, vllong1)
> > +	 + test_ldexp (vint1, vllong1)
> > +	 + test_atan2 (vint1, vllong1)
> > +	 + test_remquo (vint1, vllong1)
> > +	 + test_pow (vint1, vllong1)
> > +	 + test_fma_1 (vint1, vllong1)
> > +	 + test_fma_2 (vint1, vllong1)
> > +	 + test_fma_3 (vint1, vllong1)
> > +	 + test_fma_4 (vint1, vllong1);

You don't want to add up test results like that; you should OR them 
together instead, to avoid the potential for test results adding up to 77 
and wrongly becoming UNSUPPORTED.  (In this case of course there aren't 
enough tests to get to 77, but the principle applies that you should avoid 
the test return being a count of something.)
  
Steve Ellcey Nov. 4, 2016, 6:06 p.m. UTC | #3
On Fri, 2016-11-04 at 17:25 +0000, Joseph Myers wrote:
> On Fri, 4 Nov 2016, Steve Ellcey wrote:
> 
> > 
> > > 
> > > +  return test_cos (vint1, vllong1)
> > > +	 + test_fabs (vint1, vllong1)
> > > +	 + test_conj (vint1, vllong1)
> > > +	 + test_expm1 (vint1, vllong1)
> > > +	 + test_lrint (vint1, vllong1)
> > > +	 + test_ldexp (vint1, vllong1)
> > > +	 + test_atan2 (vint1, vllong1)
> > > +	 + test_remquo (vint1, vllong1)
> > > +	 + test_pow (vint1, vllong1)
> > > +	 + test_fma_1 (vint1, vllong1)
> > > +	 + test_fma_2 (vint1, vllong1)
> > > +	 + test_fma_3 (vint1, vllong1)
> > > +	 + test_fma_4 (vint1, vllong1);
> You don't want to add up test results like that; you should OR them 
> together instead, to avoid the potential for test results adding up
> to 77 and wrongly becoming UNSUPPORTED.  (In this case of course
> there aren't enough tests to get to 77, but the principle applies
> that you should avoid the test return being a count of something.)

I'll fix that and resubmit.  Is there documentation on what do_test
should return?  I looked at test-skeleton.c but there was nothing in
there about what do_test/TEST_FUNCTION should return for different
results (PASS/FAIL/UNSUPPORTED).  I didn't see anything in the Wiki
about return values from do_test either.

Steve Ellcey
sellcey@caviumnetworks.com
  
Joseph Myers Nov. 4, 2016, 9:21 p.m. UTC | #4
On Fri, 4 Nov 2016, Steve Ellcey wrote:

> I'll fix that and resubmit.  Is there documentation on what do_test
> should return?  I looked at test-skeleton.c but there was nothing in

0, 1 or 77.  (Any other nonzero value is equivalent to 1 as a FAIL, but 
remember that the shell only gets an 8-bit exit status.)
  

Patch

diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
index b376fd6..4d828fe 100644
--- a/math/test-tgmath2.c
+++ b/math/test-tgmath2.c
@@ -89,12 +89,6 @@  enum
 int count;
 int counts[Tlast][C_last];
 
-int
-test (const int Vint4, const long long int Vllong4)
-{
-  int result = 0;
-  int quo = 0;
-
 #define FAIL(str) \
   do								\
     {								\
@@ -138,6 +132,11 @@  test (const int Vint4, const long long int Vllong4)
   while (0)
 #define TEST(expr, type, fn) TEST2(expr, type, type, fn)
 
+int
+test_cos (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   TEST (cos (vfloat1), float, cos);
   TEST (cos (vdouble1), double, cos);
   TEST (cos (vldouble1), ldouble, cos);
@@ -155,6 +154,14 @@  test (const int Vint4, const long long int Vllong4)
   TEST (cos (Vcdouble1), cdouble, cos);
   TEST (cos (Vcldouble1), cldouble, cos);
 
+  return result;
+}
+
+int
+test_fabs (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   TEST (fabs (vfloat1), float, fabs);
   TEST (fabs (vdouble1), double, fabs);
   TEST (fabs (vldouble1), ldouble, fabs);
@@ -180,6 +187,13 @@  test (const int Vint4, const long long int Vllong4)
   TEST (fabs (Vcdouble1), double, cabs);
   TEST (fabs (Vcldouble1), ldouble, cabs);
 
+  return result;
+}
+
+int
+test_conj (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
   TEST (conj (vfloat1), cfloat, conj);
   TEST (conj (vdouble1), cdouble, conj);
   TEST (conj (vldouble1), cldouble, conj);
@@ -197,6 +211,14 @@  test (const int Vint4, const long long int Vllong4)
   TEST (conj (Vcdouble1), cdouble, conj);
   TEST (conj (Vcldouble1), cldouble, conj);
 
+  return result;
+}
+
+int
+test_expm1 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   TEST (expm1 (vfloat1), float, expm1);
   TEST (expm1 (vdouble1), double, expm1);
   TEST (expm1 (vldouble1), ldouble, expm1);
@@ -208,6 +230,13 @@  test (const int Vint4, const long long int Vllong4)
   TEST (expm1 (Vint1), double, expm1);
   TEST (expm1 (Vllong1), double, expm1);
 
+  return result;
+}
+
+int
+test_lrint (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
   TEST2 (lrint (vfloat1), float, long int, lrint);
   TEST2 (lrint (vdouble1), double, long int, lrint);
   TEST2 (lrint (vldouble1), ldouble, long int, lrint);
@@ -219,6 +248,14 @@  test (const int Vint4, const long long int Vllong4)
   TEST2 (lrint (Vint1), double, long int, lrint);
   TEST2 (lrint (Vllong1), double, long int, lrint);
 
+  return result;
+}
+
+int
+test_ldexp (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   TEST (ldexp (vfloat1, 6), float, ldexp);
   TEST (ldexp (vdouble1, 6), double, ldexp);
   TEST (ldexp (vldouble1, 6), ldouble, ldexp);
@@ -230,6 +267,9 @@  test (const int Vint4, const long long int Vllong4)
   TEST (ldexp (Vint1, 6), double, ldexp);
   TEST (ldexp (Vllong1, 6), double, ldexp);
 
+  return result;
+}
+
 #define FIRST(x, y) (y, x)
 #define SECOND(x, y) (x, y)
 #define NON_LDBL_TEST(fn, argm, arg, type, fnt) \
@@ -307,25 +347,82 @@  test (const int Vint4, const long long int Vllong4)
   NON_LDBL_CTEST (fn, FIRST, Vcdouble2, cdouble, fnt); \
   NON_LDBL_CTEST (fn, SECOND, Vcdouble2, cdouble, fnt);
 
+int
+test_atan2 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   BINARY_TEST (atan2, atan2);
 
+  return result;
+}
+
+int
+test_remquo (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+  int quo = 0;
+
 #define my_remquo(x, y) remquo (x, y, &quo)
   BINARY_TEST (my_remquo, remquo);
 #undef my_remquo
 
+  return result;
+}
+
+int
+test_pow (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
   BINARY_CTEST (pow, pow);
 
-  /* Testing all arguments of fma would be just too expensive,
-     so test just some.  */
+  return result;
+}
+
+/* Testing all arguments of fma would be just too expensive,
+   so test just some.  */
+
+int
+test_fma_1 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
 #define my_fma(x, y) fma (x, y, vfloat3)
   BINARY_TEST (my_fma, fma);
 #undef my_fma
+
+  return result;
+}
+
+int
+test_fma_2 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
 #define my_fma(x, y) fma (x, vfloat3, y)
   BINARY_TEST (my_fma, fma);
 #undef my_fma
+
+  return result;
+}
+
+int
+test_fma_3 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
+
 #define my_fma(x, y) fma (Vfloat3, x, y)
   BINARY_TEST (my_fma, fma);
 #undef my_fma
+
+  return result;
+}
+
+int
+test_fma_4 (const int Vint4, const long long int Vllong4)
+{
+  int result = 0;
   TEST (fma (vdouble1, Vdouble2, vllong3), double, fma);
   TEST (fma (vint1, Vint2, vint3), double, fma);
   TEST (fma (Vldouble1, vldouble2, Vldouble3), ldouble, fma);
@@ -337,7 +434,19 @@  test (const int Vint4, const long long int Vllong4)
 static int
 do_test (void)
 {
-  return test (vint1, vllong1);
+  return test_cos (vint1, vllong1)
+	 + test_fabs (vint1, vllong1)
+	 + test_conj (vint1, vllong1)
+	 + test_expm1 (vint1, vllong1)
+	 + test_lrint (vint1, vllong1)
+	 + test_ldexp (vint1, vllong1)
+	 + test_atan2 (vint1, vllong1)
+	 + test_remquo (vint1, vllong1)
+	 + test_pow (vint1, vllong1)
+	 + test_fma_1 (vint1, vllong1)
+	 + test_fma_2 (vint1, vllong1)
+	 + test_fma_3 (vint1, vllong1)
+	 + test_fma_4 (vint1, vllong1);
 }
 
 /* Now generate the three functions.  */