diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2007-02-23 14:27:50 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2007-02-23 14:27:50 +0000 |
commit | 6351a719ffd00bb53f088a2623c30334abb6240b (patch) | |
tree | 7e2a016dc7af2b71263c2fea7ef6b36983bc1429 /gcc/builtins.c | |
parent | 2ae2031ec142e650cf93c07963051f14a3426db0 (diff) | |
download | gcc-6351a719ffd00bb53f088a2623c30334abb6240b.zip gcc-6351a719ffd00bb53f088a2623c30334abb6240b.tar.gz gcc-6351a719ffd00bb53f088a2623c30334abb6240b.tar.bz2 |
builtins.c (fold_builtin_logb, [...]): New.
* builtins.c (fold_builtin_logb, fold_builtin_significand): New.
(fold_builtin_1): Use them.
* fold-const.c (tree_expr_nonnegative_warnv_p): Handle
BUILT_IN_SIGNIFICAND.
testsuite:
* gcc.dg/torture/builtin-logb-1.c: New test.
* gcc.dg/torture/builtin-math-2.c: Test logb/ilogb.
* gcc.dg/torture/builtin-nonneg-1.c: Test significand.
* gcc.dg/torture/builtin-frexp-1.c: Use -fno-finite-math-only on
sh* targets.
From-SVN: r122257
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 5c6dd4d..d7074ed 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -9017,6 +9017,86 @@ fold_builtin_carg (tree arg, tree type) return NULL_TREE; } +/* Fold a call to builtin logb/ilogb. */ + +static tree +fold_builtin_logb (tree arg, tree rettype) +{ + if (! validate_arg (arg, REAL_TYPE)) + return NULL_TREE; + + STRIP_NOPS (arg); + + if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) + { + const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); + + switch (value->cl) + { + case rvc_nan: + case rvc_inf: + /* If arg is Inf or NaN and we're logb, return it. */ + if (TREE_CODE (rettype) == REAL_TYPE) + return fold_convert (rettype, arg); + /* Fall through... */ + case rvc_zero: + /* Zero may set errno and/or raise an exception for logb, also + for ilogb we don't know FP_ILOGB0. */ + return NULL_TREE; + case rvc_normal: + /* For normal numbers, proceed iff radix == 2. In GCC, + normalized significands are in the range [0.5, 1.0). We + want the exponent as if they were [1.0, 2.0) so get the + exponent and subtract 1. */ + if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) + return fold_convert (rettype, build_int_cst (NULL_TREE, + REAL_EXP (value)-1)); + break; + } + } + + return NULL_TREE; +} + +/* Fold a call to builtin significand, if radix == 2. */ + +static tree +fold_builtin_significand (tree arg, tree rettype) +{ + if (! validate_arg (arg, REAL_TYPE)) + return NULL_TREE; + + STRIP_NOPS (arg); + + if (TREE_CODE (arg) == REAL_CST && ! TREE_OVERFLOW (arg)) + { + const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg); + + switch (value->cl) + { + case rvc_zero: + case rvc_nan: + case rvc_inf: + /* If arg is +-0, +-Inf or +-NaN, then return it. */ + return fold_convert (rettype, arg); + case rvc_normal: + /* For normal numbers, proceed iff radix == 2. */ + if (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)))->b == 2) + { + REAL_VALUE_TYPE result = *value; + /* In GCC, normalized significands are in the range [0.5, + 1.0). We want them to be [1.0, 2.0) so set the + exponent to 1. */ + SET_REAL_EXP (&result, 1); + return build_real (rettype, result); + } + break; + } + } + + return NULL_TREE; +} + /* Fold a call to builtin frexp, we can assume the base is 2. */ static tree @@ -9526,6 +9606,13 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore) CASE_FLT_FN (BUILT_IN_SIGNBIT): return fold_builtin_signbit (arg0, type); + CASE_FLT_FN (BUILT_IN_SIGNIFICAND): + return fold_builtin_significand (arg0, type); + + CASE_FLT_FN (BUILT_IN_ILOGB): + CASE_FLT_FN (BUILT_IN_LOGB): + return fold_builtin_logb (arg0, type); + case BUILT_IN_ISASCII: return fold_builtin_isascii (arg0); |