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

* builtins.c (expand_builtin_interclass_mathfn): Allow for missing
optabs infrastructure.  Provide generic implementation for
FINITE/ISFINITE.
(expand_builtin): Handle FINITE/ISFINITE.
(fold_builtin_classify): Make ISFINITE canonical instead of FINITE.
(fold_builtin_1): Likewise.

* builtins.def (BUILT_IN_ISFINITE): New.

* doc/extend.texi: Document isfinite.

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

From-SVN: r126725

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

index 87ae99a53e500a9f188111166de884d3578e4c00..3bd353f19b52862602b8194769b283e8d6ce1e5a 100644 (file)
@@ -1,3 +1,18 @@
+2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       PR target/30652
+
+       * builtins.c (expand_builtin_interclass_mathfn): Allow for missing
+       optabs infrastructure.  Provide generic implementation for
+       FINITE/ISFINITE.
+       (expand_builtin): Handle FINITE/ISFINITE.
+       (fold_builtin_classify): Make ISFINITE canonical instead of FINITE.
+       (fold_builtin_1): Likewise.
+
+       * builtins.def (BUILT_IN_ISFINITE): New.
+
+       * doc/extend.texi: Document isfinite.
+
 2007-07-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        PR target/30652
index e92e56fbff73c5e2776f921e87a4237fb29b7f56..b96cfb24da1e76b7ef7fc4a0977339c324353c19 100644 (file)
@@ -2211,8 +2211,8 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
 static rtx
 expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
 {
-  optab builtin_optab;
-  enum insn_code icode;
+  optab builtin_optab = 0;
+  enum insn_code icode = CODE_FOR_nothing;
   rtx op0;
   tree fndecl = get_callee_fndecl (exp);
   enum machine_mode mode;
@@ -2230,6 +2230,10 @@ 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_ISFINITE:
+    CASE_FLT_FN (BUILT_IN_FINITE):
+      /* These builtins have no optabs (yet).  */
+      break;
     default:
       gcc_unreachable ();
     }
@@ -2241,7 +2245,8 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
   /* Optab mode depends on the mode of the input argument.  */
   mode = TYPE_MODE (TREE_TYPE (arg));
 
-  icode = builtin_optab->handlers[(int) mode].insn_code;
+  if (builtin_optab)
+    icode = builtin_optab->handlers[(int) mode].insn_code;
  
   /* Before working hard, check whether the instruction is available.  */
   if (icode != CODE_FOR_nothing)
@@ -2295,6 +2300,22 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
                                  build_real (type, r));
        return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
       }
+    CASE_FLT_FN (BUILT_IN_FINITE):
+    case BUILT_IN_ISFINITE:
+      {
+       /* isfinite(x) -> islessequal(fabs(x),DBL_MAX).  */
+       tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+       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 (isle_fn, 2,
+                                 fold_build1 (ABS_EXPR, type, arg),
+                                 build_real (type, r));
+       return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
+      }
     default:
       break;
     }
@@ -6150,6 +6171,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       if (! flag_unsafe_math_optimizations)
        break;
     CASE_FLT_FN (BUILT_IN_ISINF):
+    CASE_FLT_FN (BUILT_IN_FINITE):
+    case BUILT_IN_ISFINITE:
       target = expand_builtin_interclass_mathfn (exp, target, subtarget);
       if (target)
        return target;
@@ -9569,7 +9592,7 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
 
       return NULL_TREE;
 
-    case BUILT_IN_FINITE:
+    case BUILT_IN_ISFINITE:
       if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
          && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
        return omit_one_operand (type, integer_one_node, arg);
@@ -9972,7 +9995,8 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
     case BUILT_IN_FINITED32:
     case BUILT_IN_FINITED64:
     case BUILT_IN_FINITED128:
-      return fold_builtin_classify (fndecl, arg0, BUILT_IN_FINITE);
+    case BUILT_IN_ISFINITE:
+      return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE);
 
     CASE_FLT_FN (BUILT_IN_ISINF):
     case BUILT_IN_ISINFD32:
index 28556179597180c131fbf0d1ae4bc6a941639bfe..8f5f4f24cb830bfb0f43157b81a1800b7c9bda8a 100644 (file)
@@ -654,6 +654,7 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITED128, "finited128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ISFINITE, "isfinite", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
index 9fa09f4c460916403c817b34ed06334b158a0b89..c974d5206cc2d2537d576806aa59057e1e5dd302 100644 (file)
@@ -5437,6 +5437,7 @@ should be called and the @var{flag} argument passed to it.
 @node Other Builtins
 @section Other built-in functions provided by GCC
 @cindex built-in functions
+@findex __builtin_isfinite
 @findex __builtin_isgreater
 @findex __builtin_isgreaterequal
 @findex __builtin_isless
@@ -5965,6 +5966,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.
 
 @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
 
index 1c48519a21216b392e96b4c263686cdceecc1429..64a5d01f4d0ab6abc462d5e15956aa6d1e6df9d0 100644 (file)
@@ -3,6 +3,11 @@
        * gcc.dg/pr28796-1.c: Add more cases.
        * gcc.dg/pr28796-2.c: Likewise.
 
+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 d200b1a682c2689e4e13eb14054b8df8fc213b93..077118a298878441e812410f3a6bf3707fb1d839 100644 (file)
@@ -38,6 +38,20 @@ int main()
   if (__builtin_finitel (ld) != 1)
     link_error ();
 
+  if (__builtin_isinf (f) != 0)
+    link_error ();
+  if (__builtin_isinf (d) != 0)
+    link_error ();
+  if (__builtin_isinf (ld) != 0)
+    link_error ();
+
+  if (__builtin_isfinite (f) != 1)
+    link_error ();
+  if (__builtin_isfinite (d) != 1)
+    link_error ();
+  if (__builtin_isfinite (ld) != 1)
+    link_error ();
+
   if (f != f)
     link_error ();
   if (d != d)
index 254548496465cea8f05fd2704e449d8b1838c9cb..6f929a81fd6cd0de0093be57a50cbb6d1cfeee46 100644 (file)
@@ -43,10 +43,23 @@ foo_1 (float f, double d, long double ld,
   if (__builtin_isinfl (ld) != res_isinf)
     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__))