aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-06-04 12:20:40 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-06-04 12:20:40 +0000
commit385a9348eb92bdbee1052c83f62fd7db8887916d (patch)
tree0fff82636598319f282b94c466d49daa131c721d
parent8c6a82695b85f8ed74cdc67f2cf74c5a62d0d91d (diff)
downloadgcc-385a9348eb92bdbee1052c83f62fd7db8887916d.zip
gcc-385a9348eb92bdbee1052c83f62fd7db8887916d.tar.gz
gcc-385a9348eb92bdbee1052c83f62fd7db8887916d.tar.bz2
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/builtins.c106
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c58
-rw-r--r--gcc/testsuite/gcc.dg/builtins-17.c29
-rw-r--r--gcc/testsuite/gcc.dg/builtins-2.c14
-rw-r--r--gcc/testsuite/gcc.dg/builtins-3.c17
-rw-r--r--gcc/testsuite/gcc.dg/builtins-7.c6
-rw-r--r--gcc/testsuite/gcc.dg/i386-387-4.c11
9 files changed, 258 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4199b50..d61d60c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2003-06-04 Roger Sayle <roger@eyesopen.com>
+ * 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 <roger@eyesopen.com>
+
* calls.c (expand_call): Avoid calling pure or const functions
when the result is ignored (or void) and none of the arguments
are volatile. Move warning diagnostic earlier in function.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 53a1744..b227ffb 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 ab76c7b..e6e4169 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2003-06-04 Roger Sayle <roger@eyesopen.com>
+
+ * 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 <ebotcazou@libertysurf.fr>
* 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 0000000..0ede7ec
--- /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 <roger@eyesopen.com>, 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 0000000..f33512c
--- /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 68ef67e..ebd054f 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 3c2dbfd..4bab231 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 84c0e15..87995a4 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 0000000..809ab82
--- /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);
+}
+