Commit d86dc303 by Kaveh R. Ghazi Committed by Kaveh Ghazi

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
parent 41041fc2
2005-03-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2005-03-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (fold_builtin_cbrt, fold_builtin_pow): Rearrange
code. Add more cbrt transformations.
2005-03-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* fold-const.c (fold_unary_to_constant): Add FIX_ROUND_EXPR case. * fold-const.c (fold_unary_to_constant): Add FIX_ROUND_EXPR case.
2005-03-09 Kazu Hirata <kazu@cs.umass.edu> 2005-03-09 Kazu Hirata <kazu@cs.umass.edu>
......
...@@ -6311,40 +6311,82 @@ fold_builtin_cbrt (tree arglist, tree type) ...@@ -6311,40 +6311,82 @@ fold_builtin_cbrt (tree arglist, tree type)
if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg)) if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg))
return arg; return arg;
/* Optimize cbrt(expN(x)) -> expN(x/3). */ if (flag_unsafe_math_optimizations)
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))
{ {
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) /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
{ if (BUILTIN_SQRT_P (fcode))
tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1)); {
tree tree_root; tree powfn = mathfn_built_in (type, BUILT_IN_POW);
REAL_VALUE_TYPE dconstroot = dconstthird;
SET_REAL_EXP (&dconstroot, REAL_EXP (&dconstroot) - 1); if (powfn)
dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); {
tree_root = build_real (type, dconstroot); tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
arglist = tree_cons (NULL_TREE, arg0, tree tree_root;
build_tree_list (NULL_TREE, tree_root)); REAL_VALUE_TYPE dconstroot = dconstthird;
return build_function_call_expr (powfn, arglist);
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; return NULL_TREE;
} }
...@@ -6849,7 +6891,6 @@ fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value) ...@@ -6849,7 +6891,6 @@ fold_builtin_logarithm (tree exp, const REAL_VALUE_TYPE *value)
static tree static tree
fold_builtin_pow (tree fndecl, tree arglist, tree type) fold_builtin_pow (tree fndecl, tree arglist, tree type)
{ {
enum built_in_function fcode;
tree arg0 = TREE_VALUE (arglist); tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
...@@ -6928,42 +6969,61 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) ...@@ -6928,42 +6969,61 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
} }
} }
/* Optimize pow(expN(x),y) = expN(x*y). */ if (flag_unsafe_math_optimizations)
fcode = builtin_mathfn_code (arg0);
if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
{ {
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); const enum built_in_function fcode = builtin_mathfn_code (arg0);
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);
}
/* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ /* Optimize pow(expN(x),y) = expN(x*y). */
if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode)) if (BUILTIN_EXPONENT_P (fcode))
{ {
tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1)); tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
tree narg1 = fold (build2 (MULT_EXPR, type, arg1, tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
build_real (type, dconsthalf))); 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, /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
build_tree_list (NULL_TREE, narg1)); if (BUILTIN_SQRT_P (fcode))
return build_function_call_expr (fndecl, arglist); {
} 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). */ arglist = tree_cons (NULL_TREE, narg0,
if (flag_unsafe_math_optimizations build_tree_list (NULL_TREE, narg1));
&& (fcode == BUILT_IN_POW return build_function_call_expr (fndecl, arglist);
|| fcode == BUILT_IN_POWF }
|| fcode == BUILT_IN_POWL))
{ /* Optimize pow(cbrt(x),y) = pow(x,y/3) iff x is nonnegative. */
tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); if (BUILTIN_CBRT_P (fcode))
tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1))); {
tree narg1 = fold (build2 (MULT_EXPR, type, arg01, arg1)); tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
arglist = tree_cons (NULL_TREE, arg00, if (tree_expr_nonnegative_p (arg))
build_tree_list (NULL_TREE, narg1)); {
return build_function_call_expr (fndecl, arglist); 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; return NULL_TREE;
} }
......
2005-03-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/builtins-10.c: Reactivate disabled test.
* gcc.dg/torture/builtin-power-1.c: Likewise. Also add tests for
new cbrt transformations.
2005-03-09 Mark Mitchell <mark@codesourcery.com> 2005-03-09 Mark Mitchell <mark@codesourcery.com>
PR c++/20208 PR c++/20208
......
...@@ -18,8 +18,8 @@ extern double fabs(double); ...@@ -18,8 +18,8 @@ extern double fabs(double);
void test(double x) void test(double x)
{ {
/*if (sqrt(pow(x,4.0)) != x*x) if (sqrt(pow(x,4.0)) != x*x)
link_error (); */ link_error ();
if (pow(sqrt(x),4.0) != x*x) if (pow(sqrt(x),4.0) != x*x)
link_error (); link_error ();
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
extern float FN##f(float, float); \ extern float FN##f(float, float); \
extern long double FN##l(long double, long double); extern long double FN##l(long double, long double);
PROTOTYPE(fabs)
PROTOTYPE(sqrt) PROTOTYPE(sqrt)
PROTOTYPE(cbrt) PROTOTYPE(cbrt)
PROTOTYPE2(pow) PROTOTYPE2(pow)
...@@ -32,39 +33,45 @@ void test(double d1, double d2, double d3, ...@@ -32,39 +33,45 @@ void test(double d1, double d2, double d3,
{ {
/* Test N1root(N2root(x)) -> pow(x,1/(N1*N2)). */ /* Test N1root(N2root(x)) -> pow(x,1/(N1*N2)). */
/* E.g. sqrt(cbrt(x)) -> pow(x,1/6). */ /* E.g. sqrt(cbrt(x)) -> pow(x,1/6). */
#define ROOT_ROOT(FN1,N1,FN2,N2) \ /* The `ABS' argument is `fabs' when the transformation only works
for nonnegative arguments. Otherwise it's blank. */
#define ROOT_ROOT(FN1,N1,FN2,N2,ABS) \
extern void link_failure_##FN1##_##FN2(void); \ extern void link_failure_##FN1##_##FN2(void); \
if (FN1(FN2(d1)) != pow(d1,1.0/(N1*N2)) \ if (FN1(FN2(ABS(d1))) != pow(ABS(d1),1.0/(N1*N2)) \
|| C99CODE (FN1##f(FN2##f(f1)) != powf(f1,1.0F/(N1*N2))) \ || C99CODE (FN1##f(FN2##f(ABS(f1))) != powf(ABS(f1),1.0F/(N1*N2))) \
|| C99CODE (FN1##l(FN2##l(ld1)) != powl(ld1,1.0L/(N1*N2)))) \ || C99CODE (FN1##l(FN2##l(ABS(ld1))) != powl(ABS(ld1),1.0L/(N1*N2)))) \
link_failure_##FN1##_##FN2() link_failure_##FN1##_##FN2()
ROOT_ROOT(sqrt,2,sqrt,2); ROOT_ROOT(sqrt,2,sqrt,2,);
ROOT_ROOT(sqrt,2,cbrt,3); ROOT_ROOT(sqrt,2,cbrt,3,);
ROOT_ROOT(cbrt,3,sqrt,2); ROOT_ROOT(cbrt,3,sqrt,2,);
/*ROOT_ROOT(cbrt,3,cbrt,3); Intentionally not implemented. */ ROOT_ROOT(cbrt,3,cbrt,3,fabs);
/* Test pow(Nroot(x),y) -> pow(x,y/N). */ /* Test pow(Nroot(x),y) -> pow(x,y/N). */
#define POW_ROOT(FN,N) \ /* The `ABS' argument is `fabs' when the transformation only works
for nonnegative arguments. Otherwise it's blank. */
#define POW_ROOT(FN,N,ABS) \
extern void link_failure_pow_##FN(void); \ extern void link_failure_pow_##FN(void); \
if (pow(FN(d1), d2) != pow(d1,d2/N) \ if (pow(FN(ABS(d1)), d2) != pow(ABS(d1),d2/N) \
|| powf(FN##f(f1),f2) != powf(f1,f2/N) \ || powf(FN##f(ABS(f1)),f2) != powf(ABS(f1),f2/N) \
|| powl(FN##l(ld1),ld2) != powl(ld1,ld2/N)) \ || powl(FN##l(ABS(ld1)),ld2) != powl(ABS(ld1),ld2/N)) \
link_failure_pow_##FN() link_failure_pow_##FN()
POW_ROOT(sqrt,2); POW_ROOT(sqrt,2,);
/*POW_ROOT(cbrt,3); Intentionally not implemented. */ POW_ROOT(cbrt,3,fabs);
/* Test Nroot(pow(x,y)) -> pow(x,y/N). */ /* Test Nroot(pow(x,y)) -> pow(x,y/N). */
#define ROOT_POW(FN,N) \ /* The `ABS' argument is `fabs' when the transformation only works
for nonnegative arguments. Otherwise it's blank. */
#define ROOT_POW(FN,N,ABS) \
extern void link_failure_##FN##_pow(void); \ extern void link_failure_##FN##_pow(void); \
if (FN(pow(d1, d2)) != pow(d1,d2/N) \ if (FN(pow(ABS(d1), d2)) != pow(ABS(d1),d2/N) \
|| FN##f(powf(f1,f2)) != powf(f1,f2/N) \ || FN##f(powf(ABS(f1),f2)) != powf(ABS(f1),f2/N) \
|| FN##l(powl(ld1,ld2)) != powl(ld1,ld2/N)) \ || FN##l(powl(ABS(ld1),ld2)) != powl(ABS(ld1),ld2/N)) \
link_failure_##FN##_pow() link_failure_##FN##_pow()
/*ROOT_POW(sqrt,2); Invalid. */ ROOT_POW(sqrt,2,fabs);
/*ROOT_POW(cbrt,3); Intentionally not implemented. */ ROOT_POW(cbrt,3,fabs);
/* Test pow(pow(x,y),z) -> pow(x,y*z). */ /* Test pow(pow(x,y),z) -> pow(x,y*z). */
#define POW_POW \ #define POW_POW \
......
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