builtins.c (fold_builtin_classify): New.
authorPaolo Bonzini <bonzini@gnu.org>
Thu, 1 Jul 2004 08:02:34 +0000 (08:02 +0000)
committerPaolo Bonzini <bonzini@gcc.gnu.org>
Thu, 1 Jul 2004 08:02:34 +0000 (08:02 +0000)
gcc/ChangeLog:
2004-07-01  Paolo Bonzini  <bonzini@gnu.org>

* builtins.c (fold_builtin_classify): New.
(fold_builtin_unordered_cmp): Fix commentary.
(fold_builtin): Use it.
* builtins.def: Define builtins for isnan,
isnanf, isnanl, finite, finitef, finitel,
isinf, isinff, isinfl.

gcc/testsuite/ChangeLog:
2004-07-01  Paolo Bonzini  <bonzini@gnu.org>

* gcc.dg/builtins-43.c: New.
* gcc.dg/builtins-44.c: New.
* gcc.dg/builtins-45.c: New.

From-SVN: r83960

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-43.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-44.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-45.c [new file with mode: 0644]

index 5b78d22c7659b0d19be6d3181996d3ff77064fc4..3e42262f5a392c565295af0012cb8dd2fb1aa88b 100644 (file)
@@ -1,3 +1,12 @@
+2004-07-01  Paolo Bonzini  <bonzini@gnu.org>
+
+       * builtins.c (fold_builtin_classify): New.
+       (fold_builtin_unordered_cmp): Fix commentary.
+       (fold_builtin): Use it.
+       * builtins.def: Define builtins for isnan,
+       isnanf, isnanl, finite, finitef, finitel,
+       isinf, isinff, isinfl.
+
 2004-07-01  Richard Henderson  <rth@redhat.com>
 
        * function.h (struct function): Remove dont_emit_block_notes.
index 74c1f98c69f729afbe9871ee3a243e3da6410faf..3155c61186753a56a78f81c6396c30b1bec6f8fb 100644 (file)
@@ -7611,12 +7611,98 @@ fold_builtin_abs (tree arglist, tree type)
   return fold (build1 (ABS_EXPR, type, arg));
 }
 
