diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-04-08 23:24:38 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-04-08 23:24:38 +0000 |
commit | 531878a68e636392d594f22d0fc6e1444e82d940 (patch) | |
tree | 57e664d9c1807ff9f4b3bd4f3e4ddbb0c32619d0 /gcc/builtins.c | |
parent | c583e7c354b04607db93798fc92e040f11a60a54 (diff) | |
download | gcc-531878a68e636392d594f22d0fc6e1444e82d940.zip gcc-531878a68e636392d594f22d0fc6e1444e82d940.tar.gz gcc-531878a68e636392d594f22d0fc6e1444e82d940.tar.bz2 |
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
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index d446185..ee2d579 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; |