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:51:13 +0000 (17:51 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Wed, 18 Jul 2007 17:51:13 +0000 (17:51 +0000)
PR target/30652

* builtins.c (expand_builtin_interclass_mathfn): Provide a generic
transformation for builtin ISNORMAL.
(expand_builtin): Handle BUILT_IN_ISNORMAL.
* builtins.def (BUILT_IN_ISNORMAL): New.
* doc/extend.texi: Document isnormal.

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

From-SVN: r126726

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr28796-2.c

index 3bd353f19b52862602b8194769b283e8d6ce1e5a..24b7c2e91e14f5110ded90137521a0cf7e64b1a3 100644 (file)
@@ -1,3 +1,13 @@
+2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       PR target/30652
+
+       * builtins.c (expand_builtin_interclass_mathfn): Provide a generic
+       transformation for builtin ISNORMAL.
+       (expand_builtin): Handle BUILT_IN_ISNORMAL.
+       * builtins.def (BUILT_IN_ISNORMAL): New.
+       * doc/extend.texi: Document isnormal.
+
 2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        PR target/30652
index b96cfb24da1e76b7ef7fc4a0977339c324353c19..d0e5db903bc93f5bcd0aaa762c2ad05ca13dcd27 100644 (file)
@@ -2230,6 +2230,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
       errno_set = true; builtin_optab = ilogb_optab; break;
     CASE_FLT_FN (BUILT_IN_ISINF):
       builtin_optab = isinf_optab; break;
+    case BUILT_IN_ISNORMAL:
     case BUILT_IN_ISFINITE:
     CASE_FLT_FN (BUILT_IN_FINITE):
       /* These builtins have no optabs (yet).  */
@@ -2316,6 +2317,28 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
                                  build_real (type, r));
        return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
       }
+    case BUILT_IN_ISNORMAL:
+      {
+       /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) &
+          islessequal(fabs(x),DBL_MAX).  */
+       tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+       tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL];
+       tree const type = TREE_TYPE (arg);
+       REAL_VALUE_TYPE rmax, rmin;
+       char buf[128];
+
+       get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
+       real_from_string (&rmax, buf);
+       sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1);
+       real_from_string (&rmin, buf);
+       arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg));
+       result = build_call_expr (isle_fn, 2, arg,
+                                 build_real (type, rmax));
+       result = fold_build2 (BIT_AND_EXPR, integer_type_node, result,
+                             build_call_expr (isge_fn, 2, arg,
+                                              build_real (type, rmin)));
+       return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
+      }
     default:
       break;
     }
@@ -6173,6 +6196,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
     CASE_FLT_FN (BUILT_IN_ISINF):
     CASE_FLT_FN (BUILT_IN_FINITE):
     case BUILT_IN_ISFINITE:
+    case BUILT_IN_ISNORMAL:
       target = expand_builtin_interclass_mathfn (exp, target, subtarget);
       if (target)
        return target;
index 8f5f4f24cb830bfb0f43157b81a1800b7c9bda8a..2f23d870bbf8e11bce892e09344beca2468aacec 100644 (file)
@@ -667,6 +667,7 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CO
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ISNORMAL, "isnormal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
index c974d5206cc2d2537d576806aa59057e1e5dd302..5c74b840131db277ec2851f3595f2d9ed9cebbfb 100644 (file)
@@ -5438,6 +5438,7 @@ should be called and the @var{flag} argument passed to it.
 @section Other built-in functions provided by GCC
 @cindex built-in functions
 @findex __builtin_isfinite
+@findex __builtin_isnormal
 @findex __builtin_isgreater
 @findex __builtin_isgreaterequal
 @findex __builtin_isless
@@ -5966,8 +5967,8 @@ the same names as the standard macros ( @code{isgreater},
 @code{islessgreater}, and @code{isunordered}) , with @code{__builtin_}
 prefixed.  We intend for a library implementor to be able to simply
 @code{#define} each standard macro to its built-in equivalent.
-In the same fashion, GCC provides an @code{isfinite} built-in used
-with @code{__builtin_} prefixed.
+In the same fashion, GCC provides @code{isfinite} and @code{isnormal}
+built-ins used with @code{__builtin_} prefixed.
 
 @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
 
index 64a5d01f4d0ab6abc462d5e15956aa6d1e6df9d0..ab18376ccf36fbbd4215ea5797668cd3c53ca59f 100644 (file)
@@ -1,3 +1,7 @@
+2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.dg/pr28796-2.c: Add more cases.
+
 2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/pr28796-1.c: Add more cases.
index 6f929a81fd6cd0de0093be57a50cbb6d1cfeee46..c69a60e0c4afca7ba2441fb75602d5639f313471 100644 (file)
@@ -6,7 +6,8 @@ extern void abort (void);
 
 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_unord, int res_isnan, int res_isinf,
+       int res_isfin, int res_isnorm)
 {
   if (__builtin_isunordered (f, 0) != res_unord)
     abort ();
@@ -43,6 +44,13 @@ foo_1 (float f, double d, long double ld,
   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)
@@ -64,10 +72,12 @@ foo_1 (float f, double d, long double ld,
 
 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_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);
-  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, 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()
@@ -77,19 +87,28 @@ int main()
   long double ld;
   
   f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl("");
-  foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0);
+  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);
+  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);
+  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);
+  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);
+  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;
 }