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,8 +6311,10 @@ fold_builtin_cbrt (tree arglist, tree type) ...@@ -6311,8 +6311,10 @@ 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;
if (flag_unsafe_math_optimizations)
{
/* Optimize cbrt(expN(x)) -> expN(x/3). */ /* Optimize cbrt(expN(x)) -> expN(x/3). */
if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode)) if (BUILTIN_EXPONENT_P (fcode))
{ {
tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0); tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
const REAL_VALUE_TYPE third_trunc = const REAL_VALUE_TYPE third_trunc =
...@@ -6325,9 +6327,7 @@ fold_builtin_cbrt (tree arglist, tree type) ...@@ -6325,9 +6327,7 @@ fold_builtin_cbrt (tree arglist, tree type)
} }
/* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */ /* Optimize cbrt(sqrt(x)) -> pow(x,1/6). */
/* We don't optimize cbrt(cbrt(x)) -> pow(x,1/9) because if if (BUILTIN_SQRT_P (fcode))
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); tree powfn = mathfn_built_in (type, BUILT_IN_POW);
...@@ -6344,7 +6344,49 @@ fold_builtin_cbrt (tree arglist, tree type) ...@@ -6344,7 +6344,49 @@ fold_builtin_cbrt (tree arglist, tree type)
build_tree_list (NULL_TREE, tree_root)); build_tree_list (NULL_TREE, tree_root));
return build_function_call_expr (powfn, arglist); 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,9 +6969,12 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) ...@@ -6928,9 +6969,12 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
} }
} }
if (flag_unsafe_math_optimizations)
{
const enum built_in_function fcode = builtin_mathfn_code (arg0);
/* Optimize pow(expN(x),y) = expN(x*y). */ /* Optimize pow(expN(x),y) = expN(x*y). */
fcode = builtin_mathfn_code (arg0); if (BUILTIN_EXPONENT_P (fcode))
if (flag_unsafe_math_optimizations && BUILTIN_EXPONENT_P (fcode))
{ {
tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0); tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1)); tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
...@@ -6940,7 +6984,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) ...@@ -6940,7 +6984,7 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
} }
/* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */ /* Optimize pow(sqrt(x),y) = pow(x,y*0.5). */
if (flag_unsafe_math_optimizations && BUILTIN_SQRT_P (fcode)) if (BUILTIN_SQRT_P (fcode))
{ {
tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1)); tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
tree narg1 = fold (build2 (MULT_EXPR, type, arg1, tree narg1 = fold (build2 (MULT_EXPR, type, arg1,
...@@ -6951,11 +6995,25 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) ...@@ -6951,11 +6995,25 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
return build_function_call_expr (fndecl, arglist); 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). */ /* Optimize pow(pow(x,y),z) = pow(x,y*z). */
if (flag_unsafe_math_optimizations if (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWF
&& (fcode == BUILT_IN_POW || fcode == BUILT_IN_POWL)
|| fcode == BUILT_IN_POWF
|| fcode == BUILT_IN_POWL))
{ {
tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1)); tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1))); tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
...@@ -6964,6 +7022,8 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) ...@@ -6964,6 +7022,8 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type)
build_tree_list (NULL_TREE, narg1)); build_tree_list (NULL_TREE, narg1));
return build_function_call_expr (fndecl, arglist); 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