[PATCH] C++ frontend fix for PR 32668, type-generic builtins

Kaveh R. GHAZI ghazi@caip.rutgers.edu
Fri Jul 20 16:11:00 GMT 2007


This is the C++ frontend bit for fixing PR middle-end/32668, a problem
where type-generic variadic builtins were promoting float arguments to
double.  Although that promotion is normally expected, we don't want it to
happen for the supposedly type-generic functions.

The C++ frontend already had a handy function where so-called "magic"
varargs functions (like __builtin_constant_p()) were handled specially.
This patch merely adds builtins with attribute "type generic" to the
hard-coded list in magic_varargs_p().

There were a bunch of existing C testcases in gcc.dg/pr28796-2.c.  I moved
the interesting bits into a header file and included it from new torture
directory tests for both C and C++.  (The pr28796-2.c testcase tests some
specific fast-math flags, the new torture ones test the default behavior.)

Bootstrapped on sparc-sun-solaris2.10, no regressions and the new
testcases all pass.

Okay for mainline?

		Thanks,
		--Kaveh


2007-07-19  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

gcc/cp:
	PR middle-end/32668
	* call.c (magic_varargs_p): Honor the "type generic" attribute.

gcc/testsuite:
	* g++.dg/torture/type-generic-1.C: New.
	* gcc.dg/pr28796-2.c: Move tests ...
	* gcc.dg/tg-tests.h: ... here.
	* gcc.dg/torture/type-generic-1.c: New.

diff -rup orig/egcc-SVN20070718/gcc/cp/call.c egcc-SVN20070718/gcc/cp/call.c
--- orig/egcc-SVN20070718/gcc/cp/call.c	2007-07-05 23:03:38.000000000 -0400
+++ egcc-SVN20070718/gcc/cp/call.c	2007-07-19 19:42:45.470592571 -0400
@@ -4796,6 +4796,8 @@ magic_varargs_p (tree fn)
 	return true;

       default:;
+	return lookup_attribute ("type generic",
+				 TYPE_ATTRIBUTES (TREE_TYPE (fn))) != 0;
       }

   return false;
diff -rup orig/egcc-SVN20070718/gcc/testsuite/g++.dg/torture/type-generic-1.C egcc-SVN20070718/gcc/testsuite/g++.dg/torture/type-generic-1.C
--- orig/egcc-SVN20070718/gcc/testsuite/g++.dg/torture/type-generic-1.C	2007-07-19 20:12:56.650432813 -0400
+++ egcc-SVN20070718/gcc/testsuite/g++.dg/torture/type-generic-1.C	2007-07-19 20:18:32.677168611 -0400
@@ -0,0 +1,11 @@
+/* Do the type-generic tests.  Unlike pr28796-2.c, we test these
+   without any fast-math flags.  */
+
+/* { dg-do run } */
+
+#include "../../gcc.dg/tg-tests.h"
+
+int main(void)
+{
+  return main_tests ();
+}
diff -rup orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/pr28796-2.c egcc-SVN20070718/gcc/testsuite/gcc.dg/pr28796-2.c
--- orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/pr28796-2.c	2007-07-18 13:53:05.000000000 -0400
+++ egcc-SVN20070718/gcc/testsuite/gcc.dg/pr28796-2.c	2007-07-19 20:01:53.001843747 -0400
@@ -2,113 +2,9 @@
 /* { dg-options "-O2 -funsafe-math-optimizations -fno-finite-math-only" } */
 /* { dg-options "-mieee -O2 -funsafe-math-optimizations -fno-finite-math-only" { target alpha*-*-* } } */

-extern void abort (void);
+#include "tg-tests.h"

