From 06bc3ec79056f8c53d4e59f45afe78a547c23546 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Tue, 7 Jun 2011 15:12:04 +0000 Subject: [PATCH] re PR tree-optimization/46728 (GCC does not generate fmadd for pow (x, 0.75)+y on powerpc) 2011-06-07 Bill Schmidt 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. From-SVN: r174752 --- gcc/ChangeLog | 8 +++ gcc/gimple-fold.c | 131 +++++++++++++++++++++++++++++++++++++++ gcc/gimple.h | 1 + gcc/tree-ssa-math-opts.c | 24 +------ 4 files changed, 143 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f823caf8410..932e8e1d1ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-06-07 Bill Schmidt + + 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. + 2011-06-07 H.J. Lu * config/i386/i386.md (*movsf_internal): Optimize AVX check. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index eaff1b3a4ee..180a51e095a 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3447,3 +3447,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 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (val))); + + /* 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; +} diff --git a/gcc/gimple.h b/gcc/gimple.h index 06488881239..c39eb574c87 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -4988,4 +4988,5 @@ extern tree maybe_fold_and_comparisons (enum tree_code, tree, 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 */ diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index f53a3004b93..e6b585723e9 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1172,13 +1172,7 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *gsi, location_t loc, 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 *gsi, location_t loc, 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 *gsi, location_t loc, 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) -- 2.30.2