diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2005-03-09 20:11:48 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2005-03-09 20:11:48 +0000 |
commit | d86dc3036d4ecd0432daad6a66dee219110cba5a (patch) | |
tree | dbef59a183a8241d0fee11d70432c971171cfd8a /gcc/builtins.c | |
parent | 41041fc2ac278ab937196aac357cfdb934a09473 (diff) | |
download | gcc-d86dc3036d4ecd0432daad6a66dee219110cba5a.zip gcc-d86dc3036d4ecd0432daad6a66dee219110cba5a.tar.gz gcc-d86dc3036d4ecd0432daad6a66dee219110cba5a.tar.bz2 |
builtins.c (fold_builtin_cbrt, [...]): Rearrange code.
* builtins.c (fold_builtin_cbrt, fold_builtin_pow): Rearrange
code. Add more cbrt transformations.
testsuite:
* gcc.dg/builtins-10.c: Reactivate disabled test.
* gcc.dg/torture/builtin-power-1.c: Likewise. Also add tests for
new cbrt transformations.
From-SVN: r96206
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 182 |
1 files changed, 121 insertions, 61 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 5d9aa77..b113d9f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6311,40 +6311,82 @@ fold_builtin_cbrt (tree arglist, tree type) if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg)) return arg; - /* Optimize cbrt(expN(x)) -> expN(x/3). */ - if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) - { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); - const REAL_VALUE_TYPE third_trunc = - real_value_truncate (TYPE_MODE (type), dconstthird); - arg = fold (build2 (MULT_EXPR, type, - TREE_VALUE (TREE_OPERAND (arg, 1)), - build_real (type, third_trunc))); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); - } - - /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ - /* We don't optimize cbrt(cbrt(x)) -> pow(x,1/9) because if - x is negative pow will error but cbrt won't. */ - if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode)) + if (flag_unsafe_math_optimizations) { - tree powfn = mathfn_built_in (type, BUILT_IN_POW); + /* Optimize cbrt(expN(x)) -> expN(x/3). */ + if (BUILTIN_EXPONENT_P (fcode)) + { + tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + const REAL_VALUE_TYPE third_trunc = + real_value_truncate (TYPE_MODE (type), dconstthird); + arg = fold (build2 (MULT_EXPR, type, + TREE_VALUE (TREE_OPERAND (arg, 1)), + build_real (type, third_trunc))); + arglist = build_tree_list (NULL_TREE, arg); + return build_function_call_expr (expfn, arglist); + } - if (powfn) - { - tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); - tree tree_root; - REAL_VALUE_TYPE dconstroot = dconstthird; + /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ + if (BUILTIN_SQRT_P (fcode)) + { + tree powfn = mathfn_built_in (type, BUILT_IN_POW); - SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); - dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); - tree_root = build_real (type, dconstroot); - arglist = tree_cons (NULL_TREE, arg0, - build_tree_list (NULL_TREE, tree_root)); - return build_function_call_expr (powfn, arglist); + if (powfn) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); + tree tree_root; + REAL_VALUE_TYPE dconstroot = dconstthird; + + SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); + dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); + tree_root = build_real (type, dconstroot); + arglist = tree_cons (NULL_TREE, arg0, + build_tree_list (NULL_TREE, tree_root)); + return build_function_call_expr (powfn, arglist); + } } + /* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */ + if (BUILTIN_CBRT_P (fcode)) + { + tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); + if (tree_expr_nonnegative_p (arg0)) + { + tree powfn = mathfn_built_in (type, BUILT_IN_POW); + + if (powfn) + { + tree tree_root; + REAL_VALUE_TYPE dconstroot; + + real_arithmetic (&dconstroot, MULT_EXPR, &dconstthird, &dconstthird); + dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); + tree_root = build_real (type, dconstroot); + arglist = tree_cons (NULL_TREE, arg0, + build_tree_list (NULL_TREE, tree_root)); + return build_function_call_expr (powfn, arglist); + } + } + } + + /* Optimize cbrt(pow(x,y)) -> pow(x,y/3) iff x is nonnegative. */ + if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF + || fcode == BUILT_IN_POWL) + { + tree arg00 = TREE_VALUE (TREE_OPERAND (arg, 1)); + tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1))); + if (tree_expr_nonnegative_p (arg00)) + { + tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); + const REAL_VALUE_TYPE dconstroot + = real_value_truncate (TYPE_MODE (type), dconstthird); + tree narg01 = fold (build2 (MULT_EXPR, type, arg01, + build_real (type, dconstroot))); + arglist = tree_cons (NULL_TREE, arg00, + build_tree_list (NULL_TREE, narg01)); + return build_function_call_expr (powfn, arglist); + } + } } return NULL_TREE; } @@ -6849,7 +6891,6 @@ fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value) static tree fold_builtin_pow (tree fndecl, tree arglist, tree type) { - enum built_in_function fcode; tree arg0 = TREE_VALUE (arglist); tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); @@ -6928,42 +6969,61 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) } } - /* Optimize pow(expN(x),y) = expN(x*y). */ - fcode = builtin_mathfn_code (arg0); - if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) + if (flag_unsafe_math_optimizations) { - tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); - tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); - arg = fold (build2 (MULT_EXPR, type, arg, arg1)); - arglist = build_tree_list (NULL_TREE, arg); - return build_function_call_expr (expfn, arglist); - } + const enum built_in_function fcode = builtin_mathfn_code (arg0); - /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ - if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode)) - { - tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1)); - tree narg1 = fold (build2 (MULT_EXPR, type, arg1, - build_real (type, dconsthalf))); + /* Optimize pow(expN(x),y) = expN(x*y). */ + if (BUILTIN_EXPONENT_P (fcode)) + { + tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); + tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); + arg = fold (build2 (MULT_EXPR, type, arg, arg1)); + arglist = build_tree_list (NULL_TREE, arg); + return build_function_call_expr (expfn, arglist); + } - arglist = tree_cons (NULL_TREE, narg0, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (fndecl, arglist); - } + /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ + if (BUILTIN_SQRT_P (fcode)) + { + tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1)); + tree narg1 = fold (build2 (MULT_EXPR, type, arg1, + build_real (type, dconsthalf))); - /* 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 (build2 (MULT_EXPR, type, arg01, arg1)); - arglist = tree_cons (NULL_TREE, arg00, - build_tree_list (NULL_TREE, narg1)); - return build_function_call_expr (fndecl, arglist); + arglist = tree_cons (NULL_TREE, narg0, + build_tree_list (NULL_TREE, narg1)); + return build_function_call_expr (fndecl, arglist); + } + + /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */ + if (BUILTIN_CBRT_P (fcode)) + { + tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); + if (tree_expr_nonnegative_p (arg)) + { + const REAL_VALUE_TYPE dconstroot + = real_value_truncate (TYPE_MODE (type), dconstthird); + tree narg1 = fold (build2 (MULT_EXPR, type, arg1, + build_real (type, dconstroot))); + arglist = tree_cons (NULL_TREE, arg, + build_tree_list (NULL_TREE, narg1)); + return build_function_call_expr (fndecl, arglist); + } + } + + /* Optimize pow(pow(x,y),z) = pow(x,y*z). */ + if (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 (build2 (MULT_EXPR, type, arg01, arg1)); + arglist = tree_cons (NULL_TREE, arg00, + build_tree_list (NULL_TREE, narg1)); + return build_function_call_expr (fndecl, arglist); + } } + return NULL_TREE; } |