Commit 4835c978 by Richard Sandiford Committed by Richard Sandiford

Move sqrt and cbrt simplifications to match.pd

This patch moves the sqrt and cbrt simplification rules to match.pd.
builtins.c now only does the constant folding.

Bootstrapped & regression-tested on x86_64-linux-gnu.

gcc/
	* builtins.c (fold_builtin_sqrt, fold_builtin_cbrt): Delete.
	(fold_builtin_1): Update accordingly.  Handle constant arguments here.
	* match.pd: Add rules previously handled by fold_builtin_sqrt
	and fold_builtin_cbrt.

gcc/testsuite/
	* gcc.dg/builtins-47.c: Test the optimized dump instead.

From-SVN: r228616
parent 68e57f04
2015-10-08 Richard Sandiford <richard.sandiford@arm.com>
* builtins.c (fold_builtin_sqrt, fold_builtin_cbrt): Delete.
(fold_builtin_1): Update accordingly. Handle constant arguments here.
* match.pd: Add rules previously handled by fold_builtin_sqrt
and fold_builtin_cbrt.
2015-10-08 Richard Sandiford <richard.sandiford@arm.com>
* params.def (PARAM_MAX_SSA_NAME_QUERY_DEPTH): New param.
* doc/invoke.texi (--param max-ssa-name-query-depth): Document.
* fold-const.h (tree_unary_nonnegative_warnv_p)
......@@ -158,8 +158,6 @@ static bool integer_valued_real_p (tree);
static tree fold_trunc_transparent_mathfn (location_t, tree, tree);
static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_signbit (tree, rtx);
static tree fold_builtin_sqrt (location_t, tree, tree);
static tree fold_builtin_cbrt (location_t, tree, tree);
static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
static tree fold_builtin_cos (location_t, tree, tree, tree);
......@@ -7706,145 +7704,6 @@ fold_builtin_cproj (location_t loc, tree arg, tree type)
return NULL_TREE;
}
/* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
Return NULL_TREE if no simplification can be made. */
static tree
fold_builtin_sqrt (location_t loc, tree arg, tree type)
{
enum built_in_function fcode;
tree res;
if (!validate_arg (arg, REAL_TYPE))
return NULL_TREE;
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_sqrt, &dconst0, NULL, true)))
return res;
/* Optimize sqrt(expN(x)) = expN(x*0.5). */
fcode = builtin_mathfn_code (arg);
if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
{
tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
arg = fold_build2_loc (loc, MULT_EXPR, type,
CALL_EXPR_ARG (arg, 0),
build_real (type, dconsthalf));
return build_call_expr_loc (loc, expfn, 1, arg);
}
/* Optimize sqrt(Nroot(x)) -> pow(x,1/(2*N)). */
if (flag_unsafe_math_optimizations && BUILTIN_ROOT_P (fcode))
{
tree powfn = mathfn_built_in (type, BUILT_IN_POW);
if (powfn)
{
tree arg0 = CALL_EXPR_ARG (arg, 0);
tree arg1 = (BUILTIN_SQRT_P (fcode)
? build_real (type, dconst_quarter ())
: build_real_truncate (type, dconst_sixth ()));
return build_call_expr_loc (loc, powfn, 2, arg0, arg1);
}
}
/* 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 (CALL_EXPR_FN (arg), 0);
tree arg0 = CALL_EXPR_ARG (arg, 0);
tree arg1 = CALL_EXPR_ARG (arg, 1);
tree narg1;
if (!tree_expr_nonnegative_p (arg0))
arg0 = build1 (ABS_EXPR, type, arg0);
narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg1,
build_real (type, dconsthalf));
return build_call_expr_loc (loc, powfn, 2, arg0, narg1);
}
return NULL_TREE;
}
/* Fold a builtin function call to cbrt, cbrtf, or cbrtl with argument ARG.
Return NULL_TREE if no simplification can be made. */
static tree
fold_builtin_cbrt (location_t loc, tree arg, tree type)
{
const enum built_in_function fcode = builtin_mathfn_code (arg);
tree res;
if (!validate_arg (arg, REAL_TYPE))
return NULL_TREE;
/* Calculate the result when the argument is a constant. */
if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0)))
return res;
if (flag_unsafe_math_optimizations)
{
/* Optimize cbrt(expN(x)) -> expN(x/3). */
if (BUILTIN_EXPONENT_P (fcode))
{
tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
arg = fold_build2_loc (loc, MULT_EXPR, type,
CALL_EXPR_ARG (arg, 0),
build_real_truncate (type, dconst_third ()));
return build_call_expr_loc (loc, expfn, 1, arg);
}
/* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
if (BUILTIN_SQRT_P (fcode))
{
tree powfn = mathfn_built_in (type, BUILT_IN_POW);
if (powfn)
{
tree arg0 = CALL_EXPR_ARG (arg, 0);
tree tree_root = build_real_truncate (type, dconst_sixth ());
return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
}
}
/* Optimize cbrt(cbrt(x)) -> pow(x,1/9) iff x is nonnegative. */
if (BUILTIN_CBRT_P (fcode))
{
tree arg0 = CALL_EXPR_ARG (arg, 0);
if (tree_expr_nonnegative_p (arg0))
{
tree powfn = mathfn_built_in (type, BUILT_IN_POW);
if (powfn)
{
tree tree_root = build_real_truncate (type, dconst_ninth ());
return build_call_expr_loc (loc, powfn, 2, arg0, tree_root);
}
}
}
/* 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 = CALL_EXPR_ARG (arg, 0);
tree arg01 = CALL_EXPR_ARG (arg, 1);
if (tree_expr_nonnegative_p (arg00))
{
tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg), 0);
tree c = build_real_truncate (type, dconst_third ());
tree narg01 = fold_build2_loc (loc, MULT_EXPR, type, arg01, c);
return build_call_expr_loc (loc, powfn, 2, arg00, narg01);
}
}
}
return NULL_TREE;
}
/* Fold function call to builtin cos, cosf, or cosl with argument ARG.
TYPE is the type of the return value. Return NULL_TREE if no
simplification can be made. */
......@@ -9940,10 +9799,14 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
return fold_builtin_carg (loc, arg0, type);
CASE_FLT_FN (BUILT_IN_SQRT):
return fold_builtin_sqrt (loc, arg0, type);
if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_sqrt, &dconst0, NULL, true);
break;
CASE_FLT_FN (BUILT_IN_CBRT):
return fold_builtin_cbrt (loc, arg0, type);
if (validate_arg (arg0, REAL_TYPE))
return do_mpfr_arg1 (arg0, type, mpfr_cbrt, NULL, NULL, 0);
break;
CASE_FLT_FN (BUILT_IN_ASIN):
if (validate_arg (arg0, REAL_TYPE))
......
......@@ -2309,3 +2309,44 @@ along with GCC; see the file COPYING3. If not see
(with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
(convert (bit_and (op (convert:utype @0) (convert:utype @1))
(convert:utype @4))))))))
(if (flag_unsafe_math_optimizations)
(for sqrts (SQRT)
cbrts (CBRT)
exps (EXP EXP2 EXP10 POW10)
/* sqrt(expN(x)) -> expN(x*0.5). */
(simplify
(sqrts (exps @0))
(exps (mult @0 { build_real (type, dconsthalf); })))
/* cbrt(expN(x)) -> expN(x/3). */
(simplify
(cbrts (exps @0))
(exps (mult @0 { build_real_truncate (type, dconst_third ()); }))))
(for sqrts (SQRT)
cbrts (CBRT)
pows (POW)
/* sqrt(sqrt(x)) -> pow(x,1/4). */
(simplify
(sqrts (sqrts @0))
(pows @0 { build_real (type, dconst_quarter ()); }))
/* sqrt(cbrt(x)) -> pow(x,1/6). */
(simplify
(sqrts (cbrts @0))
(pows @0 { build_real_truncate (type, dconst_sixth ()); }))
/* cbrt(sqrt(x)) -> pow(x,1/6). */
(simplify
(cbrts (sqrts @0))
(pows @0 { build_real_truncate (type, dconst_sixth ()); }))
/* cbrt(cbrt(x)) -> pow(x,1/9), iff x is nonnegative. */
(simplify
(cbrts (cbrts tree_expr_nonnegative_p@0))
(pows @0 { build_real_truncate (type, dconst_ninth ()); }))
/* sqrt(pow(x,y)) -> pow(|x|,y*0.5). */
(simplify
(sqrts (pows @0 @1))
(pows (abs @0) (mult @1 { build_real (type, dconsthalf); })))
/* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative. */
(simplify
(cbrts (pows tree_expr_nonnegative_p@0 @1))
(pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))))
2015-10-08 Richard Sandiford <richard.sandiford@arm.com>
* gcc.dg/builtins-47.c: Test the optimized dump instead.
2015-10-08 Yuri Rumyantsev <ysrumyan@gmail.com>
* gcc.dg/vect/vect-outer-simd-3.c: New test.
......
/* { dg-do run } */
/* { dg-options "-O -ffast-math -fdump-tree-gimple" } */
/* { dg-options "-O -ffast-math -fdump-tree-optimized" } */
extern double sqrt (double);
extern double pow (double, double);
......@@ -15,5 +15,5 @@ int main ()
return 0;
}
/* { dg-final { scan-tree-dump-times "sqrt" 0 "gimple" } } */
/* { dg-final { scan-tree-dump-times "pow" 0 "gimple" } } */
/* { dg-final { scan-tree-dump-times "sqrt" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "pow" 0 "optimized" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment