aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2007-02-23 14:27:50 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2007-02-23 14:27:50 +0000
commit6351a719ffd00bb53f088a2623c30334abb6240b (patch)
tree7e2a016dc7af2b71263c2fea7ef6b36983bc1429 /gcc/builtins.c
parent2ae2031ec142e650cf93c07963051f14a3426db0 (diff)
downloadgcc-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.c87
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);