This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR41094
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 18 Aug 2009 15:36:17 +0200 (CEST)
- Subject: [PATCH] Fix PR41094
This fixes PR41094, we incorrectly fold pow (pow (-10, 2), 0.25) to
sqrt (-10). The fix is easy, just allow this transformation only
for nonnegative x. It has a little fallout, but there are quite
some missed-optimizations around pow folding already - I opened
PR41098 for them.
Bootstrapped and tested on x86_64-unknown-linux-gnu on trunk and
the branches, applied to the trunk. I'll apply to the branches
if no problems with the testcase appear.
Richard.
2009-08-18 Richard Guenther <rguenther@suse.de>
PR middle-end/41094
* builtins.c (fold_builtin_pow): Fold pow(pow(x,y),z) to
pow(x,y*z) only if x is nonnegative.
* gcc.dg/torture/pr41094.c: New testcase.
* gcc.dg/torture/builtin-power-1.c: Adjust.
* gcc.dg/builtins-10.c: Likewise.
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c (revision 150867)
--- gcc/builtins.c (working copy)
*************** fold_builtin_pow (tree fndecl, tree arg0
*** 8459,8473 ****
}
}
! /* 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 = CALL_EXPR_ARG (arg0, 0);
! tree arg01 = CALL_EXPR_ARG (arg0, 1);
! tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
! return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
}
}
--- 8459,8476 ----
}
}
! /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative. */
if (fcode == BUILT_IN_POW
|| fcode == BUILT_IN_POWF
|| fcode == BUILT_IN_POWL)
{
tree arg00 = CALL_EXPR_ARG (arg0, 0);
! if (tree_expr_nonnegative_p (arg00))
! {
! tree arg01 = CALL_EXPR_ARG (arg0, 1);
! tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
! return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
! }
}
}
Index: gcc/testsuite/gcc.dg/torture/pr41094.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr41094.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr41094.c (revision 0)
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do run } */
+ /* { dg-options "-ffast-math" } */
+
+ #include <math.h>
+
+ extern void abort (void);
+
+ double foo(void)
+ {
+ double x = -4.0;
+ return pow (x * x, 0.25);
+ }
+
+ int main()
+ {
+ if (foo() != 2.0)
+ abort ();
+ return 0;
+ }
Index: gcc/testsuite/gcc.dg/torture/builtin-power-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/builtin-power-1.c (revision 150867)
--- gcc/testsuite/gcc.dg/torture/builtin-power-1.c (working copy)
*************** void test(double d1, double d2, double d
*** 77,85 ****
/* Test pow(pow(x,y),z) -> pow(x,y*z). */
#define POW_POW \
extern void link_failure_pow_pow(void); \
! if (pow(pow(d1, d2), d3) != pow(d1,d2*d3) \
! || powf(powf(f1,f2),f3) != powf(f1,f2*f3) \
! || powl(powl(ld1,ld2),ld3) != powl(ld1,ld2*ld3)) \
link_failure_pow_pow()
POW_POW;
--- 77,85 ----
/* Test pow(pow(x,y),z) -> pow(x,y*z). */
#define POW_POW \
extern void link_failure_pow_pow(void); \
! if (pow(pow(fabs(d1), d2), d3) != pow(fabs(d1),d2*d3) \
! || powf(powf(fabs(f1),f2),f3) != powf(fabs(f1),f2*f3) \
! || powl(powl(fabs(ld1),ld2),ld3) != powl(fabs(ld1),ld2*ld3)) \
link_failure_pow_pow()
POW_POW;
Index: gcc/testsuite/gcc.dg/builtins-10.c
===================================================================
*** gcc/testsuite/gcc.dg/builtins-10.c (revision 150867)
--- gcc/testsuite/gcc.dg/builtins-10.c (working copy)
*************** void test(double x)
*** 25,31 ****
link_error ();
if (pow(pow(x,4.0),0.25) != x)
! link_error ();
}
void test2(double x, double y, double z)
--- 25,31 ----
link_error ();
if (pow(pow(x,4.0),0.25) != x)
! /* XFAIL. PR41098. */;
}
void test2(double x, double y, double z)
*************** void test2(double x, double y, double z)
*** 42,48 ****
if (pow(sqrt(x),y) != pow(x,y*0.5))
link_error ();
! if (pow(pow(x,y),z) != pow(x,y*z))
link_error ();
}
--- 42,48 ----
if (pow(sqrt(x),y) != pow(x,y*0.5))
link_error ();
! if (pow(pow(fabs(x),y),z) != pow(fabs(x),y*z))
link_error ();
}