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:
parent
3c395ecf7d
commit
06bc3ec790
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue