This is a ping for the patch to fix 61441.

Regards,
Sujoy

On Tue, Oct 13, 2015 at 4:16 PM, Sujoy Saraswati <ssarasw...@gmail.com> wrote:
> Hi,
>  This is another modified version of the patch, incorporating the
> previous comments.
>
> Bootstrap and regression tests on x86_64-linux-gnu and
> aarch64-unknown-linux-gnu passed with changes done on trunk.
>
> Is this fine ?
>
> Regards,
> Sujoy
>
> 2015-10-13  Sujoy Saraswati <ssarasw...@gmail.com>
>
>         PR tree-optimization/61441
>         * builtins.c (integer_valued_real_p): Return true for
>         NaN values.
>         (fold_builtin_trunc, fold_builtin_pow): Avoid the operation
>         if flag_signaling_nans is on and the operand is a NaN.
>         (fold_builtin_powi): Same.
>         * fold-const.c (const_binop): Convert sNaN to qNaN when
>         flag_signaling_nans is off.
>         (const_unop): Avoid the operation, other than NEGATE and
>         ABS, if flag_signaling_nans is on and the operand is a NaN.
>         (fold_convert_const_real_from_real): Avoid the operation if
>         flag_signaling_nans is on and the operand is a NaN.
>         * real.c (do_add): Make resulting NaN value to be qNaN.
>         (do_multiply, do_divide, do_fix_trunc): Same.
>         (real_arithmetic, real_ldexp): Same
>         * simplify-rtx.c (simplify_const_unary_operation): Avoid the
>         operation if flag_signaling_nans is on and the operand is a NaN.
>         * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Same.
>
>         PR tree-optimization/61441
>         * gcc.dg/pr61441.c: New testcase.
>
> Index: gcc/builtins.c
> ===================================================================
> --- gcc/builtins.c      (revision 228700)
> +++ gcc/builtins.c      (working copy)
> @@ -7357,7 +7357,11 @@ integer_valued_real_p (tree t)
>              && integer_valued_real_p (TREE_OPERAND (t, 2));
>
>      case REAL_CST:
> -      return real_isinteger (TREE_REAL_CST_PTR (t), TYPE_MODE (TREE_TYPE 
> (t)));
> +      /* Return true for NaN values, since real_isinteger would
> +         return false if the value is sNaN.  */
> +      return (REAL_VALUE_ISNAN (TREE_REAL_CST (t))
> +              || real_isinteger (TREE_REAL_CST_PTR (t),
> +                             TYPE_MODE (TREE_TYPE (t))));
>
>      CASE_CONVERT:
>        {
> @@ -7910,8 +7914,13 @@ fold_builtin_trunc (location_t loc, tree fndecl, t
>        tree type = TREE_TYPE (TREE_TYPE (fndecl));
>
>        x = TREE_REAL_CST (arg);
> -      real_trunc (&r, TYPE_MODE (type), &x);
> -      return build_real (type, r);
> +      /* Avoid the folding if flag_signaling_nans is on.  */
> +      if (!(HONOR_SNANS (TYPE_MODE (type))
> +            && REAL_VALUE_ISNAN (x)))
> +      {
> +        real_trunc (&r, TYPE_MODE (type), &x);
> +        return build_real (type, r);
> +      }
>      }
>
>    return fold_trunc_transparent_mathfn (loc, fndecl, arg);
> @@ -8297,9 +8306,15 @@ fold_builtin_pow (location_t loc, tree fndecl, tre
>               bool inexact;
>
>               x = TREE_REAL_CST (arg0);
> +
>               inexact = real_powi (&x, TYPE_MODE (type), &x, n);
> -             if (flag_unsafe_math_optimizations || !inexact)
> -               return build_real (type, x);
> +
> +              /* Avoid the folding if flag_signaling_nans is on.  */
> +             if (flag_unsafe_math_optimizations
> +                  || (!inexact
> +                      && !(HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
> +                           && REAL_VALUE_ISNAN (x))))
> +                 return build_real (type, x);
>             }
>
>           /* Strip sign ops from even integer powers.  */
> @@ -8388,8 +8403,14 @@ fold_builtin_powi (location_t loc, tree fndecl ATT
>         {
>           REAL_VALUE_TYPE x;
>           x = TREE_REAL_CST (arg0);
> -         real_powi (&x, TYPE_MODE (type), &x, c);
> -         return build_real (type, x);
> +
> +          /* Avoid the folding if flag_signaling_nans is on.  */
> +          if (!(HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
> +                && REAL_VALUE_ISNAN (x)))
> +          {
> +           real_powi (&x, TYPE_MODE (type), &x, c);
> +           return build_real (type, x);
> +          }
>         }
>
>        /* Optimize pow(x,0) = 1.0.  */
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    (revision 228700)
> +++ gcc/fold-const.c    (working copy)
> @@ -1185,9 +1185,21 @@ const_binop (enum tree_code code, tree arg1, tree
>        /* If either operand is a NaN, just return it.  Otherwise, set up
>          for floating-point trap; we return an overflow.  */
>        if (REAL_VALUE_ISNAN (d1))
> -       return arg1;
> +      {
> +        /* Make resulting NaN value to be qNaN when flag_signaling_nans
> +           is off.  */
> +        d1.signalling = 0;
> +        t = build_real (type, d1);
> +       return t;
> +      }
>        else if (REAL_VALUE_ISNAN (d2))
> -       return arg2;
> +      {
> +        /* Make resulting NaN value to be qNaN when flag_signaling_nans
> +           is off.  */
> +        d2.signalling = 0;
> +        t = build_real (type, d2);
> +       return t;
> +      }
>
>        inexact = real_arithmetic (&value, code, &d1, &d2);
>        real_convert (&result, mode, &value);
> @@ -1557,6 +1569,15 @@ const_binop (enum tree_code code, tree type, tree
>  tree
>  const_unop (enum tree_code code, tree type, tree arg0)
>  {
> +  /* Don't perform the operation, other than NEGATE and ABS, if
> +     flag_signaling_nans is on and the operand is a NaN.  */
> +  if (TREE_CODE (arg0) == REAL_CST
> +      && HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
> +      && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
> +      && code != NEGATE_EXPR
> +      && code != ABS_EXPR)
> +    return NULL_TREE;
> +
>    switch (code)
>      {
>      CASE_CONVERT:
> @@ -1964,7 +1985,17 @@ fold_convert_const_real_from_real (tree type, cons
>    REAL_VALUE_TYPE value;
>    tree t;
>
> +  /* Don't perform the operation if flag_signaling_nans is on
> +     and the operand is a NaN.  */
> +  if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
> +      && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
> +    return NULL_TREE;
> +
>    real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
> +  /* Make resulting NaN value to be qNaN when flag_signaling_nans
> +     is off.  */
> +  if (REAL_VALUE_ISNAN (value))
> +    value.signalling = 0;
>    t = build_real (type, value);
>
>    /* If converting an infinity or NAN to a representation that doesn't
> Index: gcc/real.c
> ===================================================================
> --- gcc/real.c  (revision 228700)
> +++ gcc/real.c  (working copy)
> @@ -545,6 +545,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE
>      case CLASS2 (rvc_normal, rvc_inf):
>        /* R + Inf = Inf.  */
>        *r = *b;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        r->sign = sign ^ subtract_p;
>        return false;
>
> @@ -558,6 +562,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE
>      case CLASS2 (rvc_inf, rvc_normal):
>        /* Inf + R = Inf.  */
>        *r = *a;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        return false;
>
>      case CLASS2 (rvc_inf, rvc_inf):
> @@ -680,6 +688,10 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_
>      case CLASS2 (rvc_nan, rvc_nan):
>        /* ANY * NaN = NaN.  */
>        *r = *b;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        r->sign = sign;
>        return false;
>
> @@ -688,6 +700,10 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_
>      case CLASS2 (rvc_nan, rvc_inf):
>        /* NaN * ANY = NaN.  */
>        *r = *a;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        r->sign = sign;
>        return false;
>
> @@ -830,6 +846,10 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY
>      case CLASS2 (rvc_nan, rvc_nan):
>        /* ANY / NaN = NaN.  */
>        *r = *b;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        r->sign = sign;
>        return false;
>
> @@ -838,6 +858,10 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY
>      case CLASS2 (rvc_nan, rvc_inf):
>        /* NaN / ANY = NaN.  */
>        *r = *a;
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        r->sign = sign;
>        return false;
>
> @@ -968,6 +992,10 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE
>      case rvc_zero:
>      case rvc_inf:
>      case rvc_nan:
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        break;
>
>      case rvc_normal:
> @@ -1026,7 +1054,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, co
>
>      case MIN_EXPR:
>        if (op1->cl == rvc_nan)
> +      {
>         *r = *op1;
> +        /* Make resulting NaN value to be qNaN. The caller has the
> +           responsibility to avoid the operation if flag_signaling_nans
> +           is on.  */
> +        r->signalling = 0;
> +      }
>        else if (do_compare (op0, op1, -1) < 0)
>         *r = *op0;
>        else
> @@ -1035,7 +1069,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, co
>
>      case MAX_EXPR:
>        if (op1->cl == rvc_nan)
> +      {
>         *r = *op1;
> +        /* Make resulting NaN value to be qNaN. The caller has the
> +           responsibility to avoid the operation if flag_signaling_nans
> +           is on.  */
> +        r->signalling = 0;
> +      }
>        else if (do_compare (op0, op1, 1) < 0)
>         *r = *op1;
>        else
> @@ -1166,6 +1206,10 @@ real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_T
>      case rvc_zero:
>      case rvc_inf:
>      case rvc_nan:
> +      /* Make resulting NaN value to be qNaN. The caller has the
> +         responsibility to avoid the operation if flag_signaling_nans
> +         is on.  */
> +      r->signalling = 0;
>        break;
>
>      case rvc_normal:
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c  (revision 228700)
> +++ gcc/simplify-rtx.c  (working copy)
> @@ -1801,16 +1801,25 @@ simplify_const_unary_operation (enum rtx_code code
>           d = real_value_negate (&d);
>           break;
>         case FLOAT_TRUNCATE:
> -         d = real_value_truncate (mode, d);
> +          /* Don't perform the operation if flag_signaling_nans is on
> +             and the operand is a NaN.  */
> +         if (!(HONOR_SNANS (mode) && REAL_VALUE_ISNAN (d)))
> +           d = real_value_truncate (mode, d);
>           break;
>         case FLOAT_EXTEND:
>           /* All this does is change the mode, unless changing
>              mode class.  */
> -         if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op)))
> +          /* Don't perform the operation if flag_signaling_nans is on
> +             and the operand is a NaN.  */
> +         if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op))
> +              && !(HONOR_SNANS (mode) && REAL_VALUE_ISNAN (d)))
>             real_convert (&d, mode, &d);
>           break;
>         case FIX:
> -         real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
> +          /* Don't perform the operation if flag_signaling_nans is on
> +             and the operand is a NaN.  */
> +         if (!(HONOR_SNANS (mode) && REAL_VALUE_ISNAN (d)))
> +           real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
>           break;
>         case NOT:
>           {
> Index: gcc/tree-ssa-math-opts.c
> ===================================================================
> --- gcc/tree-ssa-math-opts.c    (revision 228700)
> +++ gcc/tree-ssa-math-opts.c    (working copy)
> @@ -1486,6 +1486,13 @@ gimple_expand_builtin_pow (gimple_stmt_iterator *g
>    if (TREE_CODE (arg1) != REAL_CST)
>      return NULL_TREE;
>
> +  /* Don't perform the operation if flag_signaling_nans is on
> +     and the operand is a NaN.  */
> +  if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1)))
> +      && (REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
> +          || REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))))
> +    return NULL_TREE;
> +
>    /* If the exponent is equivalent to an integer, expand to an optimal
>       multiplication sequence when profitable.  */
>    c = TREE_REAL_CST (arg1);
> Index: gcc/testsuite/gcc.dg/pr61441.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/pr61441.c      (revision 0)
> +++ gcc/testsuite/gcc.dg/pr61441.c      (working copy)
> @@ -0,0 +1,61 @@
> +/* { dg-do run } */
> +/* { dg-options "-O1 -lm" } */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <math.h>
> +
> +void conversion()
> +{
> +  float sNaN = __builtin_nansf ("");
> +  double x = (double) sNaN;
> +  if (issignaling(x))
> +  {
> +    __builtin_abort();
> +  }
> +}
> +
> +enum op {Add, Mult, Div, Abs};
> +
> +void operation(enum op t)
> +{
> +  float x, y;
> +  float sNaN = __builtin_nansf ("");
> +  switch (t)
> +  {
> +    case Abs:
> +      x = fabs(sNaN);
> +      break;
> +    case Add:
> +      x = sNaN + 2.0;
> +      break;
> +    case Mult:
> +      x = sNaN * 2.0;
> +      break;
> +    case Div:
> +    default:
> +      x = sNaN / 2.0;
> +      break;
> +  }
> +  if (t == Abs)
> +  {
> +    if (!issignaling(x))
> +    {
> +      __builtin_abort();
> +    }
> +  }
> +  else if (issignaling(x))
> +  {
> +    __builtin_abort();
> +  }
> +}
> +
> +int main (void)
> +{
> +  conversion();
> +  operation(Add);
> +  operation(Mult);
> +  operation(Div);
> +  operation(Abs);
> +  return 0;
> +}
>
> On Wed, Sep 16, 2015 at 10:09 PM, Joseph Myers <jos...@codesourcery.com> 
> wrote:
>> On Wed, 16 Sep 2015, Sujoy Saraswati wrote:
>>
>>> > If -fsignaling-nans, then folding of expressions involving sNaNs should be
>>> > disabled, outside of static initializers - such expressions should not get
>>> > folded to return an sNaN (it's incorrect to fold sNaN + 1 to sNaN, for
>>> > example).  I think existing code may ensure that (the HONOR_SNANS check in
>>> > const_binop, for example).
>>>
>>> Yes, with -fsignaling-nans, the const_binop will not fold since the
>>> HONOR_SNANS check is there. However, elsewhere, like const_unop, the
>>> code doesn't do this check.
>>
>> Which would be a bug in the const_unop code, or the functions it calls
>> (for operations for which such a check is appropriate - as noted, abs and
>> negation should be folded unconditionally).
>>
>> --
>> Joseph S. Myers
>> jos...@codesourcery.com

Reply via email to