diff mbox

Fix 61441

Message ID CA+ZXfhXZWO8eOCYGPv3nomrfK7zzWHkXSJE++jw0heHxbQoqaA@mail.gmail.com
State New
Headers show

Commit Message

Sujoy Saraswati Sept. 1, 2015, 10:23 a.m. UTC
The following patch fixes 61441. It converts sNaN to qNaN on folding
when -fno-signaling-nans is used.

Bootstrap and regression tests on x86_64-linux-gnu and
aarch64-unknown-linux-gnu passed with changes done on trunk.

Is this fix fine ?

Regards,
Sujoy

2015-09-01  Sujoy Saraswati <ssaraswati@gmail.com>

        PR tree-optimization/61441
        * tree-ssa-ccp.c (convert_snan_to_qnan): Convert sNaN to qNaN when
        flag_signaling_nans is off.
        (ccp_fold_stmt, visit_assignment, visit_cond_stmt): call
        convert_snan_to_qnan to convert sNaN to qNaN on constant folding.

        PR tree-optimization/61441
        * gcc.dg/pr61441.c: New testcase.

Comments

Richard Biener Sept. 1, 2015, 12:21 p.m. UTC | #1
On Tue, Sep 1, 2015 at 12:23 PM, Sujoy Saraswati <ssaraswati@gmail.com> wrote:
> The following patch fixes 61441. It converts sNaN to qNaN on folding
> when -fno-signaling-nans is used.
>
> Bootstrap and regression tests on x86_64-linux-gnu and
> aarch64-unknown-linux-gnu passed with changes done on trunk.
>
> Is this fix fine ?

Note that I'm curious what
the actual bug is - is it that (double) sNaN creates a sNaN?  Then the fix
should be elsewhere, in constant folding itself
(fold_convert_const_real_from_real
or real_convert).

If that isn't the bug you have very many other passes to fix for the
same problem.

So - can you please explain?

Thanks,
Richard.

> Regards,
> Sujoy
>
> 2015-09-01  Sujoy Saraswati <ssaraswati@gmail.com>
>
>         PR tree-optimization/61441
>         * tree-ssa-ccp.c (convert_snan_to_qnan): Convert sNaN to qNaN when
>         flag_signaling_nans is off.
>         (ccp_fold_stmt, visit_assignment, visit_cond_stmt): call
>         convert_snan_to_qnan to convert sNaN to qNaN on constant folding.
>
>         PR tree-optimization/61441
>         * gcc.dg/pr61441.c: New testcase.
>
> Index: gcc/tree-ssa-ccp.c
> ===================================================================
> --- gcc/tree-ssa-ccp.c  (revision 226965)
> +++ gcc/tree-ssa-ccp.c  (working copy)
> @@ -560,6 +560,24 @@ value_to_wide_int (ccp_prop_value_t val)
>    return 0;
>  }
>
> +/* Convert sNaN to qNaN when flag_signaling_nans is off */
> +
> +static void
> +convert_snan_to_qnan (tree expr)
> +{
> +  if (expr
> +      && (TREE_CODE (expr) == REAL_CST)
> +      && !flag_signaling_nans)
> +  {
> +    REAL_VALUE_TYPE *d = TREE_REAL_CST_PTR (expr);
> +
> +    if (HONOR_NANS (TYPE_MODE (TREE_TYPE (expr)))
> +        && REAL_VALUE_ISNAN (*d)
> +        && d->signalling)
> +      d->signalling = 0;
> +  }
> +}
> +
>  /* Return the value for the address expression EXPR based on alignment
>     information.  */
>
> @@ -2156,6 +2174,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>         if (val.lattice_val != CONSTANT
>             || val.mask != 0)
>           return false;
> +        convert_snan_to_qnan (val.value);
>
>         if (dump_file)
>           {
> @@ -2197,7 +2216,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>             bool res;
>             if (!useless_type_conversion_p (TREE_TYPE (lhs),
>                                             TREE_TYPE (new_rhs)))
> +            {
>               new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
> +              convert_snan_to_qnan (new_rhs);
> +            }
>             res = update_call_from_tree (gsi, new_rhs);
>             gcc_assert (res);
>             return true;
> @@ -2216,6 +2238,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>              tree new_rhs = fold_builtin_alloca_with_align (stmt);
>              if (new_rhs)
>               {
> +                convert_snan_to_qnan (new_rhs);
>                 bool res = update_call_from_tree (gsi, new_rhs);
>                 tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
>                 gcc_assert (res);
> @@ -2260,7 +2283,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>           {
>             tree rhs = unshare_expr (val);
>             if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
> +            {
>               rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
> +              convert_snan_to_qnan (rhs);
> +            }
>             gimple_assign_set_rhs_from_tree (gsi, rhs);
>             return true;
>           }
> @@ -2292,6 +2318,7 @@ visit_assignment (gimple stmt, tree *output_p)
>        /* Evaluate the statement, which could be
>          either a GIMPLE_ASSIGN or a GIMPLE_CALL.  */
>        val = evaluate_stmt (stmt);
> +      convert_snan_to_qnan (val.value);
>
>        /* If STMT is an assignment to an SSA_NAME, we only have one
>          value to set.  */
> @@ -2324,6 +2351,7 @@ visit_cond_stmt (gimple stmt, edge *taken_edge_p)
>    if (val.lattice_val != CONSTANT
>        || val.mask != 0)
>      return SSA_PROP_VARYING;
> +  convert_snan_to_qnan (val.value);
>
>    /* Find which edge out of the conditional block will be taken and add it
>       to the worklist.  If no single edge can be determined statically,
>
> 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,17 @@
> +/* { dg-do run } */
> +/* { dg-options "-O1 -lm" } */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <math.h>
> +
> +int main (void)
> +{
> +  float sNaN = __builtin_nansf ("");
> +  double x = (double) sNaN;
> +  if (issignaling(x))
> +  {
> +    __builtin_abort();
> +  }
> +  return 0;
> +}
Sujoy Saraswati Sept. 2, 2015, 11:36 a.m. UTC | #2
Hi Richard,

> Note that I'm curious what
> the actual bug is - is it that (double) sNaN creates a sNaN?  Then the fix
> should be elsewhere, in constant folding itself
> (fold_convert_const_real_from_real
> or real_convert).
>
> If that isn't the bug you have very many other passes to fix for the
> same problem.
>
> So - can you please explain?

In this test case, the floating point operation for converting the
float to double is what should convert the sNaN to qNaN. I tried to
cover more floating point operations than just the conversion
operations exposed by this test case. For example, if we consider the
following program -

#define _GNU_SOURCE
#include <stdio.h>
#include <math.h>

int main (void)
{
  float x;
  float sNaN = __builtin_nansf ("");
  x = sNaN + .0;
  return issignaling(x);
}

The operation (sNaN + .0) should also result in qNaN after folding.
Hence, I thought of doing the sNaN to qNaN conversion in various
places under tree-ssa-ccp, where the result upon a folding is
available. I do agree that this approach may mean many more such
places should also be covered in other passes, but thought of sending
the fix for the ccp pass to start with.

Let me know if you suggest alternate approach.

Regards,
Sujoy

> Thanks,
> Richard.
>
>> Regards,
>> Sujoy
>>
>> 2015-09-01  Sujoy Saraswati <ssaraswati@gmail.com>
>>
>>         PR tree-optimization/61441
>>         * tree-ssa-ccp.c (convert_snan_to_qnan): Convert sNaN to qNaN when
>>         flag_signaling_nans is off.
>>         (ccp_fold_stmt, visit_assignment, visit_cond_stmt): call
>>         convert_snan_to_qnan to convert sNaN to qNaN on constant folding.
>>
>>         PR tree-optimization/61441
>>         * gcc.dg/pr61441.c: New testcase.
>>
>> Index: gcc/tree-ssa-ccp.c
>> ===================================================================
>> --- gcc/tree-ssa-ccp.c  (revision 226965)
>> +++ gcc/tree-ssa-ccp.c  (working copy)
>> @@ -560,6 +560,24 @@ value_to_wide_int (ccp_prop_value_t val)
>>    return 0;
>>  }
>>
>> +/* Convert sNaN to qNaN when flag_signaling_nans is off */
>> +
>> +static void
>> +convert_snan_to_qnan (tree expr)
>> +{
>> +  if (expr
>> +      && (TREE_CODE (expr) == REAL_CST)
>> +      && !flag_signaling_nans)
>> +  {
>> +    REAL_VALUE_TYPE *d = TREE_REAL_CST_PTR (expr);
>> +
>> +    if (HONOR_NANS (TYPE_MODE (TREE_TYPE (expr)))
>> +        && REAL_VALUE_ISNAN (*d)
>> +        && d->signalling)
>> +      d->signalling = 0;
>> +  }
>> +}
>> +
>>  /* Return the value for the address expression EXPR based on alignment
>>     information.  */
>>
>> @@ -2156,6 +2174,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>         if (val.lattice_val != CONSTANT
>>             || val.mask != 0)
>>           return false;
>> +        convert_snan_to_qnan (val.value);
>>
>>         if (dump_file)
>>           {
>> @@ -2197,7 +2216,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>             bool res;
>>             if (!useless_type_conversion_p (TREE_TYPE (lhs),
>>                                             TREE_TYPE (new_rhs)))
>> +            {
>>               new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
>> +              convert_snan_to_qnan (new_rhs);
>> +            }
>>             res = update_call_from_tree (gsi, new_rhs);
>>             gcc_assert (res);
>>             return true;
>> @@ -2216,6 +2238,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>              tree new_rhs = fold_builtin_alloca_with_align (stmt);
>>              if (new_rhs)
>>               {
>> +                convert_snan_to_qnan (new_rhs);
>>                 bool res = update_call_from_tree (gsi, new_rhs);
>>                 tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
>>                 gcc_assert (res);
>> @@ -2260,7 +2283,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>           {
>>             tree rhs = unshare_expr (val);
>>             if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
>> +            {
>>               rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
>> +              convert_snan_to_qnan (rhs);
>> +            }
>>             gimple_assign_set_rhs_from_tree (gsi, rhs);
>>             return true;
>>           }
>> @@ -2292,6 +2318,7 @@ visit_assignment (gimple stmt, tree *output_p)
>>        /* Evaluate the statement, which could be
>>          either a GIMPLE_ASSIGN or a GIMPLE_CALL.  */
>>        val = evaluate_stmt (stmt);
>> +      convert_snan_to_qnan (val.value);
>>
>>        /* If STMT is an assignment to an SSA_NAME, we only have one
>>          value to set.  */
>> @@ -2324,6 +2351,7 @@ visit_cond_stmt (gimple stmt, edge *taken_edge_p)
>>    if (val.lattice_val != CONSTANT
>>        || val.mask != 0)
>>      return SSA_PROP_VARYING;
>> +  convert_snan_to_qnan (val.value);
>>
>>    /* Find which edge out of the conditional block will be taken and add it
>>       to the worklist.  If no single edge can be determined statically,
>>
>> 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,17 @@
>> +/* { dg-do run } */
>> +/* { dg-options "-O1 -lm" } */
>> +
>> +#define _GNU_SOURCE
>> +#include <stdio.h>
>> +#include <math.h>
>> +
>> +int main (void)
>> +{
>> +  float sNaN = __builtin_nansf ("");
>> +  double x = (double) sNaN;
>> +  if (issignaling(x))
>> +  {
>> +    __builtin_abort();
>> +  }
>> +  return 0;
>> +}
Richard Biener Sept. 2, 2015, 11:56 a.m. UTC | #3
On Wed, Sep 2, 2015 at 1:36 PM, Sujoy Saraswati <ssaraswati@gmail.com> wrote:
> Hi Richard,
>
>> Note that I'm curious what
>> the actual bug is - is it that (double) sNaN creates a sNaN?  Then the fix
>> should be elsewhere, in constant folding itself
>> (fold_convert_const_real_from_real
>> or real_convert).
>>
>> If that isn't the bug you have very many other passes to fix for the
>> same problem.
>>
>> So - can you please explain?
>
> In this test case, the floating point operation for converting the
> float to double is what should convert the sNaN to qNaN. I tried to
> cover more floating point operations than just the conversion
> operations exposed by this test case. For example, if we consider the
> following program -
>
> #define _GNU_SOURCE
> #include <stdio.h>
> #include <math.h>
>
> int main (void)
> {
>   float x;
>   float sNaN = __builtin_nansf ("");
>   x = sNaN + .0;
>   return issignaling(x);
> }
>
> The operation (sNaN + .0) should also result in qNaN after folding.
> Hence, I thought of doing the sNaN to qNaN conversion in various
> places under tree-ssa-ccp, where the result upon a folding is
> available. I do agree that this approach may mean many more such
> places should also be covered in other passes, but thought of sending
> the fix for the ccp pass to start with.
>
> Let me know if you suggest alternate approach.

CCP and other passes ultimatively end up using fold-const.c:const_{unop,binop}
for constant folding so that is where the fix should go to (or to real.c).  That
will automatically handle other passes doing similar transforms.

Richard.

> Regards,
> Sujoy
>
>> Thanks,
>> Richard.
>>
>>> Regards,
>>> Sujoy
>>>
>>> 2015-09-01  Sujoy Saraswati <ssaraswati@gmail.com>
>>>
>>>         PR tree-optimization/61441
>>>         * tree-ssa-ccp.c (convert_snan_to_qnan): Convert sNaN to qNaN when
>>>         flag_signaling_nans is off.
>>>         (ccp_fold_stmt, visit_assignment, visit_cond_stmt): call
>>>         convert_snan_to_qnan to convert sNaN to qNaN on constant folding.
>>>
>>>         PR tree-optimization/61441
>>>         * gcc.dg/pr61441.c: New testcase.
>>>
>>> Index: gcc/tree-ssa-ccp.c
>>> ===================================================================
>>> --- gcc/tree-ssa-ccp.c  (revision 226965)
>>> +++ gcc/tree-ssa-ccp.c  (working copy)
>>> @@ -560,6 +560,24 @@ value_to_wide_int (ccp_prop_value_t val)
>>>    return 0;
>>>  }
>>>
>>> +/* Convert sNaN to qNaN when flag_signaling_nans is off */
>>> +
>>> +static void
>>> +convert_snan_to_qnan (tree expr)
>>> +{
>>> +  if (expr
>>> +      && (TREE_CODE (expr) == REAL_CST)
>>> +      && !flag_signaling_nans)
>>> +  {
>>> +    REAL_VALUE_TYPE *d = TREE_REAL_CST_PTR (expr);
>>> +
>>> +    if (HONOR_NANS (TYPE_MODE (TREE_TYPE (expr)))
>>> +        && REAL_VALUE_ISNAN (*d)
>>> +        && d->signalling)
>>> +      d->signalling = 0;
>>> +  }
>>> +}
>>> +
>>>  /* Return the value for the address expression EXPR based on alignment
>>>     information.  */
>>>
>>> @@ -2156,6 +2174,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>         if (val.lattice_val != CONSTANT
>>>             || val.mask != 0)
>>>           return false;
>>> +        convert_snan_to_qnan (val.value);
>>>
>>>         if (dump_file)
>>>           {
>>> @@ -2197,7 +2216,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>             bool res;
>>>             if (!useless_type_conversion_p (TREE_TYPE (lhs),
>>>                                             TREE_TYPE (new_rhs)))
>>> +            {
>>>               new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
>>> +              convert_snan_to_qnan (new_rhs);
>>> +            }
>>>             res = update_call_from_tree (gsi, new_rhs);
>>>             gcc_assert (res);
>>>             return true;
>>> @@ -2216,6 +2238,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>              tree new_rhs = fold_builtin_alloca_with_align (stmt);
>>>              if (new_rhs)
>>>               {
>>> +                convert_snan_to_qnan (new_rhs);
>>>                 bool res = update_call_from_tree (gsi, new_rhs);
>>>                 tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
>>>                 gcc_assert (res);
>>> @@ -2260,7 +2283,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>           {
>>>             tree rhs = unshare_expr (val);
>>>             if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
>>> +            {
>>>               rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
>>> +              convert_snan_to_qnan (rhs);
>>> +            }
>>>             gimple_assign_set_rhs_from_tree (gsi, rhs);
>>>             return true;
>>>           }
>>> @@ -2292,6 +2318,7 @@ visit_assignment (gimple stmt, tree *output_p)
>>>        /* Evaluate the statement, which could be
>>>          either a GIMPLE_ASSIGN or a GIMPLE_CALL.  */
>>>        val = evaluate_stmt (stmt);
>>> +      convert_snan_to_qnan (val.value);
>>>
>>>        /* If STMT is an assignment to an SSA_NAME, we only have one
>>>          value to set.  */
>>> @@ -2324,6 +2351,7 @@ visit_cond_stmt (gimple stmt, edge *taken_edge_p)
>>>    if (val.lattice_val != CONSTANT
>>>        || val.mask != 0)
>>>      return SSA_PROP_VARYING;
>>> +  convert_snan_to_qnan (val.value);
>>>
>>>    /* Find which edge out of the conditional block will be taken and add it
>>>       to the worklist.  If no single edge can be determined statically,
>>>
>>> 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,17 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O1 -lm" } */
>>> +
>>> +#define _GNU_SOURCE
>>> +#include <stdio.h>
>>> +#include <math.h>
>>> +
>>> +int main (void)
>>> +{
>>> +  float sNaN = __builtin_nansf ("");
>>> +  double x = (double) sNaN;
>>> +  if (issignaling(x))
>>> +  {
>>> +    __builtin_abort();
>>> +  }
>>> +  return 0;
>>> +}
Sujoy Saraswati Sept. 2, 2015, 12:16 p.m. UTC | #4
> CCP and other passes ultimatively end up using fold-const.c:const_{unop,binop}
> for constant folding so that is where the fix should go to (or to real.c).  That
> will automatically handle other passes doing similar transforms.

Thanks for the tip. I will modify my fix and post it.

Regards,
Sujoy

>
> Richard.
>
>> Regards,
>> Sujoy
>>
>>> Thanks,
>>> Richard.
>>>
>>>> Regards,
>>>> Sujoy
>>>>
>>>> 2015-09-01  Sujoy Saraswati <ssaraswati@gmail.com>
>>>>
>>>>         PR tree-optimization/61441
>>>>         * tree-ssa-ccp.c (convert_snan_to_qnan): Convert sNaN to qNaN when
>>>>         flag_signaling_nans is off.
>>>>         (ccp_fold_stmt, visit_assignment, visit_cond_stmt): call
>>>>         convert_snan_to_qnan to convert sNaN to qNaN on constant folding.
>>>>
>>>>         PR tree-optimization/61441
>>>>         * gcc.dg/pr61441.c: New testcase.
>>>>
>>>> Index: gcc/tree-ssa-ccp.c
>>>> ===================================================================
>>>> --- gcc/tree-ssa-ccp.c  (revision 226965)
>>>> +++ gcc/tree-ssa-ccp.c  (working copy)
>>>> @@ -560,6 +560,24 @@ value_to_wide_int (ccp_prop_value_t val)
>>>>    return 0;
>>>>  }
>>>>
>>>> +/* Convert sNaN to qNaN when flag_signaling_nans is off */
>>>> +
>>>> +static void
>>>> +convert_snan_to_qnan (tree expr)
>>>> +{
>>>> +  if (expr
>>>> +      && (TREE_CODE (expr) == REAL_CST)
>>>> +      && !flag_signaling_nans)
>>>> +  {
>>>> +    REAL_VALUE_TYPE *d = TREE_REAL_CST_PTR (expr);
>>>> +
>>>> +    if (HONOR_NANS (TYPE_MODE (TREE_TYPE (expr)))
>>>> +        && REAL_VALUE_ISNAN (*d)
>>>> +        && d->signalling)
>>>> +      d->signalling = 0;
>>>> +  }
>>>> +}
>>>> +
>>>>  /* Return the value for the address expression EXPR based on alignment
>>>>     information.  */
>>>>
>>>> @@ -2156,6 +2174,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>>         if (val.lattice_val != CONSTANT
>>>>             || val.mask != 0)
>>>>           return false;
>>>> +        convert_snan_to_qnan (val.value);
>>>>
>>>>         if (dump_file)
>>>>           {
>>>> @@ -2197,7 +2216,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>>             bool res;
>>>>             if (!useless_type_conversion_p (TREE_TYPE (lhs),
>>>>                                             TREE_TYPE (new_rhs)))
>>>> +            {
>>>>               new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
>>>> +              convert_snan_to_qnan (new_rhs);
>>>> +            }
>>>>             res = update_call_from_tree (gsi, new_rhs);
>>>>             gcc_assert (res);
>>>>             return true;
>>>> @@ -2216,6 +2238,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>>              tree new_rhs = fold_builtin_alloca_with_align (stmt);
>>>>              if (new_rhs)
>>>>               {
>>>> +                convert_snan_to_qnan (new_rhs);
>>>>                 bool res = update_call_from_tree (gsi, new_rhs);
>>>>                 tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
>>>>                 gcc_assert (res);
>>>> @@ -2260,7 +2283,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
>>>>           {
>>>>             tree rhs = unshare_expr (val);
>>>>             if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
>>>> +            {
>>>>               rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
>>>> +              convert_snan_to_qnan (rhs);
>>>> +            }
>>>>             gimple_assign_set_rhs_from_tree (gsi, rhs);
>>>>             return true;
>>>>           }
>>>> @@ -2292,6 +2318,7 @@ visit_assignment (gimple stmt, tree *output_p)
>>>>        /* Evaluate the statement, which could be
>>>>          either a GIMPLE_ASSIGN or a GIMPLE_CALL.  */
>>>>        val = evaluate_stmt (stmt);
>>>> +      convert_snan_to_qnan (val.value);
>>>>
>>>>        /* If STMT is an assignment to an SSA_NAME, we only have one
>>>>          value to set.  */
>>>> @@ -2324,6 +2351,7 @@ visit_cond_stmt (gimple stmt, edge *taken_edge_p)
>>>>    if (val.lattice_val != CONSTANT
>>>>        || val.mask != 0)
>>>>      return SSA_PROP_VARYING;
>>>> +  convert_snan_to_qnan (val.value);
>>>>
>>>>    /* Find which edge out of the conditional block will be taken and add it
>>>>       to the worklist.  If no single edge can be determined statically,
>>>>
>>>> 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,17 @@
>>>> +/* { dg-do run } */
>>>> +/* { dg-options "-O1 -lm" } */
>>>> +
>>>> +#define _GNU_SOURCE
>>>> +#include <stdio.h>
>>>> +#include <math.h>
>>>> +
>>>> +int main (void)
>>>> +{
>>>> +  float sNaN = __builtin_nansf ("");
>>>> +  double x = (double) sNaN;
>>>> +  if (issignaling(x))
>>>> +  {
>>>> +    __builtin_abort();
>>>> +  }
>>>> +  return 0;
>>>> +}
diff mbox

Patch

Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c  (revision 226965)
+++ gcc/tree-ssa-ccp.c  (working copy)
@@ -560,6 +560,24 @@  value_to_wide_int (ccp_prop_value_t val)
   return 0;
 }

+/* Convert sNaN to qNaN when flag_signaling_nans is off */
+
+static void
+convert_snan_to_qnan (tree expr)
+{
+  if (expr
+      && (TREE_CODE (expr) == REAL_CST)
+      && !flag_signaling_nans)
+  {
+    REAL_VALUE_TYPE *d = TREE_REAL_CST_PTR (expr);
+
+    if (HONOR_NANS (TYPE_MODE (TREE_TYPE (expr)))
+        && REAL_VALUE_ISNAN (*d)
+        && d->signalling)
+      d->signalling = 0;
+  }
+}
+
 /* Return the value for the address expression EXPR based on alignment
    information.  */

@@ -2156,6 +2174,7 @@  ccp_fold_stmt (gimple_stmt_iterator *gsi)
        if (val.lattice_val != CONSTANT
            || val.mask != 0)
          return false;
+        convert_snan_to_qnan (val.value);

        if (dump_file)
          {
@@ -2197,7 +2216,10 @@  ccp_fold_stmt (gimple_stmt_iterator *gsi)
            bool res;
            if (!useless_type_conversion_p (TREE_TYPE (lhs),
                                            TREE_TYPE (new_rhs)))
+            {
              new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
+              convert_snan_to_qnan (new_rhs);
+            }
            res = update_call_from_tree (gsi, new_rhs);
            gcc_assert (res);
            return true;
@@ -2216,6 +2238,7 @@  ccp_fold_stmt (gimple_stmt_iterator *gsi)
             tree new_rhs = fold_builtin_alloca_with_align (stmt);
             if (new_rhs)
              {
+                convert_snan_to_qnan (new_rhs);
                bool res = update_call_from_tree (gsi, new_rhs);
                tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
                gcc_assert (res);
@@ -2260,7 +2283,10 @@  ccp_fold_stmt (gimple_stmt_iterator *gsi)
          {
            tree rhs = unshare_expr (val);
            if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+            {
              rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
+              convert_snan_to_qnan (rhs);
+            }
            gimple_assign_set_rhs_from_tree (gsi, rhs);
            return true;
          }
@@ -2292,6 +2318,7 @@  visit_assignment (gimple stmt, tree *output_p)
       /* Evaluate the statement, which could be
         either a GIMPLE_ASSIGN or a GIMPLE_CALL.  */
       val = evaluate_stmt (stmt);
+      convert_snan_to_qnan (val.value);

       /* If STMT is an assignment to an SSA_NAME, we only have one
         value to set.  */
@@ -2324,6 +2351,7 @@  visit_cond_stmt (gimple stmt, edge *taken_edge_p)
   if (val.lattice_val != CONSTANT
       || val.mask != 0)
     return SSA_PROP_VARYING;
+  convert_snan_to_qnan (val.value);

   /* Find which edge out of the conditional block will be taken and add it
      to the worklist.  If no single edge can be determined statically,

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,17 @@ 
+/* { dg-do run } */
+/* { dg-options "-O1 -lm" } */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <math.h>
+
+int main (void)
+{
+  float sNaN = __builtin_nansf ("");
+  double x = (double) sNaN;
+  if (issignaling(x))
+  {
+    __builtin_abort();
+  }
+  return 0;
+}