diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-03-31 14:30:29 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-03-31 14:30:29 +0000 |
commit | 03f2ea93564390f4b0ca1b87f9e63ae07197a936 (patch) | |
tree | ae8fad7cd3fde47e1b9f8cb921dd6289d19b33cf /gcc/builtins.c | |
parent | 8c1e9e340ce4092e878a00b567637a55f735dd6d (diff) | |
download | gcc-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.c | 102 |
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; |