On Mon, Jun 6, 2011 at 8:59 PM, William J. Schmidt <wschm...@linux.vnet.ibm.com> wrote: > Hi Richard, > > Here's the reworked patch addressing the noted concerns. Regtested for > powerpc-linux. OK for trunk?
Ok with ... > Thanks, > Bill > > > 2011-06-06 Bill Schmidt <wschm...@linux.vnet.ibm.com> > > PR tree-optimization/46728 > * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Change FIXME > to use gimple_val_nonnegative_real_p. > * gimple-fold.c (gimple_val_nonnegative_real_p): New function. > * gimple.h (gimple_val_nonnegative_real_p): New declaration. > > > Index: gcc/tree-ssa-math-opts.c > =================================================================== > --- gcc/tree-ssa-math-opts.c (revision 174708) > +++ gcc/tree-ssa-math-opts.c (working copy) > @@ -1172,13 +1172,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *g > > if (flag_unsafe_math_optimizations > && cbrtfn > - /* FIXME: The following line was originally > - && (tree_expr_nonnegative_p (arg0) || !HONOR_NANS (mode)), > - but since arg0 is a gimple value, the first predicate > - will always return false. It needs to be replaced with a > - call to a similar gimple_val_nonnegative_p function to be > - added in gimple-fold.c. */ > - && !HONOR_NANS (mode) > + && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode)) > && REAL_VALUES_EQUAL (c, dconst1_3)) > return build_and_insert_call (gsi, loc, &target, cbrtfn, arg0); > > @@ -1190,13 +1184,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *g > if (flag_unsafe_math_optimizations > && sqrtfn > && cbrtfn > - /* FIXME: The following line was originally > - && (tree_expr_nonnegative_p (arg0) || !HONOR_NANS (mode)), > - but since arg0 is a gimple value, the first predicate > - will always return false. It needs to be replaced with a > - call to a similar gimple_val_nonnegative_p function to be > - added in gimple-fold.c. */ > - && !HONOR_NANS (mode) > + && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode)) > && optimize_function_for_speed_p (cfun) > && hw_sqrt_exists > && REAL_VALUES_EQUAL (c, dconst1_6)) > @@ -1270,13 +1258,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *g > > if (flag_unsafe_math_optimizations > && cbrtfn > - /* FIXME: The following line was originally > - && (tree_expr_nonnegative_p (arg0) || !HONOR_NANS (mode)), > - but since arg0 is a gimple value, the first predicate > - will always return false. It needs to be replaced with a > - call to a similar gimple_val_nonnegative_p function to be > - added in gimple-fold.c. */ > - && !HONOR_NANS (mode) > + && (gimple_val_nonnegative_real_p (arg0) || !HONOR_NANS (mode)) > && real_identical (&c2, &c) > && optimize_function_for_speed_p (cfun) > && powi_cost (n / 3) <= POWI_MAX_MULTS) > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c (revision 174708) > +++ gcc/gimple-fold.c (working copy) > @@ -3433,3 +3433,134 @@ fold_const_aggregate_ref (tree t) > { > return fold_const_aggregate_ref_1 (t, NULL); > } > + > +/* Return true iff VAL is a gimple expression that is known to be > + non-negative. Restricted to floating-point inputs. */ > + > +bool > +gimple_val_nonnegative_real_p (tree val) > +{ > + gimple def_stmt; > + > + gcc_assert (val && (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)); SCALAR_FLOAT_TYPE_P (TREE_TYPE (val)) Thanks, Richard. > + /* Use existing logic for non-gimple trees. */ > + if (tree_expr_nonnegative_p (val)) > + return true; > + > + if (TREE_CODE (val) != SSA_NAME) > + return false; > + > + /* Currently we look only at the immediately defining statement > + to make this determination, since recursion on defining > + statements of operands can lead to quadratic behavior in the > + worst case. This is expected to catch almost all occurrences > + in practice. It would be possible to implement limited-depth > + recursion if important cases are lost. Alternatively, passes > + that need this information (such as the pow/powi lowering code > + in the cse_sincos pass) could be revised to provide it through > + dataflow propagation. */ > + > + def_stmt = SSA_NAME_DEF_STMT (val); > + > + if (is_gimple_assign (def_stmt)) > + { > + tree op0, op1; > + > + /* See fold-const.c:tree_expr_nonnegative_p for additional > + cases that could be handled with recursion. */ > + > + switch (gimple_assign_rhs_code (def_stmt)) > + { > + case ABS_EXPR: > + /* Always true for floating-point operands. */ > + return true; > + > + case MULT_EXPR: > + /* True if the two operands are identical (since we are > + restricted to floating-point inputs). */ > + op0 = gimple_assign_rhs1 (def_stmt); > + op1 = gimple_assign_rhs2 (def_stmt); > + > + if (op0 == op1 > + || operand_equal_p (op0, op1, 0)) > + return true; > + > + default: > + return false; > + } > + } > + else if (is_gimple_call (def_stmt)) > + { > + tree fndecl = gimple_call_fndecl (def_stmt); > + if (fndecl > + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) > + { > + tree arg1; > + > + switch (DECL_FUNCTION_CODE (fndecl)) > + { > + CASE_FLT_FN (BUILT_IN_ACOS): > + CASE_FLT_FN (BUILT_IN_ACOSH): > + CASE_FLT_FN (BUILT_IN_CABS): > + CASE_FLT_FN (BUILT_IN_COSH): > + CASE_FLT_FN (BUILT_IN_ERFC): > + CASE_FLT_FN (BUILT_IN_EXP): > + CASE_FLT_FN (BUILT_IN_EXP10): > + CASE_FLT_FN (BUILT_IN_EXP2): > + CASE_FLT_FN (BUILT_IN_FABS): > + CASE_FLT_FN (BUILT_IN_FDIM): > + CASE_FLT_FN (BUILT_IN_HYPOT): > + CASE_FLT_FN (BUILT_IN_POW10): > + return true; > + > + CASE_FLT_FN (BUILT_IN_SQRT): > + /* sqrt(-0.0) is -0.0, and sqrt is not defined over other > + nonnegative inputs. */ > + if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (val)))) > + return true; > + > + break; > + > + CASE_FLT_FN (BUILT_IN_POWI): > + /* True if the second argument is an even integer. */ > + arg1 = gimple_call_arg (def_stmt, 1); > + > + if (TREE_CODE (arg1) == INTEGER_CST > + && (TREE_INT_CST_LOW (arg1) & 1) == 0) > + return true; > + > + break; > + > + CASE_FLT_FN (BUILT_IN_POW): > + /* True if the second argument is an even integer-valued > + real. */ > + arg1 = gimple_call_arg (def_stmt, 1); > + > + if (TREE_CODE (arg1) == REAL_CST) > + { > + REAL_VALUE_TYPE c; > + HOST_WIDE_INT n; > + > + c = TREE_REAL_CST (arg1); > + n = real_to_integer (&c); > + > + if ((n & 1) == 0) > + { > + REAL_VALUE_TYPE cint; > + real_from_integer (&cint, VOIDmode, n, n < 0 ? -1 : 0, > 0); > + if (real_identical (&c, &cint)) > + return true; > + } > + } > + > + break; > + > + default: > + return false; > + } > + } > + } > + > + return false; > +} > Index: gcc/gimple.h > =================================================================== > --- gcc/gimple.h (revision 174708) > +++ gcc/gimple.h (working copy) > @@ -4988,4 +4988,5 @@ extern tree maybe_fold_and_comparisons (enum tree_ > extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree, > enum tree_code, tree, tree); > > +bool gimple_val_nonnegative_real_p (tree); > #endif /* GCC_GIMPLE_H */ > > >