aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>2011-06-07 15:12:04 +0000
committerWilliam Schmidt <wschmidt@gcc.gnu.org>2011-06-07 15:12:04 +0000
commit06bc3ec79056f8c53d4e59f45afe78a547c23546 (patch)
tree44dc6b8481b3a6a81e091f03fc34efc38e60abff
parent3c395ecf7d41384016acbcc18d4847c72685013c (diff)
downloadgcc-06bc3ec79056f8c53d4e59f45afe78a547c23546.zip
gcc-06bc3ec79056f8c53d4e59f45afe78a547c23546.tar.gz
gcc-06bc3ec79056f8c53d4e59f45afe78a547c23546.tar.bz2
re PR tree-optimization/46728 (GCC does not generate fmadd for pow (x, 0.75)+y on powerpc)
2011-06-07 Bill Schmidt <wschmidt@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. From-SVN: r174752
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/gimple-fold.c131
-rw-r--r--gcc/gimple.h1
-rw-r--r--gcc/tree-ssa-math-opts.c24
4 files changed, 143 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f823caf..932e8e1d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2011-06-07 Bill Schmidt <wschmidt@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.
+
2011-06-07 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.md (*movsf_internal): Optimize AVX check.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index eaff1b3..180a51e 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 0648888..c39eb57 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 f53a300..e6b5857 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)