[PATCH] Fix up pow folding (PR tree-optimization/56125)

Jakub Jelinek jakub@redhat.com
Mon Jan 28 14:25:00 GMT 2013


Hi!

gimple_expand_builtin_pow last two optimizations rely on earlier
optimizations in the same function to be performed, e.g.
folding pow (x, c) for n = 2c into sqrt(x) * powi(x, n / 2) is only
correct for c which isn't an integer (otherwise the sqrt(x) factor would
need to be skipped), but they actually do not check this.
E.g. the pow (x, n) where n is integer is optimized only if:
      && ((n >= -1 && n <= 2)
          || (flag_unsafe_math_optimizations
              && optimize_insn_for_speed_p ()
              && powi_cost (n) <= POWI_MAX_MULTS)))
and as in the testcase the function is called, it isn't optimized and
we fall through till the above mentioned optimization which blindly assumes
that c isn't an integer.

Fixed by both checking that c isn't an integer (and for the last
optimization also that 2c isn't an integer), and also not doing the
-> sqrt(x) * powi(x, n / 2) resp. 1.0 / sqrt(x) * powi(x, abs(n) / 2)
optimization for -Os or cold functions, at least
__attribute__((cold)) double
foo (double x, double n)
{
  return __builtin_pow (x, -1.5);
}
is smaller when expanded as pow call both on x86_64 and on powerpc (with
-Os -ffast-math).  Even just the c*_is_int tests alone could be enough
to fix the bug, so if you say want to enable it for -Os even with c 1.5,
but not for negative values which add another operation, it can be adjusted.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2013-01-28  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/56125
	* tree-ssa-math-opts.c (gimple_expand_builtin_pow): Don't optimize
	pow(x,c) into sqrt(x) * powi(x, n/2) or
	1.0 / (sqrt(x) * powi(x, abs(n/2))) if c is an integer or when
	optimizing for size.
	Don't optimize pow(x,c) into powi(x, n/3) * powi(cbrt(x), n%3) or
	1.0 / (powi(x, abs(n)/3) * powi(cbrt(x), abs(n)%3)) if 2c is an
	integer.

	* gcc.dg/pr56125.c: New test.

--- gcc/tree-ssa-math-opts.c.jj	2013-01-11 09:02:48.000000000 +0100
+++ gcc/tree-ssa-math-opts.c	2013-01-28 10:56:40.105950483 +0100
@@ -1110,7 +1110,7 @@ gimple_expand_builtin_pow (gimple_stmt_i
   HOST_WIDE_INT n;
   tree type, sqrtfn, cbrtfn, sqrt_arg0, sqrt_sqrt, result, cbrt_x, powi_cbrt_x;
   enum machine_mode mode;
-  bool hw_sqrt_exists;
+  bool hw_sqrt_exists, c_is_int, c2_is_int;
 
   /* If the exponent isn't a constant, there's nothing of interest
      to be done.  */
@@ -1122,8 +1122,9 @@ gimple_expand_builtin_pow (gimple_stmt_i
   c = TREE_REAL_CST (arg1);
   n = real_to_integer (&c);
   real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
+  c_is_int = real_identical (&c, &cint);
 
-  if (real_identical (&c, &cint)
+  if (c_is_int
       && ((n >= -1 && n <= 2)
 	  || (flag_unsafe_math_optimizations
 	      && optimize_insn_for_speed_p ()
@@ -1221,7 +1222,8 @@ gimple_expand_builtin_pow (gimple_stmt_i
       return build_and_insert_call (gsi, loc, cbrtfn, sqrt_arg0);
     }
 
-  /* Optimize pow(x,c), where n = 2c for some nonzero integer n, into
+  /* Optimize pow(x,c), where n = 2c for some nonzero integer n
+     and c not an integer, into
 
        sqrt(x) * powi(x, n/2),                n > 0;
        1.0 / (sqrt(x) * powi(x, abs(n/2))),   n < 0.
@@ -1230,10 +1232,13 @@ gimple_expand_builtin_pow (gimple_stmt_i
   real_arithmetic (&c2, MULT_EXPR, &c, &dconst2);
   n = real_to_integer (&c2);
   real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, 0);
+  c2_is_int = real_identical (&c2, &cint);
 
   if (flag_unsafe_math_optimizations
       && sqrtfn
-      && real_identical (&c2, &cint))
+      && c2_is_int
+      && !c_is_int
+      && optimize_function_for_speed_p (cfun))
     {
       tree powi_x_ndiv2 = NULL_TREE;
 
@@ -1286,6 +1291,7 @@ gimple_expand_builtin_pow (gimple_stmt_i
       && cbrtfn
       && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode))
       && real_identical (&c2, &c)
+      && !c2_is_int
       && optimize_function_for_speed_p (cfun)
       && powi_cost (n / 3) <= POWI_MAX_MULTS)
     {
--- gcc/testsuite/gcc.dg/pr56125.c.jj	2013-01-28 11:00:04.359814742 +0100
+++ gcc/testsuite/gcc.dg/pr56125.c	2013-01-28 11:00:55.048532118 +0100
@@ -0,0 +1,21 @@
+/* PR tree-optimization/56125 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void abort (void);
+extern double fabs (double);
+
+__attribute__((cold)) double
+foo (double x, double n)
+{
+  double u = x / (n * n);
+  return u;
+}
+
+int
+main ()
+{
+  if (fabs (foo (29, 2) - 7.25) > 0.001)
+    abort ();
+  return 0;
+}
 
	Jakub



More information about the Gcc-patches mailing list