Message ID | CA+ZXfhXZWO8eOCYGPv3nomrfK7zzWHkXSJE++jw0heHxbQoqaA@mail.gmail.com |
---|---|
State | New |
Headers | show |
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; > +}
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; >> +}
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; >>> +}
> 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; >>>> +}
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; +}