diff options
author | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-05-23 04:47:12 +0000 |
---|---|---|
committer | ghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-05-23 04:47:12 +0000 |
commit | 19fbe3a4cad0e35dfa638aaa049892c554299ab7 (patch) | |
tree | a7912b37870308a35af6d7fef3d8dedaa111ecf9 /gcc/builtins.c | |
parent | d64890c04581af07969401c844d47f37332327d2 (diff) | |
download | gcc-19fbe3a4cad0e35dfa638aaa049892c554299ab7.tar.gz |
* builtin-types.def (BT_FN_INT_INT_INT_INT_INT_INT_VAR): New.
* builtins.c (fold_builtin_fpclassify): New.
(fold_builtin_varargs): Handle BUILT_IN_FPCLASSIFY.
* builtins.def (BUILT_IN_FPCLASSIFY): New.
* c-common.c (handle_type_generic_attribute): Adjust to accept
fixed arguments before an elipsis.
(check_builtin_function_arguments): Handle BUILT_IN_FPCLASSIFY.
* doc/extend.texi: Document __builtin_fpclassify.
testsuite:
* gcc.dg/builtins-error.c: Test __builtin_fpclassify. Also
add tests for all previous type-generic builtins.
* gcc.dg/pr28796-2.c: Add -DUNSAFE flag.
* gcc.dg/tg-tests.h: Test __builtin_fpclassify.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@135789 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 3060f80ae00..d442469b7ee 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -9744,6 +9744,70 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index) } } +/* Fold a call to __builtin_fpclassify(int, int, int, int, int, ...). + This builtin will generate code to return the appropriate floating + point classification depending on the value of the floating point + number passed in. The possible return values must be supplied as + int arguments to the call in the following order: FP_NAN, FP_INF, + FP_NORMAL, FP_SUBNORMAL and FP_ZERO. The ellipses is for exactly + one floating point argument which is "type generic". */ + +static tree +fold_builtin_fpclassify (tree exp) +{ + tree fp_nan, fp_inf, fp_normal, fp_subnormal, fp_zero, arg, type, res, tmp; + enum machine_mode mode; + REAL_VALUE_TYPE r; + char buf[128]; + + /* Verify the required arguments in the original call. */ + if (!validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, + INTEGER_TYPE, INTEGER_TYPE, + INTEGER_TYPE, REAL_TYPE, VOID_TYPE)) + return NULL_TREE; + + fp_nan = CALL_EXPR_ARG (exp, 0); + fp_inf = CALL_EXPR_ARG (exp, 1); + fp_normal = CALL_EXPR_ARG (exp, 2); + fp_subnormal = CALL_EXPR_ARG (exp, 3); + fp_zero = CALL_EXPR_ARG (exp, 4); + arg = CALL_EXPR_ARG (exp, 5); + type = TREE_TYPE (arg); + mode = TYPE_MODE (type); + arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg)); + + /* fpclassify(x) -> + isnan(x) ? FP_NAN : + (fabs(x) == Inf ? FP_INF : + (fabs(x) >= DBL_MIN ? FP_NORMAL : + (x == 0 ? FP_ZERO : FP_SUBNORMAL))). */ + + tmp = fold_build2 (EQ_EXPR, integer_type_node, arg, + build_real (type, dconst0)); + res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_zero, fp_subnormal); + + sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); + real_from_string (&r, buf); + tmp = fold_build2 (GE_EXPR, integer_type_node, arg, build_real (type, r)); + res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_normal, res); + + if (HONOR_INFINITIES (mode)) + { + real_inf (&r); + tmp = fold_build2 (EQ_EXPR, integer_type_node, arg, + build_real (type, r)); + res = fold_build3 (COND_EXPR, integer_type_node, tmp, fp_inf, res); + } + + if (HONOR_NANS (mode)) + { + tmp = fold_build2 (ORDERED_EXPR, integer_type_node, arg, arg); + res = fold_build3 (COND_EXPR, integer_type_node, tmp, res, fp_nan); + } + + return res; +} + /* Fold a call to an unordered comparison function such as __builtin_isgreater(). FNDECL is the FUNCTION_DECL for the function being called and ARG0 and ARG1 are the arguments for the call. @@ -10528,6 +10592,11 @@ fold_builtin_varargs (tree fndecl, tree exp, bool ignore ATTRIBUTE_UNUSED) case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_VSNPRINTF_CHK: ret = fold_builtin_snprintf_chk (exp, NULL_TREE, fcode); + break; + + case BUILT_IN_FPCLASSIFY: + ret = fold_builtin_fpclassify (exp); + break; default: break; |