aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2005-03-09 20:11:48 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2005-03-09 20:11:48 +0000
commitd86dc3036d4ecd0432daad6a66dee219110cba5a (patch)
treedbef59a183a8241d0fee11d70432c971171cfd8a
parent41041fc2ac278ab937196aac357cfdb934a09473 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/builtins.c182
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/builtins-10.c4
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-power-1.c47
5 files changed, 161 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e902198..dddd9ab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
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.
2005-03-09 Kazu Hirata <kazu@cs.umass.edu>
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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fd38a0e..9d40f91 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+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>
PR c++/20208
diff --git a/gcc/testsuite/gcc.dg/builtins-10.c b/gcc/testsuite/gcc.dg/builtins-10.c
index 53158a0..d90e61a 100644
--- a/gcc/testsuite/gcc.dg/builtins-10.c
+++ b/gcc/testsuite/gcc.dg/builtins-10.c
@@ -18,8 +18,8 @@ extern double fabs(double);
void test(double x)
{
- /*if (sqrt(pow(x,4.0)) != x*x)
- link_error (); */
+ if (sqrt(pow(x,4.0)) != x*x)
+ link_error ();
if (pow(sqrt(x),4.0) != x*x)
link_error ();
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-power-1.c b/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
index 7cdc00c..7b890bb 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
@@ -22,6 +22,7 @@
extern float FN##f(float, float); \
extern long double FN##l(long double, long double);
+PROTOTYPE(fabs)
PROTOTYPE(sqrt)
PROTOTYPE(cbrt)
PROTOTYPE2(pow)
@@ -32,39 +33,45 @@ void test(double d1, double d2, double d3,
{
/* Test N1root(N2root(x)) -> pow(x,1/(N1*N2)). */
/* 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); \
- if (FN1(FN2(d1)) != pow(d1,1.0/(N1*N2)) \
- || C99CODE (FN1##f(FN2##f(f1)) != powf(f1,1.0F/(N1*N2))) \
- || C99CODE (FN1##l(FN2##l(ld1)) != powl(ld1,1.0L/(N1*N2)))) \
+ if (FN1(FN2(ABS(d1))) != pow(ABS(d1),1.0/(N1*N2)) \
+ || C99CODE (FN1##f(FN2##f(ABS(f1))) != powf(ABS(f1),1.0F/(N1*N2))) \
+ || C99CODE (FN1##l(FN2##l(ABS(ld1))) != powl(ABS(ld1),1.0L/(N1*N2)))) \
link_failure_##FN1##_##FN2()
- ROOT_ROOT(sqrt,2,sqrt,2);
- ROOT_ROOT(sqrt,2,cbrt,3);
- ROOT_ROOT(cbrt,3,sqrt,2);
- /*ROOT_ROOT(cbrt,3,cbrt,3); Intentionally not implemented. */
+ ROOT_ROOT(sqrt,2,sqrt,2,);
+ ROOT_ROOT(sqrt,2,cbrt,3,);
+ ROOT_ROOT(cbrt,3,sqrt,2,);
+ ROOT_ROOT(cbrt,3,cbrt,3,fabs);
/* 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); \
- if (pow(FN(d1), d2) != pow(d1,d2/N) \
- || powf(FN##f(f1),f2) != powf(f1,f2/N) \
- || powl(FN##l(ld1),ld2) != powl(ld1,ld2/N)) \
+ if (pow(FN(ABS(d1)), d2) != pow(ABS(d1),d2/N) \
+ || powf(FN##f(ABS(f1)),f2) != powf(ABS(f1),f2/N) \
+ || powl(FN##l(ABS(ld1)),ld2) != powl(ABS(ld1),ld2/N)) \
link_failure_pow_##FN()
- POW_ROOT(sqrt,2);
- /*POW_ROOT(cbrt,3); Intentionally not implemented. */
+ POW_ROOT(sqrt,2,);
+ POW_ROOT(cbrt,3,fabs);
/* 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); \
- if (FN(pow(d1, d2)) != pow(d1,d2/N) \
- || FN##f(powf(f1,f2)) != powf(f1,f2/N) \
- || FN##l(powl(ld1,ld2)) != powl(ld1,ld2/N)) \
+ if (FN(pow(ABS(d1), d2)) != pow(ABS(d1),d2/N) \
+ || FN##f(powf(ABS(f1),f2)) != powf(ABS(f1),f2/N) \
+ || FN##l(powl(ABS(ld1),ld2)) != powl(ABS(ld1),ld2/N)) \
link_failure_##FN##_pow()
- /*ROOT_POW(sqrt,2); Invalid. */
- /*ROOT_POW(cbrt,3); Intentionally not implemented. */
+ ROOT_POW(sqrt,2,fabs);
+ ROOT_POW(cbrt,3,fabs);
/* Test pow(pow(x,y),z) -> pow(x,y*z). */
#define POW_POW \