]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/30652 (SSE expansion is missing for isinf() and other fpclassify functions)
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Wed, 18 Jul 2007 17:30:38 +0000 (17:30 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Wed, 18 Jul 2007 17:30:38 +0000 (17:30 +0000)
PR target/30652
PR middle-end/20558

* builtins.c (expand_builtin_interclass_mathfn): Provide a
generic fallback for isinf.
* c-cppbuiltin.c (builtin_define_float_constants): Move FP max
calculation code ...
* real.c (get_max_float): ... to here.
* real.h (get_max_float): New.

testsuite:
* gcc.dg/pr28796-1.c: Add more cases.
* gcc.dg/pr28796-2.c: Likewise.

From-SVN: r126724

gcc/ChangeLog
gcc/builtins.c
gcc/c-cppbuiltin.c
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr28796-1.c
gcc/testsuite/gcc.dg/pr28796-2.c

index 94074ff9a720fcd6968d30392659275d1cbf87b1..87ae99a53e500a9f188111166de884d3578e4c00 100644 (file)
@@ -1,3 +1,15 @@
+2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       PR target/30652
+       PR middle-end/20558
+
+       * builtins.c (expand_builtin_interclass_mathfn): Provide a
+       generic fallback for isinf.
+       * c-cppbuiltin.c (builtin_define_float_constants): Move FP max
+       calculation code ...
+       * real.c (get_max_float): ... to here.
+       * real.h (get_max_float): New.
+
 2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        PR middle-end/32668
index 44cfc0d48b2abc8727553724ca87adeb335bf501..e92e56fbff73c5e2776f921e87a4237fb29b7f56 100644 (file)
@@ -2275,6 +2275,30 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
       return target;
     }
 
+  /* If there is no optab, try generic code.  */
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+      tree result;
+
+    CASE_FLT_FN (BUILT_IN_ISINF):
+      {
+       /* isinf(x) -> isgreater(fabs(x),DBL_MAX).  */
+       tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
+       tree const type = TREE_TYPE (arg);
+       REAL_VALUE_TYPE r;
+       char buf[128];
+
+       get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
+       real_from_string (&r, buf);
+       result = build_call_expr (isgr_fn, 2,
+                                 fold_build1 (ABS_EXPR, type, arg),
+                                 build_real (type, r));
+       return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
+      }
+    default:
+      break;
+    }
+
   target = expand_call (exp, target, target == const0_rtx);
 
   return target;
index 19bb47c14102ae17943dba9a534c202106475cc9..653c5e484426c92c75d281eb5264260fcc43ee4e 100644 (file)
@@ -200,31 +200,8 @@ builtin_define_float_constants (const char *name_prefix,
   /* Since, for the supported formats, B is always a power of 2, we
      construct the following numbers directly as a hexadecimal
      constants.  */
-
-  /* The maximum representable finite floating-point number,
-     (1 - b**-p) * b**emax  */
-  {
-    int i, n;
-    char *p;
-
-    strcpy (buf, "0x0.");
-    n = fmt->p;
-    for (i = 0, p = buf + 4; i + 3 < n; i += 4)
-      *p++ = 'f';
-    if (i < n)
-      *p++ = "08ce"[n - i];
-    sprintf (p, "p%d", fmt->emax);
-    if (fmt->pnan < fmt->p)
-      {
-       /* This is an IBM extended double format made up of two IEEE
-          doubles.  The value of the long double is the sum of the
-          values of the two parts.  The most significant part is
-          required to be the value of the long double rounded to the
-          nearest double.  Rounding means we need a slightly smaller
-          value for LDBL_MAX.  */
-       buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
-      }
-  }
+  get_max_float (fmt, buf, sizeof (buf));
+  
   sprintf (name, "__%s_MAX__", name_prefix);
   builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
 
index b4d617f94d6ed12bfd2f63c231815b6701a820ad..258ecf6635bb2831cd959fa9812668040b5401a7 100644 (file)
@@ -4835,3 +4835,35 @@ real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode)
   real_trunc (&cint, mode, c);
   return real_identical (c, &cint);
 }
