From 385a9348eb92bdbee1052c83f62fd7db8887916d Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Wed, 4 Jun 2003 12:20:40 +0000 Subject: [PATCH] builtins.c (dconstpi, dconste): New mathematical constants. * builtins.c (dconstpi, dconste): New mathematical constants. (init_builtin_dconsts): New function to initialize dconstpi and dconste. (fold_builtin): Optimize exp(1.0) = e. Evaluate exp(x) at compile time with -ffast-math when x is an integer constant. Optimize tan(0.0) = 0.0. Optimize atan(0.0) = 0.0, atan(1.0) = pi/4 and tan(atan(x)) = x with -ffast-math. * gcc.dg/builtins-2.c: Add tests for tan(atan(x)). * gcc.dg/builtins-3.c: Add tests for tan(0.0) and atan(0.0). * gcc.dg/builtins-7.c: Add tests for tan(atan(x)) == x. * gcc.dg/builtins-17.c: New test case. * gcc.dg/i386-387-4.c: New test case. * gcc.c-torture/execute/ieee/mzero4.c: New test case. From-SVN: r67438 --- gcc/ChangeLog | 10 ++ gcc/builtins.c | 106 +++++++++++++++++- gcc/testsuite/ChangeLog | 9 ++ .../gcc.c-torture/execute/ieee/mzero4.c | 58 ++++++++++ gcc/testsuite/gcc.dg/builtins-17.c | 29 +++++ gcc/testsuite/gcc.dg/builtins-2.c | 14 +++ gcc/testsuite/gcc.dg/builtins-3.c | 17 +++ gcc/testsuite/gcc.dg/builtins-7.c | 6 + gcc/testsuite/gcc.dg/i386-387-4.c | 11 ++ 9 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c create mode 100644 gcc/testsuite/gcc.dg/builtins-17.c create mode 100644 gcc/testsuite/gcc.dg/i386-387-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4199b5091a8..d61d60c86ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2003-06-04 Roger Sayle + + * builtins.c (dconstpi, dconste): New mathematical constants. + (init_builtin_dconsts): New function to initialize dconstpi + and dconste. + (fold_builtin): Optimize exp(1.0) = e. Evaluate exp(x) at + compile time with -ffast-math when x is an integer constant. + Optimize tan(0.0) = 0.0. Optimize atan(0.0) = 0.0, + atan(1.0) = pi/4 and tan(atan(x)) = x with -ffast-math. + 2003-06-04 Roger Sayle * calls.c (expand_call): Avoid calling pure or const functions diff --git a/gcc/builtins.c b/gcc/builtins.c index 53a1744fe72..b227ffbcd2c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -79,6 +79,11 @@ tree built_in_decls[(int) END_BUILTINS]; required to implement the function call in all cases. */ tree implicit_built_in_decls[(int) END_BUILTINS]; +/* Trigonometric and mathematical constants used in builtin folding. */ +static bool builtin_dconsts_init = 0; +static REAL_VALUE_TYPE dconstpi; +static REAL_VALUE_TYPE dconste; + static int get_pointer_alignment PARAMS ((tree, unsigned int)); static tree c_strlen PARAMS ((tree)); static const char *c_getstr PARAMS ((tree)); @@ -171,7 +176,22 @@ static tree fold_trunc_transparent_mathfn PARAMS ((tree)); static bool readonly_data_expr PARAMS ((tree)); static rtx expand_builtin_fabs PARAMS ((tree, rtx, rtx)); static rtx expand_builtin_cabs PARAMS ((tree, rtx)); +static void init_builtin_dconsts PARAMS ((void)); + +/* Initialize mathematical constants for constant folding builtins. + These constants need to be given to atleast 160 bits precision. */ +static void +init_builtin_dconsts () +{ + real_from_string (&dconstpi, + "3.1415926535897932384626433832795028841971693993751058209749445923078"); + real_from_string (&dconste, + "2.7182818284590452353602874713526624977572470936999595749669676277241"); + + builtin_dconsts_init = true; +} + /* Return the alignment in bits of EXP, a pointer valued expression. But don't return more than MAX_ALIGN no matter what. The alignment returned is, by default, the alignment of the thing that @@ -5213,7 +5233,7 @@ fold_builtin (exp) /* Optimize sin(0.0) = 0.0. */ if (real_zerop (arg)) - return build_real (type, dconst0); + return arg; } break; @@ -5242,6 +5262,41 @@ fold_builtin (exp) if (real_zerop (arg)) return build_real (type, dconst1); + /* Optimize exp(1.0) = e. */ + if (real_onep (arg)) + { + REAL_VALUE_TYPE cst; + + if (! builtin_dconsts_init) + init_builtin_dconsts (); + real_convert (&cst, TYPE_MODE (type), &dconste); + return build_real (type, cst); + } + + /* Attempt to evaluate exp at compile-time. */ + if (flag_unsafe_math_optimizations + && TREE_CODE (arg) == REAL_CST + && ! TREE_CONSTANT_OVERFLOW (arg)) + { + REAL_VALUE_TYPE cint; + REAL_VALUE_TYPE c; + HOST_WIDE_INT n; + + c = TREE_REAL_CST (arg); + n = real_to_integer (&c); + real_from_integer (&cint, VOIDmode, n, + n < 0 ? -1 : 0, 0); + if (real_identical (&c, &cint)) + { + REAL_VALUE_TYPE x; + + if (! builtin_dconsts_init) + init_builtin_dconsts (); + real_powi (&x, TYPE_MODE (type), &dconste, n); + return build_real (type, x); + } + } + /* Optimize exp(log(x)) = x. */ fcode = builtin_mathfn_code (arg); if (flag_unsafe_math_optimizations @@ -5301,6 +5356,53 @@ fold_builtin (exp) } break; + case BUILT_IN_TAN: + case BUILT_IN_TANF: + case BUILT_IN_TANL: + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + { + enum built_in_function fcode; + tree arg = TREE_VALUE (arglist); + + /* Optimize tan(0.0) = 0.0. */ + if (real_zerop (arg)) + return arg; + + /* Optimize tan(atan(x)) = x. */ + fcode = builtin_mathfn_code (arg); + if (flag_unsafe_math_optimizations + && (fcode == BUILT_IN_ATAN + || fcode == BUILT_IN_ATANF + || fcode == BUILT_IN_ATANL)) + return TREE_VALUE (TREE_OPERAND (arg, 1)); + } + break; + + case BUILT_IN_ATAN: + case BUILT_IN_ATANF: + case BUILT_IN_ATANL: + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + { + tree arg = TREE_VALUE (arglist); + + /* Optimize atan(0.0) = 0.0. */ + if (real_zerop (arg)) + return arg; + + /* Optimize atan(1.0) = pi/4. */ + if (real_onep (arg)) + { + REAL_VALUE_TYPE cst; + + if (! builtin_dconsts_init) + init_builtin_dconsts (); + real_convert (&cst, TYPE_MODE (type), &dconstpi); + cst.exp -= 2; + return build_real (type, cst); + } + } + break; + case BUILT_IN_POW: case BUILT_IN_POWF: case BUILT_IN_POWL: @@ -5387,7 +5489,7 @@ fold_builtin (exp) REAL_VALUE_TYPE cint; HOST_WIDE_INT n; - n = real_to_integer(&c); + n = real_to_integer (&c); real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0); if (real_identical (&c, &cint)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ab76c7b8343..e6e4169382d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2003-06-04 Roger Sayle + + * gcc.dg/builtins-2.c: Add tests for tan(atan(x)). + * gcc.dg/builtins-3.c: Add tests for tan(0.0) and atan(0.0). + * gcc.dg/builtins-7.c: Add tests for tan(atan(x)) == x. + * gcc.dg/builtins-17.c: New test case. + * gcc.dg/i386-387-4.c: New test case. + * gcc.c-torture/execute/ieee/mzero4.c: New test case. + 2003-06-04 Eric Botcazou * gcc.dg/ultrasp9.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c b/gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c new file mode 100644 index 00000000000..0ede7ec9598 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 Free Software Foundation. + by Roger Sayle , derived from mzero3.c + + Constant folding of sin(-0.0), tan(-0.0) and atan(-0.0) should + all return -0.0, for both double and float forms. */ + +void abort (void); +typedef __SIZE_TYPE__ size_t; +extern int memcmp (const void *, const void *, size_t); + +double sin (double); +double tan (double); +double atan (double); + +float sinf (float); +float tanf (float); +float atanf (float); + +void expectd (double, double); +void expectf (float, float); + +void +expectd (double value, double expected) +{ + if (value != expected + || memcmp ((void *)&value, (void *) &expected, sizeof (double)) != 0) + abort (); +} + +void +expectf (float value, float expected) +{ + if (value != expected + || memcmp ((void *)&value, (void *) &expected, sizeof (float)) != 0) + abort (); +} + +int main () +{ + expectd (sin (0.0), 0.0); + expectd (tan (0.0), 0.0); + expectd (atan (0.0), 0.0); + + expectd (sin (-0.0), -0.0); + expectd (tan (-0.0), -0.0); + expectd (atan (-0.0), -0.0); + + expectf (sinf (0.0f), 0.0f); + expectf (tanf (0.0f), 0.0f); + expectf (atanf (0.0f), 0.0f); + + expectf (sinf (-0.0f), -0.0f); + expectf (tanf (-0.0f), -0.0f); + expectf (atanf (-0.0f), -0.0f); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-17.c b/gcc/testsuite/gcc.dg/builtins-17.c new file mode 100644 index 00000000000..f33512cb916 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-17.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation. + + Check that constant folding of built-in math functions doesn't + break anything and produces the expected results. + + Written by Roger Sayle, 25th May 2003. */ + +/* { dg-do link } */ +/* { dg-options "-O2 -ffast-math" } */ + +extern void link_error(void); + +extern double exp(double); + + +int main() +{ + if (exp (1.0) < 2.71 || exp (1.0) > 2.72) + link_error (); + if (exp (2.0) < 7.38 || exp (2.0) > 7.39) + link_error (); + if (exp (-2.0) < 0.13 || exp (-2.0) > 0.14) + link_error (); + if (atan (1.0) < 0.78 || atan (1.0) > 0.79) + link_error (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-2.c b/gcc/testsuite/gcc.dg/builtins-2.c index 68ef67e297b..ebd054f229a 100644 --- a/gcc/testsuite/gcc.dg/builtins-2.c +++ b/gcc/testsuite/gcc.dg/builtins-2.c @@ -53,6 +53,11 @@ double test9(double x) return fabs(exp(x)); } +double test10(double x) +{ + return tan(atan(x)); +} + float test1f(float x) { return logf(expf(x)); @@ -98,6 +103,11 @@ float test9f(float x) return fabsf(expf(x)); } +float test10f(float x) +{ + return tanf(atanf(x)); +} + long double test1l(long double x) { return logl(expl(x)); @@ -143,4 +153,8 @@ long double test9l(long double x) return fabsl(expl(x)); } +long double test10l(long double x) +{ + return tanl(atanl(x)); +} diff --git a/gcc/testsuite/gcc.dg/builtins-3.c b/gcc/testsuite/gcc.dg/builtins-3.c index 3c2dbfd7f52..4bab231a571 100644 --- a/gcc/testsuite/gcc.dg/builtins-3.c +++ b/gcc/testsuite/gcc.dg/builtins-3.c @@ -30,6 +30,12 @@ int main() if (cos (0.0) != 1.0) link_error (); + if (tan (0.0) != 0.0) + link_error (); + + if (atan (0.0) != 0.0) + link_error (); + if (sqrtf (0.0f) != 0.0f) link_error (); @@ -49,6 +55,11 @@ int main() if (cosf (0.0f) != 1.0f) link_error (); + if (tanf (0.0f) != 0.0f) + link_error (); + + if (atanf (0.0f) != 0.0f) + link_error (); if (sqrtl (0.0l) != 0.0l) link_error (); @@ -68,6 +79,12 @@ int main() if (cosl (0.0l) != 1.0l) link_error (); + if (tanl (0.0l) != 0.0l) + link_error (); + + if (atanl (0.0) != 0.0l) + link_error (); + return 0; } diff --git a/gcc/testsuite/gcc.dg/builtins-7.c b/gcc/testsuite/gcc.dg/builtins-7.c index 84c0e154fa0..87995a4d3a0 100644 --- a/gcc/testsuite/gcc.dg/builtins-7.c +++ b/gcc/testsuite/gcc.dg/builtins-7.c @@ -14,18 +14,24 @@ void test(double x) { if (pow (x, 1.0) != x) link_error (); + if (tan (atan (x)) != x) + link_error (); } void testf(float x) { if (powf (x, 1.0f) != x) link_error (); + if (tanf (atanf (x)) != x) + link_error (); } void testl(long double x) { if (powl (x, 1.0l) != x) link_error (); + if (tanl (atanl (x)) != x) + link_error (); } int main() diff --git a/gcc/testsuite/gcc.dg/i386-387-4.c b/gcc/testsuite/gcc.dg/i386-387-4.c new file mode 100644 index 00000000000..809ab823660 --- /dev/null +++ b/gcc/testsuite/gcc.dg/i386-387-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target "i?86-*-*" } } */ +/* { dg-options "-O2 -march=i686" } */ +/* { dg-final { scan-assembler "fldpi" } } */ + +long double atanl (long double); + +long double pi() +{ + return 4.0 * atanl (1.0); +} + -- 2.30.2