-void __attribute__ ((__noinline__))
-foo_1 (float f, double d, long double ld,
-       int res_unord, int res_isnan, int res_isinf,
-       int res_isfin, int res_isnorm)
+int main(void)
 {
-  if (__builtin_isunordered (f, 0) != res_unord)
-    abort ();
-  if (__builtin_isunordered (0, f) != res_unord)
-    abort ();
-  if (__builtin_isunordered (d, 0) != res_unord)
-    abort ();
-  if (__builtin_isunordered (0, d) != res_unord)
-    abort ();
-  if (__builtin_isunordered (ld, 0) != res_unord)
-    abort ();
-  if (__builtin_isunordered (0, ld) != res_unord)
-    abort ();
-
-  if (__builtin_isnan (f) != res_isnan)
-    abort ();
-  if (__builtin_isnan (d) != res_isnan)
-    abort ();
-  if (__builtin_isnan (ld) != res_isnan)
-    abort ();
-  if (__builtin_isnanf (f) != res_isnan)
-    abort ();
-  if (__builtin_isnanl (ld) != res_isnan)
-    abort ();
-
-  if (__builtin_isinf (f) != res_isinf)
-    abort ();
-  if (__builtin_isinf (d) != res_isinf)
-    abort ();
-  if (__builtin_isinf (ld) != res_isinf)
-    abort ();
-  if (__builtin_isinff (f) != res_isinf)
-    abort ();
-  if (__builtin_isinfl (ld) != res_isinf)
-    abort ();
-
-  if (__builtin_isnormal (f) != res_isnorm)
-    abort ();
-  if (__builtin_isnormal (d) != res_isnorm)
-    abort ();
-  if (__builtin_isnormal (ld) != res_isnorm)
-    abort ();
-
-  if (__builtin_isfinite (f) != res_isfin)
-    abort ();
-  if (__builtin_isfinite (d) != res_isfin)
-    abort ();
-  if (__builtin_isfinite (ld) != res_isfin)
-    abort ();
-
-  if (__builtin_finitef (f) != res_isfin)
-    abort ();
-  if (__builtin_finite (f) != res_isfin)
-    abort ();
-  if (__builtin_finite (d) != res_isfin)
-    abort ();
-  if (__builtin_finitel (d) != res_isfin)
-    abort ();
-  if (__builtin_finitel (ld) != res_isfin)
-    abort ();
-}
-
-void __attribute__ ((__noinline__))
-foo (float f, double d, long double ld,
-     int res_unord, int res_isnan, int res_isinf,
-     int res_isfin, int res_isnorm)
-{
-  foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm);
-  /* Try all values negative as well.  */
-  foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm);
-}
-
-int main()
-{
-  float f;
-  double d;
-  long double ld;
-
-  f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl("");
-  foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0, /*isnorm=*/ 0);
-
-  f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl();
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0);
-
-  f = 0; d = 0; ld = 0;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0);
-
-  f = 1; d = 1; ld = 1;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
-
-  f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
-
-  f = __FLT_MIN__/2; d = __DBL_MIN__/2; ld = __LDBL_MIN__/2;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0);
-
-  f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
-
-  f = __FLT_MAX__*2; d = __DBL_MAX__*2; ld = __LDBL_MAX__*2;
-  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0);
-
-  return 0;
+  return main_tests ();
 }
