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
This commit is contained in:
Bill Schmidt 2011-06-07 15:12:04 +00:00 committed by William Schmidt
parent 3c395ecf7d
commit 06bc3ec790
4 changed files with 143 additions and 21 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)