arguments to overlap.
(real_round): New function to implement round(3m) semantics.
* real.h (real_round): Prototype here.
* builtins.c (fold_builtin_round): New function to constant fold
round, roundf and roundl.
(fold_builtin): Call fold_builtin_round for BUILT_IN_ROUND{,F,L}.
* gcc.dg/builtins-29.c: New test case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76428
138bc75d-0d04-0410-961f-
82ee72b054a4
+2004-01-23 Roger Sayle <roger@eyesopen.com>
+
+ * real.c (real_floor, real_ceil): Tweak to allow input and output
+ arguments to overlap.
+ (real_round): New function to implement round(3m) semantics.
+ * real.h (real_round): Prototype here.
+ * builtins.c (fold_builtin_round): New function to constant fold
+ round, roundf and roundl.
+ (fold_builtin): Call fold_builtin_round for BUILT_IN_ROUND{,F,L}.
+
+ * gcc.dg/builtins-29.c: New test case.
+
2004-01-23 Alexandre Oliva <aoliva@redhat.com>
PR optimization/13819
static tree fold_builtin_trunc (tree);
static tree fold_builtin_floor (tree);
static tree fold_builtin_ceil (tree);
+static tree fold_builtin_round (tree);
static tree fold_builtin_bitop (tree);
static tree fold_builtin_memcpy (tree);
static tree fold_builtin_mempcpy (tree);
return fold_trunc_transparent_mathfn (exp);
}
+/* Fold function call to builtin round, roundf or roundl. Return
+ NULL_TREE if no simplification can be made. */
+
+static tree
+fold_builtin_round (tree exp)
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg;
+
+ if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+ return 0;
+
+ /* Optimize ceil of constant value. */
+ arg = TREE_VALUE (arglist);
+ if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg))
+ {
+ REAL_VALUE_TYPE x;
+
+ x = TREE_REAL_CST (arg);
+ if (! REAL_VALUE_ISNAN (x) || ! flag_errno_math)
+ {
+ tree type = TREE_TYPE (exp);
+ REAL_VALUE_TYPE r;
+
+ real_round (&r, TYPE_MODE (type), &x);
+ return build_real (type, r);
+ }
+ }
+
+ return fold_trunc_transparent_mathfn (exp);
+}
+
/* Fold function call to builtin ffs, clz, ctz, popcount and parity
and their long and long long variants (i.e. ffsl and ffsll).
Return NULL_TREE if no simplification can be made. */
case BUILT_IN_ROUND:
case BUILT_IN_ROUNDF:
case BUILT_IN_ROUNDL:
+ return fold_builtin_round (exp);
+
case BUILT_IN_NEARBYINT:
case BUILT_IN_NEARBYINTF:
case BUILT_IN_NEARBYINTL:
real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode,
const REAL_VALUE_TYPE *x)
{
- do_fix_trunc (r, x);
- if (! real_identical (r, x) && r->sign)
- do_add (r, r, &dconstm1, 0);
+ REAL_VALUE_TYPE t;
+
+ do_fix_trunc (&t, x);
+ if (! real_identical (&t, x) && x->sign)
+ do_add (&t, &t, &dconstm1, 0);
if (mode != VOIDmode)
- real_convert (r, mode, r);
+ real_convert (r, mode, &t);
}
/* Round X to the smallest integer not less then argument, i.e. round
real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode,
const REAL_VALUE_TYPE *x)
{
- do_fix_trunc (r, x);
- if (! real_identical (r, x) && ! r->sign)
- do_add (r, r, &dconst1, 0);
+ REAL_VALUE_TYPE t;
+
+ do_fix_trunc (&t, x);
+ if (! real_identical (&t, x) && ! x->sign)
+ do_add (&t, &t, &dconst1, 0);
+ if (mode != VOIDmode)
+ real_convert (r, mode, &t);
+}
+
+/* Round X to the nearest integer, but round halfway cases away from
+ zero. */
+
+void
+real_round (REAL_VALUE_TYPE *r, enum machine_mode mode,
+ const REAL_VALUE_TYPE *x)
+{
+ do_add (r, x, &dconsthalf, x->sign);
+ do_fix_trunc (r, r);
if (mode != VOIDmode)
real_convert (r, mode, r);
}
+
/* Definitions of floating-point access for GNU compiler.
Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998, 1999,
- 2000, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
const REAL_VALUE_TYPE *);
extern void real_ceil (REAL_VALUE_TYPE *, enum machine_mode,
const REAL_VALUE_TYPE *);
+extern void real_round (REAL_VALUE_TYPE *, enum machine_mode,
+ const REAL_VALUE_TYPE *);
#endif /* ! GCC_REAL_H */