builtins.c (fold_builtin): Constant fold expressions as x*0.5 instead of x/2.0.
* builtins.c (fold_builtin): Constant fold expressions as x*0.5 instead of x/2.0. Optimize sqrt(pow(x,y)) as pow(x,y*0.5), log(pow(x,y)) as y*log(x), pow(exp(x),y) as exp(x*y), pow(sqrt(x),y) as pow(x,y*0.5) and pow(pow(x,y),z) as pow(x,y*z). Delete function scope "fcode" variable to avoid shadowing. * gcc.dg/builtins-9.c: New test case. * gcc.dg/builtins-10.c: New test case. From-SVN: r65386
This commit is contained in:
parent
c583e7c354
commit
531878a68e
5 changed files with 253 additions and 8 deletions
|
@ -1,3 +1,11 @@
|
|||
2003-04-08 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* builtins.c (fold_builtin): Constant fold expressions as x*0.5
|
||||
instead of x/2.0. Optimize sqrt(pow(x,y)) as pow(x,y*0.5),
|
||||
log(pow(x,y)) as y*log(x), pow(exp(x),y) as exp(x*y),
|
||||
pow(sqrt(x),y) as pow(x,y*0.5) and pow(pow(x,y),z) as pow(x,y*z).
|
||||
Delete function scope "fcode" variable to avoid shadowing.
|
||||
|
||||
2003-04-08 Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
* dwarf2out.c (DWARF_ARANGES_HEADER_SIZE, DWARF_ARANGES_PAD_SIZE):
|
||||
|
|
|
@ -4686,12 +4686,11 @@ fold_builtin (exp)
|
|||
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
||||
tree arglist = TREE_OPERAND (exp, 1);
|
||||
tree type = TREE_TYPE (TREE_TYPE (fndecl));
|
||||
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
|
||||
|
||||
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
|
||||
return 0;
|
||||
|
||||
switch (fcode)
|
||||
switch (DECL_FUNCTION_CODE (fndecl))
|
||||
{
|
||||
case BUILT_IN_CONSTANT_P:
|
||||
return fold_builtin_constant_p (arglist);
|
||||
|
@ -4735,7 +4734,7 @@ fold_builtin (exp)
|
|||
return build_real (type, r);
|
||||
}
|
||||
|
||||
/* Optimize sqrt(exp(x)) = exp(x/2.0). */
|
||||
/* Optimize sqrt(exp(x)) = exp(x*0.5). */
|
||||
fcode = builtin_mathfn_code (arg);
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_EXP
|
||||
|
@ -4743,12 +4742,28 @@ fold_builtin (exp)
|
|||
|| fcode == BUILT_IN_EXPL))
|
||||
{
|
||||
tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
|
||||
arg = fold (build (RDIV_EXPR, type,
|
||||
arg = fold (build (MULT_EXPR, type,
|
||||
TREE_VALUE (TREE_OPERAND (arg, 1)),
|
||||
build_real (type, dconst2)));
|
||||
build_real (type, dconsthalf)));
|
||||
arglist = build_tree_list (NULL_TREE, arg);
|
||||
return build_function_call_expr (expfn, arglist);
|
||||
}
|
||||
|
||||
/* Optimize sqrt(pow(x,y)) = pow(x,y*0.5). */
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_POW
|
||||
|| fcode == BUILT_IN_POWF
|
||||
|| fcode == BUILT_IN_POWL))
|
||||
{
|
||||
tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
|
||||
tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
|
||||
tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
|
||||
tree narg1 = fold (build (MULT_EXPR, type, arg1,
|
||||
build_real (type, dconsthalf)));
|
||||
arglist = tree_cons (NULL_TREE, arg0,
|
||||
build_tree_list (NULL_TREE, narg1));
|
||||
return build_function_call_expr (powfn, arglist);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4820,7 +4835,7 @@ fold_builtin (exp)
|
|||
|| fcode == BUILT_IN_EXPL))
|
||||
return TREE_VALUE (TREE_OPERAND (arg, 1));
|
||||
|
||||
/* Optimize log(sqrt(x)) = log(x)/2.0. */
|
||||
/* Optimize log(sqrt(x)) = log(x)*0.5. */
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_SQRT
|
||||
|| fcode == BUILT_IN_SQRTF
|
||||
|
@ -4828,8 +4843,23 @@ fold_builtin (exp)
|
|||
{
|
||||
tree logfn = build_function_call_expr (fndecl,
|
||||
TREE_OPERAND (arg, 1));
|
||||
return fold (build (RDIV_EXPR, type, logfn,
|
||||
build_real (type, dconst2)));
|
||||
return fold (build (MULT_EXPR, type, logfn,
|
||||
build_real (type, dconsthalf)));
|
||||
}
|
||||
|
||||
/* Optimize log(pow(x,y)) = y*log(x). */
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_POW
|
||||
|| fcode == BUILT_IN_POWF
|
||||
|| fcode == BUILT_IN_POWL))
|
||||
{
|
||||
tree arg0, arg1, logfn;
|
||||
|
||||
arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
|
||||
arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
|
||||
arglist = build_tree_list (NULL_TREE, arg0);
|
||||
logfn = build_function_call_expr (fndecl, arglist);
|
||||
return fold (build (MULT_EXPR, type, arg1, logfn));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -4839,6 +4869,7 @@ fold_builtin (exp)
|
|||
case BUILT_IN_POWL:
|
||||
if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
|
||||
{
|
||||
enum built_in_function fcode;
|
||||
tree arg0 = TREE_VALUE (arglist);
|
||||
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
|
||||
|
@ -4895,6 +4926,7 @@ fold_builtin (exp)
|
|||
{
|
||||
tree sqrtfn;
|
||||
|
||||
fcode = DECL_FUNCTION_CODE (fndecl);
|
||||
if (fcode == BUILT_IN_POW)
|
||||
sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
|
||||
else if (fcode == BUILT_IN_POWF)
|
||||
|
@ -4911,6 +4943,49 @@ fold_builtin (exp)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Optimize pow(exp(x),y) = exp(x*y). */
|
||||
fcode = builtin_mathfn_code (arg0);
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_EXP
|
||||
|| fcode == BUILT_IN_EXPF
|
||||
|| fcode == BUILT_IN_EXPL))
|
||||
{
|
||||
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
|
||||
tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
arg = fold (build (MULT_EXPR, type, arg, arg1));
|
||||
arglist = build_tree_list (NULL_TREE, arg);
|
||||
return build_function_call_expr (expfn, arglist);
|
||||
}
|
||||
|
||||
/* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_SQRT
|
||||
|| fcode == BUILT_IN_SQRTF
|
||||
|| fcode == BUILT_IN_SQRTL))
|
||||
{
|
||||
tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
tree narg1 = fold (build (MULT_EXPR, type, arg1,
|
||||
build_real (type, dconsthalf)));
|
||||
|
||||
arglist = tree_cons (NULL_TREE, narg0,
|
||||
build_tree_list (NULL_TREE, narg1));
|
||||
return build_function_call_expr (fndecl, arglist);
|
||||
}
|
||||
|
||||
/* Optimize pow(pow(x,y),z) = pow(x,y*z). */
|
||||
if (flag_unsafe_math_optimizations
|
||||
&& (fcode == BUILT_IN_POW
|
||||
|| fcode == BUILT_IN_POWF
|
||||
|| fcode == BUILT_IN_POWL))
|
||||
{
|
||||
tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
|
||||
tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
|
||||
arglist = tree_cons (NULL_TREE, arg00,
|
||||
build_tree_list (NULL_TREE, narg1));
|
||||
return build_function_call_expr (fndecl, arglist);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2003-04-08 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/builtins-9.c: New test case.
|
||||
* gcc.dg/builtins-10.c: New test case.
|
||||
|
||||
2003-04-07 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* gcc.dg/noncompile/init-4.c.c: New test.
|
||||
|
|
54
gcc/testsuite/gcc.dg/builtins-10.c
Normal file
54
gcc/testsuite/gcc.dg/builtins-10.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* 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, 2nd April 2003. */
|
||||
|
||||
/* { dg-do link } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern void link_error(void);
|
||||
|
||||
extern double exp(double);
|
||||
extern double log(double);
|
||||
extern double sqrt(double);
|
||||
extern double pow(double,double);
|
||||
|
||||
void test(double x)
|
||||
{
|
||||
if (sqrt(pow(x,4.0)) != x*x)
|
||||
link_error ();
|
||||
|
||||
if (pow(sqrt(x),4.0) != x*x)
|
||||
link_error ();
|
||||
|
||||
if (pow(pow(x,4.0),0.25) != x)
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test2(double x, double y, double z)
|
||||
{
|
||||
if (sqrt(pow(x,y)) != pow(x,y*0.5))
|
||||
link_error ();
|
||||
|
||||
if (log(pow(x,y)) != y*log(x))
|
||||
link_error ();
|
||||
|
||||
if (pow(exp(x),y) != exp(x*y))
|
||||
link_error ();
|
||||
|
||||
if (pow(sqrt(x),y) != pow(x,y*0.5))
|
||||
link_error ();
|
||||
|
||||
if (pow(pow(x,y),z) != pow(x,y*z))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test (2.0);
|
||||
test2 (2.0, 3.0, 4.0);
|
||||
return 0;
|
||||
}
|
||||
|
103
gcc/testsuite/gcc.dg/builtins-9.c
Normal file
103
gcc/testsuite/gcc.dg/builtins-9.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Check that constant folding of built-in math functions doesn't
|
||||
break anything.
|
||||
|
||||
Written by Roger Sayle, 2nd April 2003. */
|
||||
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern double log(double);
|
||||
extern double exp(double);
|
||||
extern double sqrt(double);
|
||||
extern double pow(double,double);
|
||||
|
||||
extern float logf(float);
|
||||
extern float expf(float);
|
||||
extern float sqrtf(float);
|
||||
extern float powf(float,float);
|
||||
|
||||
extern long double logl(long double);
|
||||
extern long double expl(long double);
|
||||
extern long double sqrtl(long double);
|
||||
extern long double powl(long double,long double);
|
||||
|
||||
|
||||
double test1(double x, double y)
|
||||
{
|
||||
return log(pow(x,y));
|
||||
}
|
||||
|
||||
double test2(double x, double y)
|
||||
{
|
||||
return sqrt(pow(x,y));
|
||||
}
|
||||
|
||||
double test3(double x, double y)
|
||||
{
|
||||
return pow(exp(x),y);
|
||||
}
|
||||
|
||||
double test4(double x, double y)
|
||||
{
|
||||
return pow(sqrt(x),y);
|
||||
}
|
||||
|
||||
double test5(double x, double y, double z)
|
||||
{
|
||||
return pow(pow(x,y),z);
|
||||
}
|
||||
|
||||
|
||||
float test1f(float x, float y)
|
||||
{
|
||||
return logf(powf(x,y));
|
||||
}
|
||||
|
||||
float test2f(float x, float y)
|
||||
{
|
||||
return sqrtf(powf(x,y));
|
||||
}
|
||||
|
||||
float test3f(float x, float y)
|
||||
{
|
||||
return powf(expf(x),y);
|
||||
}
|
||||
|
||||
float test4f(float x, float y)
|
||||
{
|
||||
return powf(sqrtf(x),y);
|
||||
}
|
||||
|
||||
float test5f(float x, float y, float z)
|
||||
{
|
||||
return powf(powf(x,y),z);
|
||||
}
|
||||
|
||||
|
||||
long double test1l(long double x, long double y)
|
||||
{
|
||||
return logl(powl(x,y));
|
||||
}
|
||||
|
||||
long double test2l(long double x, long double y)
|
||||
{
|
||||
return sqrtl(powl(x,y));
|
||||
}
|
||||
|
||||
long double test3l(long double x, long double y)
|
||||
{
|
||||
return powl(expl(x),y);
|
||||
}
|
||||
|
||||
long double test4l(long double x, long double y)
|
||||
{
|
||||
return powl(sqrtl(x),y);
|
||||
}
|
||||
|
||||
long double test5l(long double x, long double y, long double z)
|
||||
{
|
||||
return powl(powl(x,y),z);
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue