This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fold isnan to UNORDERED_EXPR
- From: Paolo Bonzini <paolo dot bonzini at polimi dot it>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 28 Jun 2004 12:34:54 +0200
- Subject: [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" } } */