This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fold isnan to UNORDERED_EXPR


This patch expand isnan(x) to UNORDERED_EXPR (x, x) at the tree level.
As a followup, I'll introduce folding UNORDERED_EXPR (x, x) ||
UNORDERED_EXPR (y, y) into UNORDERED_EXPR (x, y), and similarly for an
AND of two ORDERED_EXPRs.

Similar to what is done for isgreater and friends, isnan is declared as
a variadic function so that it can accept whatever floating-point type.

Indeed, waiting for Roger's restructuring of isgreater was useful, since
this patch is smaller and cleaner than my old one.

Bootstrapped/regtested i686-pc-linux-gnu, ok for mainline?

Paolo

2004-06-21 Paolo Bonzini <bonzini@gnu.org>

	* builtins.c (fold_builtin_isnan): New.
	(fold_builtin_unordered_cmp): Fix commentary.
	(fold_builtin) <BUILTIN_ISNAN>: Call fold_builtin_isnan.
	* builtins.def (BUILTIN_ISNAN): New.

2004-06-21 Paolo Bonzini <bonzini@gnu.org>

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




This patch expand isnan(x) to UNORDERED_EXPR (x, x).  Similar
to what is done for isgreater and friends, isnan is declared as
a variadic function so that it can accept whatever floating-point
type.

Paolo

2004-06-21  Paolo Bonzini  <bonzini@gnu.org>

	* builtins.c (fold_builtin_isnan): New.
	(fold_builtin_unordered_cmp): Fix commentary.
	(fold_builtin) <BUILTIN_ISNAN>: Call fold_builtin_isnan.
	* builtins.def (BUILTIN_ISNAN): New.

2004-06-21  Paolo Bonzini  <bonzini@gnu.org>

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

Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.342
diff -u -r1.342 builtins.c
--- builtins.c	20 Jun 2004 17:03:02 -0000	1.342
+++ builtins.c	21 Jun 2004 08:55:34 -0000
@@ -7608,12 +7608,55 @@
   return fold (build1 (ABS_EXPR, type, arg));
 }
 
+/* Fold a call to __builtin_isnan().  EXP is the CALL_EXPR for the
+   call.  */
+
+static tree
+fold_builtin_isnan (tree exp)
+{
+  tree fndecl = get_callee_fndecl (exp);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (TREE_TYPE (fndecl));
+  enum tree_code code;
+  tree arg;
+
+  if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      /* Check that we have exactly two arguments.  */
+      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);
+  if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg))))
+    return omit_one_operand (type, integer_zero_node, arg);
+
+  arg = builtin_save_expr (arg);
+  return fold (build2 (UNORDERED_EXPR, type, arg, arg));
+}
+
 /* 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,
@@ -8244,6 +8287,9 @@
     case BUILT_IN_COPYSIGNL:
       return fold_builtin_copysign (arglist, type);
 
+    case BUILT_IN_ISNAN:
+      return fold_builtin_isnan (exp);
+
     case BUILT_IN_ISGREATER:
       return fold_builtin_unordered_cmp (exp, UNLE_EXPR, LE_EXPR);
     case BUILT_IN_ISGREATEREQUAL:
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.85
diff -u -r1.85 builtins.def
--- builtins.def	10 Jun 2004 08:07:43 -0000	1.85
+++ builtins.def	21 Jun 2004 08:55:35 -0000
@@ -576,6 +576,7 @@
 DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
 DEF_LIB_BUILTIN        (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LIST)


/* { 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_isnan (nanl))
    link_error ();

  if (__builtin_isnan (4.0))
    link_error ();
  if (__builtin_isnan (4.0))
    link_error ();
  if (__builtin_isnan (4.0))
    link_error ();

  f (__builtin_isnan (x));
  f (__builtin_isnan (y));
  f (__builtin_isnan (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" } } */


/* { 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_isnan (nanl))
    link_error ();

  if (__builtin_isnan (4.0))
    link_error ();
  if (__builtin_isnan (4.0))
    link_error ();
  if (__builtin_isnan (4.0))
    link_error ();

  f (__builtin_isnan (x));
  f (__builtin_isnan (y));
  f (__builtin_isnan (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" } } */



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]