From 64a9295a723890c67026c3ccc42005e305beca66 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 1 Jul 2004 08:02:34 +0000 Subject: [PATCH] builtins.c (fold_builtin_classify): New. gcc/ChangeLog: 2004-07-01 Paolo Bonzini * 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 * gcc.dg/builtins-43.c: New. * gcc.dg/builtins-44.c: New. * gcc.dg/builtins-45.c: New. From-SVN: r83960 --- gcc/ChangeLog | 9 +++ gcc/builtins.c | 111 +++++++++++++++++++++++++++-- gcc/builtins.def | 9 +++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/builtins-43.c | 53 ++++++++++++++ gcc/testsuite/gcc.dg/builtins-44.c | 55 ++++++++++++++ gcc/testsuite/gcc.dg/builtins-45.c | 47 ++++++++++++ 7 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtins-43.c create mode 100644 gcc/testsuite/gcc.dg/builtins-44.c create mode 100644 gcc/testsuite/gcc.dg/builtins-45.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b78d22c765..3e42262f5a3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-07-01 Paolo Bonzini + + * 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 * function.h (struct function): Remove dont_emit_block_notes. diff --git a/gcc/builtins.c b/gcc/builtins.c index 74c1f98c69f..3155c611867 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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: diff --git a/gcc/builtins.def b/gcc/builtins.def index 52b29660c75..bd8a6308a3c 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 926c9cd8b7f..77ab7222a3b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-07-01 Paolo Bonzini + + * gcc.dg/builtins-43.c: New. + * gcc.dg/builtins-44.c: New. + * gcc.dg/builtins-45.c: New. + 2004-06-26 Geoffrey Keating Andreas Tobler diff --git a/gcc/testsuite/gcc.dg/builtins-43.c b/gcc/testsuite/gcc.dg/builtins-43.c new file mode 100644 index 00000000000..d174f7a90bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-43.c @@ -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 index 00000000000..2f5a3e1064c --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-44.c @@ -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 index 00000000000..967fba4afe4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-45.c @@ -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" } } */ + -- 2.30.2