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
This commit is contained in:
Roger Sayle 2003-06-04 12:20:40 +00:00 committed by Roger Sayle
parent 8c6a82695b
commit 385a9348eb
9 changed files with 258 additions and 2 deletions

View 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

View 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))

View 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.

View file

@ -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;
}

View file

@ -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;
}

View 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));
}

View 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;
}

View 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()

View file

@ -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);
}