diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2008-05-18 23:19:38 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2008-05-18 23:19:38 +0000 |
commit | 05f41289d88658c05f34f713aed66054e12ff316 (patch) | |
tree | 90c75e8f2433a04ac95315cbba4166b8f7f7b3d2 /gcc/builtins.c | |
parent | d393bbd73754dfe54fac24d350c789316f17428f (diff) | |
download | gcc-05f41289d88658c05f34f713aed66054e12ff316.zip gcc-05f41289d88658c05f34f713aed66054e12ff316.tar.gz gcc-05f41289d88658c05f34f713aed66054e12ff316.tar.bz2 |
re PR middle-end/35509 (builtin isinf() mismatch to compile-time substitution)
PR middle-end/35509
* builtins.c (mathfn_built_in_1): Renamed from mathfn_built_in.
Add `implicit' parameter. Handle BUILT_IN_SIGNBIT.
(mathfn_built_in): Rewrite in terms of mathfn_built_in_1.
(fold_builtin_classify): Handle BUILT_IN_ISINF_SIGN.
(fold_builtin_1): Likewise.
* builtins.def (BUILT_IN_ISINF_SIGN): New.
c-common.c (check_builtin_function_arguments): Handle
BUILT_IN_ISINF_SIGN.
* doc/extend.texi: Document __builtin_isinf_sign.
* fold-const.c (operand_equal_p): Handle COND_EXPR.
testsuite:
* gcc.dg/builtins-error.c: Test __builtin_isinf_sign.
* gcc.dg/tg-tests.h: Likewise. Mark variables volatile.
* gcc.dg/torture/builtin-isinf_sign-1.c: New test.
From-SVN: r135517
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 4211e62..3060f80 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1669,10 +1669,15 @@ expand_builtin_classify_type (tree exp) fcodel = BUILT_IN_MATHFN##L_R ; break; /* Return mathematic function equivalent to FN but operating directly - on TYPE, if available. If we can't do the conversion, return zero. */ -tree -mathfn_built_in (tree type, enum built_in_function fn) + on TYPE, if available. If IMPLICIT is true find the function in + implicit_built_in_decls[], otherwise use built_in_decls[]. If we + can't do the conversion, return zero. */ + +static tree +mathfn_built_in_1 (tree type, enum built_in_function fn, bool implicit) { + tree const *const fn_arr + = implicit ? implicit_built_in_decls : built_in_decls; enum built_in_function fcode, fcodef, fcodel; switch (fn) @@ -1747,6 +1752,7 @@ mathfn_built_in (tree type, enum built_in_function fn) CASE_MATHFN (BUILT_IN_SCALB) CASE_MATHFN (BUILT_IN_SCALBLN) CASE_MATHFN (BUILT_IN_SCALBN) + CASE_MATHFN (BUILT_IN_SIGNBIT) CASE_MATHFN (BUILT_IN_SIGNIFICAND) CASE_MATHFN (BUILT_IN_SIN) CASE_MATHFN (BUILT_IN_SINCOS) @@ -1765,15 +1771,23 @@ mathfn_built_in (tree type, enum built_in_function fn) } if (TYPE_MAIN_VARIANT (type) == double_type_node) - return implicit_built_in_decls[fcode]; + return fn_arr[fcode]; else if (TYPE_MAIN_VARIANT (type) == float_type_node) - return implicit_built_in_decls[fcodef]; + return fn_arr[fcodef]; else if (TYPE_MAIN_VARIANT (type) == long_double_type_node) - return implicit_built_in_decls[fcodel]; + return fn_arr[fcodel]; else return NULL_TREE; } +/* Like mathfn_built_in_1(), but always use the implicit array. */ + +tree +mathfn_built_in (tree type, enum built_in_function fn) +{ + return mathfn_built_in_1 (type, fn, /*implicit=*/ 1); +} + /* If errno must be maintained, expand the RTL to check if the result, TARGET, of a built-in function call, EXP, is NaN, and if so set errno to EDOM. */ @@ -9668,6 +9682,37 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index) return NULL_TREE; + case BUILT_IN_ISINF_SIGN: + { + /* isinf_sign(x) -> isinf(x) ? (signbit(x) ? -1 : 1) : 0 */ + /* In a boolean context, GCC will fold the inner COND_EXPR to + 1. So e.g. "if (isinf_sign(x))" would be folded to just + "if (isinf(x) ? 1 : 0)" which becomes "if (isinf(x))". */ + tree signbit_fn = mathfn_built_in_1 (TREE_TYPE (arg), BUILT_IN_SIGNBIT, 0); + tree isinf_fn = built_in_decls[BUILT_IN_ISINF]; + tree tmp = NULL_TREE; + + arg = builtin_save_expr (arg); + + if (signbit_fn && isinf_fn) + { + tree signbit_call = build_call_expr (signbit_fn, 1, arg); + tree isinf_call = build_call_expr (isinf_fn, 1, arg); + + signbit_call = fold_build2 (NE_EXPR, integer_type_node, + signbit_call, integer_zero_node); + isinf_call = fold_build2 (NE_EXPR, integer_type_node, + isinf_call, integer_zero_node); + + tmp = fold_build3 (COND_EXPR, integer_type_node, signbit_call, + integer_minus_one_node, integer_one_node); + tmp = fold_build3 (COND_EXPR, integer_type_node, isinf_call, tmp, + integer_zero_node); + } + + return tmp; + } + case BUILT_IN_ISFINITE: if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))) && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) @@ -10074,6 +10119,9 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore) case BUILT_IN_ISINFD128: return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF); + case BUILT_IN_ISINF_SIGN: + return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISINF_SIGN); + CASE_FLT_FN (BUILT_IN_ISNAN): case BUILT_IN_ISNAND32: case BUILT_IN_ISNAND64: |