aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-04-08 23:24:38 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-04-08 23:24:38 +0000
commit531878a68e636392d594f22d0fc6e1444e82d940 (patch)
tree57e664d9c1807ff9f4b3bd4f3e4ddbb0c32619d0 /gcc/builtins.c
parentc583e7c354b04607db93798fc92e040f11a60a54 (diff)
downloadgcc-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.c91
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;