diff -rup orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/tg-tests.h egcc-SVN20070718/gcc/testsuite/gcc.dg/tg-tests.h
--- orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/tg-tests.h	2007-07-19 20:12:49.129533954 -0400
+++ egcc-SVN20070718/gcc/testsuite/gcc.dg/tg-tests.h	2007-07-19 20:26:23.129730580 -0400
@@ -0,0 +1,119 @@
+/* Test various type-generic builtins by calling "main_tests()".  */
+
+void __attribute__ ((__noinline__))
+foo_1 (float f, double d, long double ld,
+       int res_unord, int res_isnan, int res_isinf,
+       int res_isfin, int res_isnorm)
+{
+  if (__builtin_isunordered (f, 0) != res_unord)
+    __builtin_abort ();
+  if (__builtin_isunordered (0, f) != res_unord)
+    __builtin_abort ();
+  if (__builtin_isunordered (d, 0) != res_unord)
+    __builtin_abort ();
+  if (__builtin_isunordered (0, d) != res_unord)
+    __builtin_abort ();
+  if (__builtin_isunordered (ld, 0) != res_unord)
+    __builtin_abort ();
+  if (__builtin_isunordered (0, ld) != res_unord)
+    __builtin_abort ();
+
+  if (__builtin_isnan (f) != res_isnan)
+    __builtin_abort ();
+  if (__builtin_isnan (d) != res_isnan)
+    __builtin_abort ();
+  if (__builtin_isnan (ld) != res_isnan)
+    __builtin_abort ();
+  if (__builtin_isnanf (f) != res_isnan)
+    __builtin_abort ();
+  if (__builtin_isnanl (ld) != res_isnan)
+    __builtin_abort ();
+
+  if (__builtin_isinf (f) != res_isinf)
+    __builtin_abort ();
+  if (__builtin_isinf (d) != res_isinf)
+    __builtin_abort ();
+  if (__builtin_isinf (ld) != res_isinf)
+    __builtin_abort ();
+  if (__builtin_isinff (f) != res_isinf)
+    __builtin_abort ();
+  if (__builtin_isinfl (ld) != res_isinf)
+    __builtin_abort ();
+
+  if (__builtin_isnormal (f) != res_isnorm)
+    __builtin_abort ();
+  if (__builtin_isnormal (d) != res_isnorm)
+    __builtin_abort ();
+  if (__builtin_isnormal (ld) != res_isnorm)
+    __builtin_abort ();
+
+  if (__builtin_isfinite (f) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_isfinite (d) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_isfinite (ld) != res_isfin)
+    __builtin_abort ();
+
+  if (__builtin_finitef (f) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_finite (f) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_finite (d) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_finitel (d) != res_isfin)
+    __builtin_abort ();
+  if (__builtin_finitel (ld) != res_isfin)
+    __builtin_abort ();
+}
+
+void __attribute__ ((__noinline__))
+foo (float f, double d, long double ld,
+     int res_unord, int res_isnan, int res_isinf,
+     int res_isfin, int res_isnorm)
+{
+  foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm);
+  /* Try all the values negated as well.  */
+  foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm);
+}
+
+int __attribute__ ((__noinline__))
+main_tests (void)
+{
+  float f;
+  double d;
+  long double ld;
+
+  /* Test NaN.  */
+  f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl("");
+  foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0, /*isnorm=*/ 0);
+
+  /* Test infinity.  */
+  f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl();
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0);
+
+  /* Test zero.  */
+  f = 0; d = 0; ld = 0;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0);
+
+  /* Test one.  */
+  f = 1; d = 1; ld = 1;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
+
+  /* Test minimum values.  */
+  f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
+
+  /* Test subnormal values.  */
+  f = __FLT_MIN__/2; d = __DBL_MIN__/2; ld = __LDBL_MIN__/2;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0);
+
+  /* Test maximum values.  */
+  f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1);
+
+  /* Test overflow values.  */
+  f = __FLT_MAX__*2; d = __DBL_MAX__*2; ld = __LDBL_MAX__*2;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0);
+
+  return 0;
+}
diff -rup orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/torture/type-generic-1.c egcc-SVN20070718/gcc/testsuite/gcc.dg/torture/type-generic-1.c
--- orig/egcc-SVN20070718/gcc/testsuite/gcc.dg/torture/type-generic-1.c	2007-07-19 20:12:42.954557738 -0400
+++ egcc-SVN20070718/gcc/testsuite/gcc.dg/torture/type-generic-1.c	2007-07-19 20:18:08.668235149 -0400
@@ -0,0 +1,11 @@
+/* Do the type-generic tests.  Unlike pr28796-2.c, we test these
+   without any fast-math flags.  */
+
+/* { dg-do run } */
+
+#include "../tg-tests.h"
+
+int main(void)
+{
+  return main_tests ();
+}



More information about the Gcc-patches mailing list