Here's a small patch to expand pow(x,n) for integer n using the
powi(x,n) logic in the cse_sincos pass.  OK for trunk?

For the next patch, I'll plan on expanding pow(x,n) for n in
{0.5, 0.25, 0.75, 1./3., 1./6.}.  This logic will be added to
gimple_expand_builtin_pow.

Bill


2011-05-24  Bill Schmidt  <wschm...@linux.vnet.ibm.com>
        PR tree-optimization/46728
        * tree-ssa-math-opts.c (gimple_expand_builtin_pow): New.
        (execute_cse_sincos): Add switch case for BUILT_IN_POW.
        
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c    (revision 174129)
+++ gcc/tree-ssa-math-opts.c    (working copy)
@@ -1024,6 +1024,39 @@ gimple_expand_builtin_powi (gimple_stmt_iterator *
   return NULL_TREE;
 }
 
+/* ARG0 and ARG1 are the two arguments to a pow builtin call in GSI
+   with location info LOC.  If possible, create an equivalent and
+   less expensive sequence of statements prior to GSI, and return an
+   expession holding the result.  */
+
+static tree
+gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc, 
+                          tree arg0, tree arg1)
+{
+  REAL_VALUE_TYPE c, cint;
+  HOST_WIDE_INT n;
+
+  /* If the exponent isn't a constant, there's nothing of interest
+     to be done.  */
+  if (TREE_CODE (arg1) != REAL_CST)
+    return NULL_TREE;
+
+  /* If the exponent is equivalent to an integer, expand it into
+     multiplies when profitable.  */
+  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_insn_for_speed_p ()
+             && powi_cost (n) <= POWI_MAX_MULTS)))
+    return gimple_expand_builtin_powi (gsi, loc, arg0, n);
+
+  return NULL_TREE;
+}
+
 /* Go through all calls to sin, cos and cexpi and call execute_cse_sincos_1
    on the SSA_NAME argument of each of them.  Also expand powi(x,n) into
    an optimal number of multiplies, when n is a constant.  */
@@ -1065,6 +1098,23 @@ execute_cse_sincos (void)
                    cfg_changed |= execute_cse_sincos_1 (arg);
                  break;
 
+               CASE_FLT_FN (BUILT_IN_POW):
+                 arg0 = gimple_call_arg (stmt, 0);
+                 arg1 = gimple_call_arg (stmt, 1);
+
+                 loc = gimple_location (stmt);
+                 result = gimple_expand_builtin_pow (&gsi, loc, arg0, arg1);
+
+                 if (result)
+                   {
+                     tree lhs = gimple_get_lhs (stmt);
+                     gimple new_stmt = gimple_build_assign (lhs, result);
+                     gimple_set_location (new_stmt, loc);
+                     unlink_stmt_vdef (stmt);
+                     gsi_replace (&gsi, new_stmt, true);
+                   }
+                 break;
+
                CASE_FLT_FN (BUILT_IN_POWI):
                  arg0 = gimple_call_arg (stmt, 0);
                  arg1 = gimple_call_arg (stmt, 1);


Reply via email to