diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2004-07-01 08:02:34 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2004-07-01 08:02:34 +0000 |
commit | 64a9295a723890c67026c3ccc42005e305beca66 (patch) | |
tree | a36dd2e20b0d8ec8ec87600ce7b3f20a3c5ce3a2 /gcc/builtins.c | |
parent | 1ea463a273df44816d63c3f96292341668a88ef0 (diff) | |
download | gcc-64a9295a723890c67026c3ccc42005e305beca66.zip gcc-64a9295a723890c67026c3ccc42005e305beca66.tar.gz gcc-64a9295a723890c67026c3ccc42005e305beca66.tar.bz2 |
builtins.c (fold_builtin_classify): New.
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
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 111 |
1 files changed, 106 insertions, 5 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 74c1f98..3155c61 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: |