This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 ();
  }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]