[PATCH] gimple_val_nonnegative_real_p (PR46728 patch 7 of 7)

Richard Guenther richard.guenther@gmail.com
Tue Jun 7 10:08:00 GMT 2011


On Mon, Jun 6, 2011 at 8:59 PM, William J. Schmidt
<wschmidt@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  <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.
>
>
> 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 */
>
>
>



More information about the Gcc-patches mailing list