Commit 25348c94 by Roger Sayle Committed by Roger Sayle

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
parent 69f2de23
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
......
......@@ -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:
......
......@@ -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);
}
/* 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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment