real.c (real_floor, real_ceil): Tweak to allow input and output arguments to overlap.

* 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.

From-SVN: r76428
This commit is contained in:
Roger Sayle 2004-01-23 16:16:33 +00:00 committed by Roger Sayle
parent 69f2de23b2
commit 25348c94e7
4 changed files with 75 additions and 8 deletions

View file

@ -1,3 +1,15 @@
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

View file

@ -156,6 +156,7 @@ static tree fold_builtin_cabs (tree, tree, tree);
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);
@ -5923,6 +5924,38 @@ fold_builtin_ceil (tree exp)
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. */
@ -6868,6 +6901,8 @@ fold_builtin (tree exp)
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:

View file

@ -4539,11 +4539,13 @@ void
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
@ -4553,9 +4555,25 @@ void
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);
}

View file

@ -1,6 +1,6 @@
/* 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.
@ -372,5 +372,7 @@ extern void real_floor (REAL_VALUE_TYPE *, enum machine_mode,
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 */