re PR middle-end/41094 (Erroneous optimization of pow() with -ffast-math)

2009-08-24  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.

From-SVN: r151051
This commit is contained in:
Richard Guenther 2009-08-24 09:52:03 +00:00 committed by Richard Biener
parent 791749ce04
commit eaa34b960c
6 changed files with 44 additions and 9 deletions

View File

@ -1,3 +1,9 @@
2009-08-24 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.
2009-08-23 Uros Bizjak <ubizjak@gmail.com>
PR target/40718

View File

@ -8634,15 +8634,18 @@ fold_builtin_pow (tree fndecl, tree arg0, tree arg1, tree type)
}
}
/* Optimize pow(pow(x,y),z) = pow(x,y*z). */
/* 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);
tree arg01 = CALL_EXPR_ARG (arg0, 1);
tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
return build_call_expr (fndecl, 2, arg00, narg1);
if (tree_expr_nonnegative_p (arg00))
{
tree arg01 = CALL_EXPR_ARG (arg0, 1);
tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
return build_call_expr (fndecl, 2, arg00, narg1);
}
}
}

View File

@ -1,3 +1,10 @@
2009-08-24 Richard Guenther <rguenther@suse.de>
PR middle-end/41094
* gcc.dg/torture/pr41094.c: New testcase.
* gcc.dg/torture/builtin-power-1.c: Adjust.
* gcc.dg/builtins-10.c: Likewise.
2009-08-23 Uros Bizjak <ubizjak@gmail.com>
PR target/40718

View File

@ -25,7 +25,7 @@ void test(double x)
link_error ();
if (pow(pow(x,4.0),0.25) != x)
link_error ();
/* XFAIL. PR41098. */;
}
void test2(double x, double y, double z)
@ -42,7 +42,7 @@ void test2(double x, double y, double z)
if (pow(sqrt(x),y) != pow(x,y*0.5))
link_error ();
if (pow(pow(x,y),z) != pow(x,y*z))
if (pow(pow(fabs(x),y),z) != pow(fabs(x),y*z))
link_error ();
}

View File

@ -77,9 +77,9 @@ void test(double d1, double d2, double d3,
/* 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)) \
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;

View File

@ -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;
}