]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
builtins.c (dconstpi, dconste): New mathematical constants.
authorRoger Sayle <roger@eyesopen.com>
Wed, 4 Jun 2003 12:20:40 +0000 (12:20 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Wed, 4 Jun 2003 12:20:40 +0000 (12:20 +0000)
* 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
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/ieee/mzero4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-17.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-2.c
gcc/testsuite/gcc.dg/builtins-3.c
gcc/testsuite/gcc.dg/builtins-7.c
gcc/testsuite/gcc.dg/i386-387-4.c [new file with mode: 0644]

index 4199b5091a80704b4d4718195e22da43df464c27..d61d60c86ee703575560398de3203d8e9bbe9302 100644 (file)
@@ -1,3 +1,13 @@
+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
index 53a1744fe724a257b8cf79b2e351a6c9dd79ec9e..b227ffbcd2c527699b1656cf7e4ce50569169bdc 100644 (file)
@@ -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))
index ab76c7b8343f6cf5b595272d9701752646192194..e6e4169382d4f42bb2ab42057e7f128a32e4098f 100644 (file)
@@ -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 (file)
index 0000000..0ede7ec
--- /dev/null
@@ -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 (file)
index 0000000..f33512c
--- /dev/null
@@ -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;
+}
+
index 68ef67e297b97889415691a9c54990dfadbcc571..ebd054f229a0ed94bf79a7685e6be8996a47abbf 100644 (file)
@@ -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));
+}
 
index 3c2dbfd7f52fdce6eb743b68a1fd4b04114b1819..4bab231a57138c69e2922e84e926db8c419bbf15 100644 (file)
@@ -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;
 }
 
index 84c0e154fa09c72f7baaa6920c5e3eb80a20fe6f..87995a4d3a0da8ff76a93778cfedebe775a88540 100644 (file)
@@ -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 (file)
index 0000000..809ab82
--- /dev/null
@@ -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);
+}
+