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 PR25620, pow() expansion missed-optimization, 2nd try


This is the 2nd try as suggested by Roger.  I have left out the
split out of common parts of pow/powi expansion - it doesn't really
work out.  I have also left in the cbrt() variant, but I can easily
leave that out if required.

Bootstrapped and regtested on x86_64-unknown-linux-gnu.  SPEC 2k
doesn't show a difference, Polyhedron has an improvement for air
(down from 21s to 16.5s runtime).

Ok for mainline?

Thanks,
Richard.

2006-11-11  Richard Guenther  <rguenther@suse.de>

	PR middle-end/25620
	* builtins.c (expand_builtin_pow): Use sqrt or cbrt if that
	makes the remaining exponent integer.

	* gcc.target/i386/pow-1.c: New testcase.
	* gcc.dg/builtins-58.c: Likewise.

Index: builtins.c
===================================================================
*** builtins.c	(revision 118691)
--- builtins.c	(working copy)
*************** expand_builtin_pow (tree exp, rtx target
*** 2609,2639 ****
    arg0 = TREE_VALUE (arglist);
    arg1 = TREE_VALUE (TREE_CHAIN (arglist));
  
    if (TREE_CODE (arg1) == REAL_CST
        && ! TREE_CONSTANT_OVERFLOW (arg1))
      {
        REAL_VALUE_TYPE cint;
!       REAL_VALUE_TYPE c;
        HOST_WIDE_INT n;
  
        c = TREE_REAL_CST (arg1);
        n = real_to_integer (&c);
        real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
!       if (real_identical (&c, &cint))
! 	{
! 	  /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
! 	     Otherwise, check the number of multiplications required.
! 	     Note that pow never sets errno for an integer exponent.  */
! 	  if ((n >= -1 && n <= 2)
  	      || (flag_unsafe_math_optimizations
! 		  && ! optimize_size
! 		  && powi_cost (n) <= POWI_MAX_MULTS))
  	    {
- 	      enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
- 	      rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
  	      op = force_reg (mode, op);
! 	      return expand_powi (op, mode, n);
  	    }
  	}
      }
  
--- 2609,2697 ----
    arg0 = TREE_VALUE (arglist);
    arg1 = TREE_VALUE (TREE_CHAIN (arglist));
  
+   /* Handle constant exponents.  */
    if (TREE_CODE (arg1) == REAL_CST
        && ! TREE_CONSTANT_OVERFLOW (arg1))
      {
        REAL_VALUE_TYPE cint;
!       REAL_VALUE_TYPE c, c2;
        HOST_WIDE_INT n;
+       rtx op, op2;
+       tree fn;
+       tree type = TREE_TYPE (exp);
+       enum machine_mode mode = TYPE_MODE (type);
  
        c = TREE_REAL_CST (arg1);
        n = real_to_integer (&c);
        real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
!       if (real_identical (&c, &cint)
! 	  && ((n >= -1 && n <= 2)
  	      || (flag_unsafe_math_optimizations
! 		  && !optimize_size
! 		  && powi_cost (n) <= POWI_MAX_MULTS)))
!         {
! 	  op = expand_expr (arg0, subtarget, VOIDmode, 0);
! 	  if (n != 1)
  	    {
  	      op = force_reg (mode, op);
! 	      op = expand_powi (op, mode, n);
! 	    }
! 	  return op;
! 	}
! 
!       if (!flag_unsafe_math_optimizations)
! 	return NULL_RTX;
! 
!       /* If the exponent is not integer valued, check if it is
! 	 half of an integer.  In this case we can expand to
! 	 sqrt (x) * x**(n/2).  */
!       real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
!       n = real_to_integer (&c2);
!       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
!       if (real_identical (&c2, &cint)
! 	  && (fn = mathfn_built_in (type, BUILT_IN_SQRT))
! 	  && !optimize_size
! 	  && powi_cost (n/2) <= POWI_MAX_MULTS)
! 	{
! 	  tree arg = build_tree_list (NULL_TREE, arg0);
! 	  tree call_expr = build_function_call_expr (fn, arg);
! 	  op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
! 	  if (n != 1)
! 	    {
! 	      op2 = expand_expr (arg0, subtarget, VOIDmode, 0);
! 	      op2 = force_reg (mode, op2);
! 	      op2 = expand_powi (op2, mode, n / 2);
! 	      expand_simple_binop (mode, MULT, op, op2, op, 0, OPTAB_DIRECT);
! 	    }
! 	  return op;
! 	}
! 
!       /* Try if the exponent is a third of an integer.  In this case
! 	 we can expand to x**(n/3) * cbrt(x)**(n%3).  */
!       real_arithmetic (&c2, MULT_EXPR, &c, &dconst3);
!       real_round (&c2, mode, &c2);
!       n = real_to_integer (&c2);
!       real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
!       real_arithmetic (&c2, RDIV_EXPR, &cint, &dconst3);
!       real_convert (&c2, mode, &c2);
!       if (real_identical (&c2, &c)
! 	  && (fn = mathfn_built_in (type, BUILT_IN_CBRT))
! 	  && !optimize_size
! 	  && powi_cost (n/3) <= POWI_MAX_MULTS)
! 	{
! 	  tree arg = build_tree_list (NULL_TREE, arg0);
! 	  tree call_expr = build_function_call_expr (fn, arg);
! 	  op = expand_builtin (call_expr, NULL_RTX, subtarget, mode, 0);
! 	  if (n % 3 == 2)
! 	    expand_simple_binop (mode, MULT, op, op, op, 0, OPTAB_DIRECT);
! 	  if (n != 1)
! 	    {
! 	      op2 = expand_expr (arg0, subtarget, VOIDmode, 0);
! 	      op2 = force_reg (mode, op2);
! 	      op2 = expand_powi (op2, mode, n / 3);
! 	      expand_simple_binop (mode, MULT, op, op2, op, 0, OPTAB_DIRECT);
  	    }
+ 	  return op;
  	}
      }
  
Index: testsuite/gcc.target/i386/pow-1.c
===================================================================
*** testsuite/gcc.target/i386/pow-1.c	(revision 0)
--- testsuite/gcc.target/i386/pow-1.c	(revision 0)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -ffast-math" } */
+ 
+ double test1 (double x)
+ {
+   return __builtin_pow (x, 1./2.);
+ }
+ 
+ double test2 (double x)
+ {
+   return __builtin_pow (x, 3./2.);
+ }
+ 
+ double test3 (double x)
+ {
+   return __builtin_pow (x, 5./2.);
+ }
+ 
+ /* { dg-final { scan-assembler-not "call" } } */
+ 
Index: testsuite/gcc.dg/builtins-58.c
===================================================================
*** testsuite/gcc.dg/builtins-58.c	(revision 0)
--- testsuite/gcc.dg/builtins-58.c	(revision 0)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -ffast-math -std=c99" } */
+ 
+ double test1 (double x)
+ {
+   return __builtin_pow (x, 1./3.);
+ }
+ 
+ double test2 (double x)
+ {
+   return __builtin_pow (x, 4./3.);
+ }
+ 
+ double test3 (double x)
+ {
+   return __builtin_pow (x, 7./3.);
+ }
+ 
+ /* { dg-final { scan-assembler-times "cbrt" 3 } } */
+ 


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