aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-03-31 14:30:29 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-03-31 14:30:29 +0000
commit03f2ea93564390f4b0ca1b87f9e63ae07197a936 (patch)
treeae8fad7cd3fde47e1b9f8cb921dd6289d19b33cf /gcc/builtins.c
parent8c1e9e340ce4092e878a00b567637a55f735dd6d (diff)
downloadgcc-03f2ea93564390f4b0ca1b87f9e63ae07197a936.zip
gcc-03f2ea93564390f4b0ca1b87f9e63ae07197a936.tar.gz
gcc-03f2ea93564390f4b0ca1b87f9e63ae07197a936.tar.bz2
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
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c102
1 files changed, 95 insertions, 7 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b6fe4b4..d446185 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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;