Commit 03f2ea93 by Roger Sayle Committed by Roger Sayle

emit-rtl.c (dconstm2, dconsthalf): New real constants.


	* emit-rtl.c (dconstm2, dconsthalf): New real constants.
	(init_emit_once): Initialize dconstm2 and dconsthalf here.
	* real.h (dconstm2, dconsthalf): Add prototypes here.
	* real.c (real_sqrt): Use dconsthalf rather than local copy.
	* builtins.c (fold_builtin): When optimizing sqrt(exp(x)) as
	exp(x/2.0) remember to fold the division if possible.
	Fold sin(0.0) as 0.0, cos(0.0) as 1.0, pow(x,1.0) as x,
	pow(x,-1.0) as 1.0/x, pow(x,2.0) as x*x, pow(x,-2.0) as
	1.0/(x*x) and pow(x,0.5) as sqrt(x).

	* gcc.dg/builtins-3.c: Add new tests for sin and cos.
	* gcc.dg/builtins-7.c: New test case.
	* gcc.dg/builtins-8.c: New test case.

From-SVN: r65088
parent 8c1e9e34
2003-03-31 Roger Sayle <roger@eyesopen.com>
* emit-rtl.c (dconstm2, dconsthalf): New real constants.
(init_emit_once): Initialize dconstm2 and dconsthalf here.
* real.h (dconstm2, dconsthalf): Add prototypes here.
* real.c (real_sqrt): Use dconsthalf rather than local copy.
* builtins.c (fold_builtin): When optimizing sqrt(exp(x)) as
exp(x/2.0) remember to fold the division if possible.
Fold sin(0.0) as 0.0, cos(0.0) as 1.0, pow(x,1.0) as x,
pow(x,-1.0) as 1.0/x, pow(x,2.0) as x*x, pow(x,-2.0) as
1.0/(x*x) and pow(x,0.5) as sqrt(x).
2003-03-31 Kazu Hirata <kazu@cs.umass.edu>
* config/h8300/h8300.md (a new peephole2): New.
......
......@@ -4743,15 +4743,41 @@ fold_builtin (exp)
|| fcode == BUILT_IN_EXPL))
{
tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
arg = build (RDIV_EXPR, type,
TREE_VALUE (TREE_OPERAND (arg, 1)),
build_real (type, dconst2));
arg = fold (build (RDIV_EXPR, type,
TREE_VALUE (TREE_OPERAND (arg, 1)),
build_real (type, dconst2)));
arglist = build_tree_list (NULL_TREE, arg);
return build_function_call_expr (expfn, arglist);
}
}
break;
case BUILT_IN_SIN:
case BUILT_IN_SINF:
case BUILT_IN_SINL:
if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
{
tree arg = TREE_VALUE (arglist);
/* Optimize sin(0.0) = 0.0. */
if (real_zerop (arg))
return build_real (type, dconst0);
}
break;
case BUILT_IN_COS:
case BUILT_IN_COSF:
case BUILT_IN_COSL:
if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
{
tree arg = TREE_VALUE (arglist);
/* Optimize cos(0.0) = 1.0. */
if (real_zerop (arg))
return build_real (type, dconst1);
}
break;
case BUILT_IN_EXP:
case BUILT_IN_EXPF:
case BUILT_IN_EXPL:
......@@ -4816,13 +4842,75 @@ fold_builtin (exp)
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
/* Optimize pow(x,0.0) = 1.0. */
if (real_zerop (arg1))
return omit_one_operand (type, build_real (type, dconst1), arg0);
/* Optimize pow(1.0,y) = 1.0. */
if (real_onep (arg0))
return omit_one_operand (type, build_real (type, dconst1), arg1);
if (TREE_CODE (arg1) == REAL_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1))
{
REAL_VALUE_TYPE c;
c = TREE_REAL_CST (arg1);
/* Optimize pow(x,0.0) = 1.0. */
if (REAL_VALUES_EQUAL (c, dconst0))
return omit_one_operand (type, build_real (type, dconst1),
arg0);
/* Optimize pow(x,1.0) = x. */
if (REAL_VALUES_EQUAL (c, dconst1))
return arg0;
/* Optimize pow(x,-1.0) = 1.0/x. */
if (REAL_VALUES_EQUAL (c, dconstm1))
return fold (build (RDIV_EXPR, type,
build_real (type, dconst1),
arg0));
/* Optimize pow(x,2.0) = x*x. */
if (REAL_VALUES_EQUAL (c, dconst2)
&& (*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (arg0))
{
arg0 = save_expr (arg0);
return fold (build (MULT_EXPR, type, arg0, arg0));
}
/* Optimize pow(x,-2.0) = 1.0/(x*x). */
if (flag_unsafe_math_optimizations
&& REAL_VALUES_EQUAL (c, dconstm2)
&& (*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (arg0))
{
arg0 = save_expr (arg0);
return fold (build (RDIV_EXPR, type,
build_real (type, dconst1),
fold (build (MULT_EXPR, type,
arg0, arg0))));
}
/* Optimize pow(x,0.5) = sqrt(x). */
if (flag_unsafe_math_optimizations
&& REAL_VALUES_EQUAL (c, dconsthalf))
{
tree sqrtfn;
if (fcode == BUILT_IN_POW)
sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
else if (fcode == BUILT_IN_POWF)
sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
else if (fcode == BUILT_IN_POWL)
sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
else
sqrtfn = NULL_TREE;
if (sqrtfn != NULL_TREE)
{
tree arglist = build_tree_list (NULL_TREE, arg0);
return build_function_call_expr (sqrtfn, arglist);
}
}
}
}
break;
......
......@@ -111,6 +111,8 @@ REAL_VALUE_TYPE dconst0;
REAL_VALUE_TYPE dconst1;
REAL_VALUE_TYPE dconst2;
REAL_VALUE_TYPE dconstm1;
REAL_VALUE_TYPE dconstm2;
REAL_VALUE_TYPE dconsthalf;
/* All references to the following fixed hard registers go through
these unique rtl objects. On machines where the frame-pointer and
......@@ -5552,6 +5554,10 @@ init_emit_once (line_numbers)
REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode);
REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode);
REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
dconsthalf = dconst1;
dconsthalf.exp--;
for (i = 0; i <= 2; i++)
{
......
......@@ -4423,7 +4423,6 @@ real_sqrt (r, mode, x)
const REAL_VALUE_TYPE *x;
{
static REAL_VALUE_TYPE halfthree;
static REAL_VALUE_TYPE half;
static bool init = false;
REAL_VALUE_TYPE h, t, i;
int iter, exp;
......@@ -4452,8 +4451,7 @@ real_sqrt (r, mode, x)
if (!init)
{
real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2);
real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half);
real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &dconsthalf);
init = true;
}
......@@ -4467,7 +4465,7 @@ real_sqrt (r, mode, x)
/* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x). */
real_arithmetic (&t, MULT_EXPR, x, &i);
real_arithmetic (&h, MULT_EXPR, &t, &i);
real_arithmetic (&t, MULT_EXPR, &h, &half);
real_arithmetic (&t, MULT_EXPR, &h, &dconsthalf);
real_arithmetic (&h, MINUS_EXPR, &halfthree, &t);
real_arithmetic (&t, MULT_EXPR, &i, &h);
......@@ -4484,7 +4482,7 @@ real_sqrt (r, mode, x)
real_arithmetic (&h, MULT_EXPR, &t, &i);
real_arithmetic (&i, MINUS_EXPR, &dconst1, &h);
real_arithmetic (&h, MULT_EXPR, &t, &i);
real_arithmetic (&i, MULT_EXPR, &half, &h);
real_arithmetic (&i, MULT_EXPR, &dconsthalf, &h);
real_arithmetic (&h, PLUS_EXPR, &t, &i);
/* ??? We need a Tuckerman test to get the last bit. */
......
......@@ -322,12 +322,14 @@ extern void real_ldexp PARAMS ((REAL_VALUE_TYPE *,
/* **** End of software floating point emulator interface macros **** */
/* Constant real values 0, 1, 2, and -1. */
/* Constant real values 0, 1, 2, -1, -2 and 0.5. */
extern REAL_VALUE_TYPE dconst0;
extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
extern REAL_VALUE_TYPE dconstm2;
extern REAL_VALUE_TYPE dconsthalf;
/* Function to return a real value (not a tree node)
from a given integer constant. */
......
2003-03-31 Roger Sayle <roger@eyesopen.com>
* gcc.dg/builtins-3.c: Add new tests for sin and cos.
* gcc.dg/builtins-7.c: New test case.
* gcc.dg/builtins-8.c: New test case.
2003-03-31 Richard Sandiford <rsandifo@redhat.com>
* gcc.c-torture/execute/ieee/20030331-1.c: New test.
......
/* Copyright (C) 2002 Free Software Foundation.
/* Copyright (C) 2002, 2003 Free Software Foundation.
Verify that built-in math function constant folding of constant
arguments is correctly performed by the by the compiler.
arguments is correctly performed by the compiler.
Written by Roger Sayle, 16th August 2002. */
......@@ -24,6 +24,12 @@ int main()
if (log (1.0) != 0.0)
link_error ();
if (sin (0.0) != 0.0)
link_error ();
if (cos (0.0) != 1.0)
link_error ();
if (sqrtf (0.0f) != 0.0f)
link_error ();
......@@ -37,6 +43,12 @@ int main()
if (logf (1.0f) != 0.0f)
link_error ();
if (sinf (0.0f) != 0.0f)
link_error ();
if (cosf (0.0f) != 1.0f)
link_error ();
if (sqrtl (0.0l) != 0.0l)
link_error ();
......@@ -50,6 +62,12 @@ int main()
if (logl (1.0l) != 0.0l)
link_error ();
if (sinl (0.0l) != 0.0l)
link_error ();
if (cosl (0.0l) != 1.0l)
link_error ();
return 0;
}
/* Copyright (C) 2003 Free Software Foundation.
Verify that built-in math function constant folding of constant
arguments is correctly performed by the by the compiler.
Written by Roger Sayle, 30th March 2003. */
/* { dg-do link } */
/* { dg-options "-O2 -ffast-math" } */
extern void link_error(void);
void test(double x)
{
if (pow (x, 1.0) != x)
link_error ();
}
void testf(float x)
{
if (powf (x, 1.0f) != x)
link_error ();
}
void testl(long double x)
{
if (powl (x, 1.0l) != x)
link_error ();
}
int main()
{
test (2.0);
testf (2.0f);
testl (2.0l);
return 0;
}
/* Copyright (C) 2003 Free Software Foundation.
Verify that built-in math function constant folding of functions
with one constant argument is correctly performed by the compiler.
Written by Roger Sayle, 30th March 2003. */
/* { dg-do run } */
/* { dg-options "-O2 -ffast-math" } */
extern void abort(void);
void test(double x)
{
if (pow(x,-1.0) != 1.0/x)
abort ();
if (pow(x,2.0) != x*x)
abort ();
if (pow(x,-2.0) != 1.0/(x*x))
abort ();
if (pow(x,0.5) != sqrt(x))
abort ();
}
int main()
{
test (1.0);
test (2.0);
return 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