Commit 385a9348 by Roger Sayle Committed by Roger Sayle

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
parent 8c6a8269
2003-06-04 Roger Sayle <roger@eyesopen.com> 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 * calls.c (expand_call): Avoid calling pure or const functions
when the result is ignored (or void) and none of the arguments when the result is ignored (or void) and none of the arguments
are volatile. Move warning diagnostic earlier in function. are volatile. Move warning diagnostic earlier in function.
......
...@@ -79,6 +79,11 @@ tree built_in_decls[(int) END_BUILTINS]; ...@@ -79,6 +79,11 @@ tree built_in_decls[(int) END_BUILTINS];
required to implement the function call in all cases. */ required to implement the function call in all cases. */
tree implicit_built_in_decls[(int) END_BUILTINS]; 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 int get_pointer_alignment PARAMS ((tree, unsigned int));
static tree c_strlen PARAMS ((tree)); static tree c_strlen PARAMS ((tree));
static const char *c_getstr PARAMS ((tree)); static const char *c_getstr PARAMS ((tree));
...@@ -171,7 +176,22 @@ static tree fold_trunc_transparent_mathfn PARAMS ((tree)); ...@@ -171,7 +176,22 @@ static tree fold_trunc_transparent_mathfn PARAMS ((tree));
static bool readonly_data_expr PARAMS ((tree)); static bool readonly_data_expr PARAMS ((tree));
static rtx expand_builtin_fabs PARAMS ((tree, rtx, rtx)); static rtx expand_builtin_fabs PARAMS ((tree, rtx, rtx));
static rtx expand_builtin_cabs PARAMS ((tree, 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. /* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what. But don't return more than MAX_ALIGN no matter what.
The alignment returned is, by default, the alignment of the thing that The alignment returned is, by default, the alignment of the thing that
...@@ -5213,7 +5233,7 @@ fold_builtin (exp) ...@@ -5213,7 +5233,7 @@ fold_builtin (exp)
/* Optimize sin(0.0) = 0.0. */ /* Optimize sin(0.0) = 0.0. */
if (real_zerop (arg)) if (real_zerop (arg))
return build_real (type, dconst0); return arg;
} }
break; break;
...@@ -5242,6 +5262,41 @@ fold_builtin (exp) ...@@ -5242,6 +5262,41 @@ fold_builtin (exp)
if (real_zerop (arg)) if (real_zerop (arg))
return build_real (type, dconst1); 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. */ /* Optimize exp(log(x)) = x. */
fcode = builtin_mathfn_code (arg); fcode = builtin_mathfn_code (arg);
if (flag_unsafe_math_optimizations if (flag_unsafe_math_optimizations
...@@ -5301,6 +5356,53 @@ fold_builtin (exp) ...@@ -5301,6 +5356,53 @@ fold_builtin (exp)
} }
break; 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_POW:
case BUILT_IN_POWF: case BUILT_IN_POWF:
case BUILT_IN_POWL: case BUILT_IN_POWL:
...@@ -5387,7 +5489,7 @@ fold_builtin (exp) ...@@ -5387,7 +5489,7 @@ fold_builtin (exp)
REAL_VALUE_TYPE cint; REAL_VALUE_TYPE cint;
HOST_WIDE_INT n; HOST_WIDE_INT n;
n = real_to_integer(&c); n = real_to_integer (&c);
real_from_integer (&cint, VOIDmode, n, real_from_integer (&cint, VOIDmode, n,
n < 0 ? -1 : 0, 0); n < 0 ? -1 : 0, 0);
if (real_identical (&c, &cint)) if (real_identical (&c, &cint))
......
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> 2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/ultrasp9.c: New test. * gcc.dg/ultrasp9.c: New test.
......
/* 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;
}
/* 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;
}
...@@ -53,6 +53,11 @@ double test9(double x) ...@@ -53,6 +53,11 @@ double test9(double x)
return fabs(exp(x)); return fabs(exp(x));
} }
double test10(double x)
{
return tan(atan(x));
}
float test1f(float x) float test1f(float x)
{ {
return logf(expf(x)); return logf(expf(x));
...@@ -98,6 +103,11 @@ float test9f(float x) ...@@ -98,6 +103,11 @@ float test9f(float x)
return fabsf(expf(x)); return fabsf(expf(x));
} }
float test10f(float x)
{
return tanf(atanf(x));
}
long double test1l(long double x) long double test1l(long double x)
{ {
return logl(expl(x)); return logl(expl(x));
...@@ -143,4 +153,8 @@ long double test9l(long double x) ...@@ -143,4 +153,8 @@ long double test9l(long double x)
return fabsl(expl(x)); return fabsl(expl(x));
} }
long double test10l(long double x)
{
return tanl(atanl(x));
}
...@@ -30,6 +30,12 @@ int main() ...@@ -30,6 +30,12 @@ int main()
if (cos (0.0) != 1.0) if (cos (0.0) != 1.0)
link_error (); link_error ();
if (tan (0.0) != 0.0)
link_error ();
if (atan (0.0) != 0.0)
link_error ();
if (sqrtf (0.0f) != 0.0f) if (sqrtf (0.0f) != 0.0f)
link_error (); link_error ();
...@@ -49,6 +55,11 @@ int main() ...@@ -49,6 +55,11 @@ int main()
if (cosf (0.0f) != 1.0f) if (cosf (0.0f) != 1.0f)
link_error (); link_error ();
if (tanf (0.0f) != 0.0f)
link_error ();
if (atanf (0.0f) != 0.0f)
link_error ();
if (sqrtl (0.0l) != 0.0l) if (sqrtl (0.0l) != 0.0l)
link_error (); link_error ();
...@@ -68,6 +79,12 @@ int main() ...@@ -68,6 +79,12 @@ int main()
if (cosl (0.0l) != 1.0l) if (cosl (0.0l) != 1.0l)
link_error (); link_error ();
if (tanl (0.0l) != 0.0l)
link_error ();
if (atanl (0.0) != 0.0l)
link_error ();
return 0; return 0;
} }
...@@ -14,18 +14,24 @@ void test(double x) ...@@ -14,18 +14,24 @@ void test(double x)
{ {
if (pow (x, 1.0) != x) if (pow (x, 1.0) != x)
link_error (); link_error ();
if (tan (atan (x)) != x)
link_error ();
} }
void testf(float x) void testf(float x)
{ {
if (powf (x, 1.0f) != x) if (powf (x, 1.0f) != x)
link_error (); link_error ();
if (tanf (atanf (x)) != x)
link_error ();
} }
void testl(long double x) void testl(long double x)
{ {
if (powl (x, 1.0l) != x) if (powl (x, 1.0l) != x)
link_error (); link_error ();
if (tanl (atanl (x)) != x)
link_error ();
} }
int main() int main()
......
/* { 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment