This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] More constant folding of math built-ins (take 2)
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Brad Lucier <lucier at math dot purdue dot edu>
- Date: Thu, 29 May 2003 07:09:25 -0600 (MDT)
- Subject: [PATCH] More constant folding of math built-ins (take 2)
My sincere apologies. As Brad Lucier has pointed out, my trigonometry
is not what it was twenty years ago, and the identity that I'd intended
to implement is tan(atan(x)) = x, not atan(tan(x)) = x [which is only
valid for -pi/2 < x < pi/2].
The following patch corrects my shame. Just goes to show you can
list six separate test cases, for a total of 26 checks of a single
patch, and still get things wrong! Many thanks again to Brad for
his excellent catch.
The following patch has been tested on i686-pc-linux-gnu, with a full
"make bootstrap", all languages except treelang (including Ada), and
regression tested with a top-level "make -k check" with no new failures.
The new test cases are unchanged, and as posted in my original patch.
Ok for mainline?
2003-05-29 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.
* 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.
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.203
diff -c -3 -p -r1.203 builtins.c
*** builtins.c 23 May 2003 20:45:38 -0000 1.203
--- builtins.c 29 May 2003 04:27:01 -0000
*************** tree built_in_decls[(int) END_BUILTINS];
*** 79,84 ****
--- 79,89 ----
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));
*************** static tree fold_builtin_nan PARAMS ((t
*** 169,174 ****
--- 174,194 ----
static int validate_arglist PARAMS ((tree, ...));
static tree fold_trunc_transparent_mathfn PARAMS ((tree));
static bool readonly_data_expr PARAMS ((tree));
+ 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.
*************** fold_builtin (exp)
*** 5117,5123 ****
/* Optimize sin(0.0) = 0.0. */
if (real_zerop (arg))
! return build_real (type, dconst0);
}
break;
--- 5137,5143 ----
/* Optimize sin(0.0) = 0.0. */
if (real_zerop (arg))
! return arg;
}
break;
*************** fold_builtin (exp)
*** 5146,5151 ****
--- 5166,5206 ----
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
*************** fold_builtin (exp)
*** 5205,5210 ****
--- 5260,5312 ----
}
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:
*************** fold_builtin (exp)
*** 5291,5297 ****
REAL_VALUE_TYPE cint;
HOST_WIDE_INT n;
! n = real_to_integer(&c);
real_from_integer (&cint, VOIDmode, n,
n < 0 ? -1 : 0, 0);
if (real_identical (&c, &cint))
--- 5393,5399 ----
REAL_VALUE_TYPE cint;
HOST_WIDE_INT n;
! n = real_to_integer (&c);
real_from_integer (&cint, VOIDmode, n,
n < 0 ? -1 : 0, 0);
if (real_identical (&c, &cint))
Index: builtins-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-2.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 builtins-2.c
*** builtins-2.c 16 Dec 2002 18:22:43 -0000 1.2
--- builtins-2.c 29 May 2003 04:23:06 -0000
*************** double test9(double x)
*** 53,58 ****
--- 53,63 ----
return fabs(exp(x));
}
+ double test10(double x)
+ {
+ return tan(atan(x));
+ }
+
float test1f(float x)
{
return logf(expf(x));
*************** float test9f(float x)
*** 98,103 ****
--- 103,113 ----
return fabsf(expf(x));
}
+ float test10f(float x)
+ {
+ return tanf(atanf(x));
+ }
+
long double test1l(long double x)
{
return logl(expl(x));
*************** long double test9l(long double x)
*** 143,146 ****
--- 153,160 ----
return fabsl(expl(x));
}
+ long double test10l(long double x)
+ {
+ return tanl(atanl(x));
+ }
Index: builtins-3.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-3.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 builtins-3.c
*** builtins-3.c 31 Mar 2003 14:30:29 -0000 1.3
--- builtins-3.c 29 May 2003 04:23:06 -0000
*************** int main()
*** 30,35 ****
--- 30,41 ----
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 ();
*************** int main()
*** 49,54 ****
--- 55,65 ----
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 ();
*************** int main()
*** 66,71 ****
--- 77,88 ----
link_error ();
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: builtins-7.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/builtins-7.c,v
retrieving revision 1.1
diff -c -3 -p -r1.1 builtins-7.c
*** builtins-7.c 31 Mar 2003 14:30:29 -0000 1.1
--- builtins-7.c 29 May 2003 04:23:06 -0000
*************** void test(double x)
*** 14,30 ****
--- 14,36 ----
{
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 ();
}
Roger
--