aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2007-02-24 18:11:33 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2007-02-24 18:11:33 +0000
commit3d577eafa1d67958e22cae9a27d8194fd47bd22f (patch)
tree02890b0b9a4814d77189e87581d3c8ea66db9fe3 /gcc/builtins.c
parent00c73ae6373c0a4080b9a414b43cc6efebb0705c (diff)
downloadgcc-3d577eafa1d67958e22cae9a27d8194fd47bd22f.zip
gcc-3d577eafa1d67958e22cae9a27d8194fd47bd22f.tar.gz
gcc-3d577eafa1d67958e22cae9a27d8194fd47bd22f.tar.bz2
builtins.c (fold_builtin_modf): New.
* builtins.c (fold_builtin_modf): New. (fold_builtin_2): Use it. testsuite: * gcc.dg/torture/builtin-modf-1.c: New test. From-SVN: r122292
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d7074ed..3e1ab59 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -9214,6 +9214,62 @@ fold_builtin_load_exponent (tree arg0, tree arg1, tree type, bool ldexp)
return NULL_TREE;
}
+/* Fold a call to builtin modf. */
+
+static tree
+fold_builtin_modf (tree arg0, tree arg1, tree rettype)
+{
+ if (! validate_arg (arg0, REAL_TYPE) || ! validate_arg (arg1, POINTER_TYPE))
+ return NULL_TREE;
+
+ STRIP_NOPS (arg0);
+
+ if (!(TREE_CODE (arg0) == REAL_CST && ! TREE_OVERFLOW (arg0)))
+ return NULL_TREE;
+
+ arg1 = build_fold_indirect_ref (arg1);
+
+ /* Proceed if a valid pointer type was passed in. */
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) == TYPE_MAIN_VARIANT (rettype))
+ {
+ const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (arg0);
+ REAL_VALUE_TYPE trunc, frac;
+
+ switch (value->cl)
+ {
+ case rvc_nan:
+ case rvc_zero:
+ /* For +-NaN or +-0, return (*arg1 = arg0, arg0). */
+ trunc = frac = *value;
+ break;
+ case rvc_inf:
+ /* For +-Inf, return (*arg1 = arg0, +-0). */
+ frac = dconst0;
+ frac.sign = value->sign;
+ trunc = *value;
+ break;
+ case rvc_normal:
+ /* Return (*arg1 = trunc(arg0), arg0-trunc(arg0)). */
+ real_trunc (&trunc, VOIDmode, value);
+ real_arithmetic (&frac, MINUS_EXPR, value, &trunc);
+ /* If the original number was negative and already
+ integral, then the fractional part is -0.0. */
+ if (value->sign && frac.cl == rvc_zero)
+ frac.sign = value->sign;
+ break;
+ }
+
+ /* Create the COMPOUND_EXPR (*arg1 = trunc, frac). */
+ arg1 = fold_build2 (MODIFY_EXPR, rettype, arg1,
+ build_real (rettype, trunc));
+ TREE_SIDE_EFFECTS (arg1) = 1;
+ return fold_build2 (COMPOUND_EXPR, rettype, arg1,
+ build_real (rettype, frac));
+ }
+
+ return NULL_TREE;
+}
+
/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
ARG is the argument for the call. */
@@ -9690,6 +9746,9 @@ fold_builtin_2 (tree fndecl, tree arg0, tree arg1, bool ignore)
CASE_FLT_FN (BUILT_IN_FREXP):
return fold_builtin_frexp (arg0, arg1, type);
+ CASE_FLT_FN (BUILT_IN_MODF):
+ return fold_builtin_modf (arg0, arg1, type);
+
case BUILT_IN_BZERO:
return fold_builtin_bzero (arg0, arg1, ignore);