+/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
+   EXP is the CALL_EXPR for the call.  */
+
+static tree
+fold_builtin_classify (tree exp, int builtin_index)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (TREE_TYPE (fndecl));
+  tree arg;
+  REAL_VALUE_TYPE r;
+
+  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      /* Check that we have exactly one argument.  */
+      if (arglist == 0)
+       {
+         error ("too few arguments to function `%s'",
+                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+         return error_mark_node;
+       }
+      else if (TREE_CHAIN (arglist) != 0)
+       {
+         error ("too many arguments to function `%s'",
+                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+         return error_mark_node;
+       }
+      else
+       {
+         error ("non-floating-point argument to function `%s'",
+                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+         return error_mark_node;
+       }
+    }
+
+  arg = TREE_VALUE (arglist);
+  switch (builtin_index)
+    {
+    case BUILT_IN_ISINF:
+      if (!MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+        return omit_one_operand (type, integer_zero_node, arg);
+
+      if (TREE_CODE (arg) == REAL_CST)
+       {
+         r = TREE_REAL_CST (arg);
+         if (real_isinf (&r))
+           return real_compare (GT_EXPR, &r, &dconst0)
+                  ? integer_one_node : integer_minus_one_node;
+         else
+           return integer_zero_node;
+       }
+
+      return NULL_TREE;
+
+    case BUILT_IN_ISFINITE:
+      if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg)))
+          && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
+        return omit_one_operand (type, integer_zero_node, arg);
+
+      if (TREE_CODE (arg) == REAL_CST)
+       {
+         r = TREE_REAL_CST (arg);
+         return real_isinf (&r) || real_isnan (&r)
+                ? integer_zero_node : integer_one_node;
+       }
+
+      return NULL_TREE;
+
+    case BUILT_IN_ISNAN:
+      if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
+        return omit_one_operand (type, integer_zero_node, arg);
+
+      if (TREE_CODE (arg) == REAL_CST)
+       {
+         r = TREE_REAL_CST (arg);
+         return real_isnan (&r) ? integer_one_node : integer_zero_node;
+       }
+
+      arg = builtin_save_expr (arg);
+      return fold (build2 (UNORDERED_EXPR, type, arg, arg));
+
+    default:
+      abort ();
+    }
+}
+
 /* Fold a call to an unordered comparison function such as
-   __builtin_isgreater().  ARGLIST is the funtion's argument list
-   and TYPE is the functions return type.  UNORDERED_CODE and
-   ORDERED_CODE are comparison codes that give the opposite of
-   the desired result.  UNORDERED_CODE is used for modes that can
-   hold NaNs and ORDERED_CODE is used for the rest.  */
+   __builtin_isgreater().  EXP is the CALL_EXPR for the call.
+   UNORDERED_CODE and ORDERED_CODE are comparison codes that give
+   the opposite of the desired result.  UNORDERED_CODE is used
+   for modes that can hold NaNs and ORDERED_CODE is used for
+   the rest.  */
 
 static tree
 fold_builtin_unordered_cmp (tree exp,
@@ -8247,6 +8333,21 @@ fold_builtin_1 (tree exp)
     case BUILT_IN_COPYSIGNL:
       return fold_builtin_copysign (arglist, type);
 
+    case BUILT_IN_FINITE:
+    case BUILT_IN_FINITEF:
+    case BUILT_IN_FINITEL:
+      return fold_builtin_classify (exp, BUILT_IN_FINITE);
+
+    case BUILT_IN_ISINF:
+    case BUILT_IN_ISINFF:
+    case BUILT_IN_ISINFL:
+      return fold_builtin_classify (exp, BUILT_IN_ISINF);
+
+    case BUILT_IN_ISNAN:
+    case BUILT_IN_ISNANF:
+    case BUILT_IN_ISNANL:
+      return fold_builtin_classify (exp, BUILT_IN_ISNAN);
+
     case BUILT_IN_ISGREATER:
       return fold_builtin_unordered_cmp (exp, UNLE_EXPR, LE_EXPR);
     case BUILT_IN_ISGREATEREQUAL:
index 52b29660c7515dbecf27103608a5ec8d909f117b..bd8a6308a3cb3af4ab7b9c227f7254ffbc023dfe 100644 (file)
@@ -571,6 +571,15 @@ DEF_GCC_BUILTIN        (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
 DEF_C99_BUILTIN        (BUILT_IN_IMAXABS, "imaxabs", BT_FN_INTMAX_INTMAX, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INIT_DWARF_REG_SIZES, "init_dwarf_reg_size_table", BT_FN_VOID_PTR, ATTR_NULL)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITE, "finite", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITEF, "finitef", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+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)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
index 926c9cd8b7f9989b2c6c9f1053b1182fb7576cd1..77ab7222a3bdc50406ed42d257c7b0249ec8c20c 100644 (file)
@@ -1,3 +1,9 @@
+2004-07-01  Paolo Bonzini  <bonzini@gnu.org>
+
+       * gcc.dg/builtins-43.c: New.
+       * gcc.dg/builtins-44.c: New.
+       * gcc.dg/builtins-45.c: New.
+
 2004-06-26  Geoffrey Keating  <geoffk@apple.com>
            Andreas Tobler  <a.tobler@schweiz.ch>
 
diff --git a/gcc/testsuite/gcc.dg/builtins-43.c b/gcc/testsuite/gcc.dg/builtins-43.c
new file mode 100644 (file)
index 0000000..d174f7a
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-trapping-math -fdump-tree-generic -fdump-tree-optimized" } */
+  
+extern void f(int);
+extern void link_error ();
+
+extern float x;
+extern double y;
+extern long double z;
+
+int
+main ()
+{
+  double nan = __builtin_nan ("");
+  float nanf = __builtin_nanf ("");
+  long double nanl = __builtin_nanl ("");
+
+  if (!__builtin_isnan (nan))
+    link_error ();
+  if (!__builtin_isnan (nanf))
+    link_error ();
+  if (!__builtin_isnanf (nanf))
+    link_error ();
+  if (!__builtin_isnan (nanl))
+    link_error ();
+  if (!__builtin_isnanl (nanl))
+    link_error ();
+
+  if (__builtin_isnan (4.0))
+    link_error ();
+  if (__builtin_isnan (4.0))
+    link_error ();
+  if (__builtin_isnanf (4.0))
+    link_error ();
+  if (__builtin_isnan (4.0))
+    link_error ();
+  if (__builtin_isnanl (4.0))
+    link_error ();
+
+  f (__builtin_isnan (x));
+  f (__builtin_isnan (y));
+  f (__builtin_isnanf (y));
+  f (__builtin_isnan (z));
+  f (__builtin_isnanl (z));
+}
+
+
+/* Check that all instances of __builtin_isnan were folded.  */
+/* { dg-final { scan-tree-dump-times "isnan" 0 "generic" } } */
+
+/* Check that all instances of link_error were subject to DCE.  */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/builtins-44.c b/gcc/testsuite/gcc.dg/builtins-44.c
new file mode 100644 (file)
index 0000000..2f5a3e1
--- /dev/null
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-trapping-math -fdump-tree-optimized" } */
+  
+extern void f(int);
+extern void link_error ();
+
+extern float x;
+extern double y;
+extern long double z;
+
+int
+main ()
+{
+  double pinf = __builtin_inf ();
+  float pinff = __builtin_inff ();
+  long double pinfl = __builtin_infl ();
+
+  if (__builtin_isinf (pinf) != 1)
+    link_error ();
+  if (__builtin_isinf (pinff) != 1)
+    link_error ();
+  if (__builtin_isinff (pinff) != 1)
+    link_error ();
+  if (__builtin_isinf (pinfl) != 1)
+    link_error ();
+  if (__builtin_isinfl (pinfl) != 1)
+    link_error ();
+
+  if (__builtin_isinf (-pinf) != -1)
+    link_error ();
+  if (__builtin_isinf (-pinff) != -1)
+    link_error ();
+  if (__builtin_isinff (-pinff) != -1)
+    link_error ();
+  if (__builtin_isinf (-pinfl) != -1)
+    link_error ();
+  if (__builtin_isinfl (-pinfl) != -1)
+    link_error ();
+
+  if (__builtin_isinf (4.0))
+    link_error ();
+  if (__builtin_isinf (4.0))
+    link_error ();
+  if (__builtin_isinff (4.0))
+    link_error ();
+  if (__builtin_isinf (4.0))
+    link_error ();
+  if (__builtin_isinfl (4.0))
+    link_error ();
+}
+
+
+/* Check that all instances of link_error were subject to DCE.  */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/builtins-45.c b/gcc/testsuite/gcc.dg/builtins-45.c
new file mode 100644 (file)
index 0000000..967fba4
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-trapping-math -fdump-tree-optimized" } */
+  
+extern void f(int);
+extern void link_error ();
+
+extern float x;
+extern double y;
+extern long double z;
+
+int
+main ()
+{
+  double nan = __builtin_nan ("");
+  float nanf = __builtin_nanf ("");
+  long double nanl = __builtin_nanl ("");
+
+  double pinf = __builtin_inf ();
+  float pinff = __builtin_inff ();
+  long double pinfl = __builtin_infl ();
+
+  if (__builtin_finite (pinf))
+    link_error ();
+  if (__builtin_finitef (pinff))
+    link_error ();
+  if (__builtin_finitel (pinfl))
+    link_error ();
+
+  if (__builtin_finite (nan))
+    link_error ();
+  if (__builtin_finitef (nanf))
+    link_error ();
+  if (__builtin_finitel (nanl))
+    link_error ();
+
+  if (!__builtin_finite (4.0))
+    link_error ();
+  if (!__builtin_finitef (4.0))
+    link_error ();
+  if (!__builtin_finitel (4.0))
+    link_error ();
+}
+
+
+/* Check that all instances of link_error were subject to DCE.  */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
+