diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-23 16:16:33 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-23 16:16:33 +0000 |
commit | 89ab38872b6855cc949da8c98193475846373bf3 (patch) | |
tree | a4e7871be466032d2019d3dd74d2f1702b848756 | |
parent | 1f8ad3f723ae0ef51930007ebc47611111a41f35 (diff) | |
download | gcc-89ab38872b6855cc949da8c98193475846373bf3.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76428 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/builtins.c | 35 | ||||
-rw-r--r-- | gcc/real.c | 32 | ||||
-rw-r--r-- | gcc/real.h | 4 |
4 files changed, 75 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 413c01ca1c3..e70f2e8e3bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/builtins.c b/gcc/builtins.c index 3174e75cea2..2dfc0e8a89e 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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: diff --git a/gcc/real.c b/gcc/real.c index 5d9bc41dcb7..cd27d3e0501 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -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); } + diff --git a/gcc/real.h b/gcc/real.h index 3620d50580a..3ff0356bd65 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -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 */ |