+
+/* Write into BUF the maximum representable finite floating-point
+   number, (1 - b**-p) * b**emax for a given FP format FMT as a hex
+   float string.  LEN is the size of BUF, and the buffer must be large
+   enough to contain the resulting string.  */
+
+void
+get_max_float (const struct real_format *fmt, char *buf, size_t len)
+{
+  int i, n;
+  char *p;
+
+  strcpy (buf, "0x0.");
+  n = fmt->p;
+  for (i = 0, p = buf + 4; i + 3 < n; i += 4)
+    *p++ = 'f';
+  if (i < n)
+    *p++ = "08ce"[n - i];
+  sprintf (p, "p%d", fmt->emax);
+  if (fmt->pnan < fmt->p)
+    {
+      /* This is an IBM extended double format made up of two IEEE
+        doubles.  The value of the long double is the sum of the
+        values of the two parts.  The most significant part is
+        required to be the value of the long double rounded to the
+        nearest double.  Rounding means we need a slightly smaller
+        value for LDBL_MAX.  */
+      buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
+    }
+
+  gcc_assert (strlen (buf) < len);
+}
index 09b1e52fb2c50cd3580516d9d4f610d226010691..68ad362849da5fec58f8ae8e0f74899df1d3b0b8 100644 (file)
@@ -438,4 +438,8 @@ extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mp_rnd_t);
 /* Check whether the real constant value given is an integer.  */
 extern bool real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode);
 
+/* Write into BUF the maximum representable finite floating-point
+   number, (1 - b**-p) * b**emax for a given FP format FMT as a hex
+   float string.  BUF must be large enough to contain the result.  */
+extern void get_max_float (const struct real_format *, char *, size_t);
 #endif /* ! GCC_REAL_H */
index e1a8f1ff828b72068e124c5a5bbcf91ff4b0d4cd..1c48519a21216b392e96b4c263686cdceecc1429 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.dg/pr28796-1.c: Add more cases.
+       * gcc.dg/pr28796-2.c: Likewise.
+
 2007-07-17  Janus Weil  <jaydub66@gmail.com>
 
        PR fortran/32535
index a762becdafb3005123288cce08ced365f671d839..d200b1a682c2689e4e13eb14054b8df8fc213b93 100644 (file)
@@ -1,17 +1,48 @@
 /* { dg-do link } */
 /* { dg-options "-ffinite-math-only" } */
 
+extern void link_error(void);
+
 float f;
+double d;
+long double ld;
 
 int main()
 {
   if (__builtin_isunordered (f, f) != 0)
     link_error ();
+  if (__builtin_isunordered (d, d) != 0)
+    link_error ();
+  if (__builtin_isunordered (ld, ld) != 0)
+    link_error ();
+
   if (__builtin_isnan (f) != 0)
     link_error ();
+  if (__builtin_isnan (d) != 0)
+    link_error ();
+  if (__builtin_isnan (ld) != 0)
+    link_error ();
+  if (__builtin_isnanf (f) != 0)
+    link_error ();
+  if (__builtin_isnanl (ld) != 0)
+    link_error ();
+
   if (__builtin_finite (f) != 1)
     link_error ();
+  if (__builtin_finite (d) != 1)
+    link_error ();
+  if (__builtin_finite (ld) != 1)
+    link_error ();
+  if (__builtin_finitef (f) != 1)
+    link_error ();
+  if (__builtin_finitel (ld) != 1)
+    link_error ();
+
   if (f != f)
     link_error ();
+  if (d != d)
+    link_error ();
+  if (ld != ld)
+    link_error ();
   return 0;
 }
index f76bfed35fa4870f0e8b3cd9cc9446c44d174b91..254548496465cea8f05fd2704e449d8b1838c9cb 100644 (file)
@@ -4,19 +4,79 @@
 
 extern void abort (void);
 
-void foo(float f)
+void __attribute__ ((__noinline__))
+foo_1 (float f, double d, long double ld,
+       int res_unord, int res_isnan, int res_isinf, int res_isfin)
 {
-  if (__builtin_isunordered (f, f) != 1)
+  if (__builtin_isunordered (f, 0) != res_unord)
     abort ();
-  if (__builtin_isnan (f) != 1)
+  if (__builtin_isunordered (0, f) != res_unord)
     abort ();
-  if (__builtin_finite (f) != 0)
+  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_finite (f) != res_isfin)
+    abort ();
+  if (__builtin_finite (d) != 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)
+{
+  foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin);
+  foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin);
+}
+
 int main()
 {
-  float f = __builtin_nanf("");
-  foo(f);
+  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);
+
+  f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl();
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0);
+
+  f = 0; d = 0; ld = 0;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
+
+  f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
+
+  f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__;
+  foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
+
   return 0;
 }