diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-04-08 23:24:38 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-04-08 23:24:38 +0000 |
commit | 2643011aed8692ce128b0bc8f78ad03d1a5661d3 (patch) | |
tree | 57e664d9c1807ff9f4b3bd4f3e4ddbb0c32619d0 | |
parent | 38c416603c656090e4f9a69b0a1450728aa247b8 (diff) | |
download | gcc-2643011aed8692ce128b0bc8f78ad03d1a5661d3.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65386 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/builtins.c | 91 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-10.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-9.c | 103 |
5 files changed, 253 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dfd76308111..20134695c3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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): diff --git a/gcc/builtins.c b/gcc/builtins.c index d446185c8c5..ee2d57990d4 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 256bfc544a1..09890c71bea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/builtins-10.c b/gcc/testsuite/gcc.dg/builtins-10.c new file mode 100644 index 00000000000..9e5a4583fc3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-10.c @@ -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; +} + diff --git a/gcc/testsuite/gcc.dg/builtins-9.c b/gcc/testsuite/gcc.dg/builtins-9.c new file mode 100644 index 00000000000..108e0d2f11e --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-9.c @@ -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); +} + |