RE: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
Hi, > If you have access to x86_64-linux, you can easily test it yourself with: > make -C gcc check-gcc RUNTESTFLAGS='--target_board=unix\{-m64,-m32/- > march=i386\} dg.exp=pr61441.c' > > Your patch does help. Thanks, I tested the changes and it worked fine. > issignalling is a GNU extension of glibc, so supposedly you should limit the > test to the targets that use glibc, so either > /* { dg-do run { target { *-*-linux* *-*-gnu* } } } */ > or perhaps specific target-supports.exp test for this (I wonder if android > and/or uclibc support it). I am making the change to limit it to Linux and gnu targets as you mentioned above. The Github for android/uclibc seems to indicate they don't support it. I checked in the changed test case as - Index: gcc/testsuite/gcc.dg/pr61441.c === --- gcc/testsuite/gcc.dg/pr61441.c (revision 232151) +++ gcc/testsuite/gcc.dg/pr61441.c (working copy) @@ -1,5 +1,5 @@ -/* { dg-do run } */ -/* { dg-options "-O1 -lm" } */ +/* { dg-do run { target { *-*-linux* *-*-gnu* } } } */ +/* { dg-options "-O1 -lm -fexcess-precision=standard" } */ #define _GNU_SOURCE #include @@ -56,6 +56,8 @@ int main (void) operation(Add); operation(Mult); operation(Div); +#if __FLT_EVAL_METHOD__ == 0 operation(Abs); +#endif return 0; } Regards, Sujoy
Re: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
On Thu, Jan 07, 2016 at 06:48:25AM +, Saraswati, Sujoy (OSTL) wrote: > Hi, > > > On Thu, Nov 26, 2015 at 08:38:55AM +, Saraswati, Sujoy (OSTL) wrote: > > > PR tree-optimization/61441 > > > * gcc.dg/pr61441.c: New testcase. > > > > Note the testcase fails on i686-linux, and even -fexcess-precision=standard > > doesn't help (-ffloat-store works, but that is a big hammer and we really > > don't want it for targets without excess precision). > > At least with -fexcess-precision=standard, the problem is in the fabs case, > > with -fexcess-precision=standard the value is then rounded from long > > double to double and that rounding affects the signalling bit. > > So, either the testcase should be compiled with -fexcess-precision=standard > > and the operation(Abs) case be guarded with #if __FLT_EVAL_METHOD__ > > == 0, or something similar. > > I modified the test case as below - If you have access to x86_64-linux, you can easily test it yourself with: make -C gcc check-gcc RUNTESTFLAGS='--target_board=unix\{-m64,-m32/-march=i386\} dg.exp=pr61441.c' Your patch does help. issignalling is a GNU extension of glibc, so supposedly you should limit the test to the targets that use glibc, so either /* { dg-do run { target { *-*-linux* *-*-gnu* } } } */ or perhaps specific target-supports.exp test for this (I wonder if android and/or uclibc support it). > I did a search on the https://gcc.gnu.org/ml/gcc-testresults/2015-12/ but > couldn't see a failure report for this - is there place where I could look up > to see the test results for various architectures ? Perhaps H.J. uses differently configured i686-linux build? If it is configured with --with-fpmath=sse or =avx, then i387 is only used for long double and therefore the target is not excess precision target any longer. Jakub
RE: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
Hi, > On Thu, Nov 26, 2015 at 08:38:55AM +, Saraswati, Sujoy (OSTL) wrote: > > PR tree-optimization/61441 > > * gcc.dg/pr61441.c: New testcase. > > Note the testcase fails on i686-linux, and even -fexcess-precision=standard > doesn't help (-ffloat-store works, but that is a big hammer and we really > don't want it for targets without excess precision). > At least with -fexcess-precision=standard, the problem is in the fabs case, > with -fexcess-precision=standard the value is then rounded from long > double to double and that rounding affects the signalling bit. > So, either the testcase should be compiled with -fexcess-precision=standard > and the operation(Abs) case be guarded with #if __FLT_EVAL_METHOD__ > == 0, or something similar. I modified the test case as below - Index: testsuite/gcc.dg/pr61441.c === --- testsuite/gcc.dg/pr61441.c (revision 232121) +++ testsuite/gcc.dg/pr61441.c (working copy) @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O1 -lm" } */ +/* { dg-options "-O1 -lm -fexcess-precision=standard" } */ #define _GNU_SOURCE #include @@ -56,6 +56,8 @@ int main (void) operation(Add); operation(Mult); operation(Div); +#if __FLT_EVAL_METHOD__ == 0 operation(Abs); +#endif return 0; } However, I do not have access to a i686-linux box to test it out. Let me know if this looks fine. I did a search on the https://gcc.gnu.org/ml/gcc-testresults/2015-12/ but couldn't see a failure report for this - is there place where I could look up to see the test results for various architectures ? There was another issue reported on https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61441, where the test fails on arm-none-eabi with unresolved symbol for issignaling(). Apparently, the newlib's math.h doesn't have the issignaling macro - let me know if I need to modify the test case to take care of this. Regards, Sujoy
Re: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
On Thu, Nov 26, 2015 at 08:38:55AM +, Saraswati, Sujoy (OSTL) wrote: > PR tree-optimization/61441 > * gcc.dg/pr61441.c: New testcase. Note the testcase fails on i686-linux, and even -fexcess-precision=standard doesn't help (-ffloat-store works, but that is a big hammer and we really don't want it for targets without excess precision). At least with -fexcess-precision=standard, the problem is in the fabs case, with -fexcess-precision=standard the value is then rounded from long double to double and that rounding affects the signalling bit. So, either the testcase should be compiled with -fexcess-precision=standard and the operation(Abs) case be guarded with #if __FLT_EVAL_METHOD__ == 0, or something similar. Jakub
RE: Fix 61441 [ 1/5] Add REAL_VALUE_ISSIGNALING_NAN
Hi, > If you haven't set up write-access to the repository, please go ahead and get > that process started: > > https://www.gnu.org/software/gcc/svnwrite.html > > You can list me as your sponsor on the form. > > Once your account is set up, you can commit patches which have been > approved. > > I'll go ahead and approve #1, #2 and #4. Richi has approved #3. Thank you. I have filled the form for https://sourceware.org/cgi-bin/pdw/ps_form.cgi and mentioned you as the sponsor. I will commit the changes once the sourceware.org account request comes through. > I'm still looking at #5. I received your comments on this. I will correct the spelling mistakes as well as the space-tab usage and post it. Regards, Sujoy > Jeff
Re: Fix 61441 [ 1/5] Add REAL_VALUE_ISSIGNALING_NAN
On 11/26/2015 01:27 AM, Saraswati, Sujoy (OSTL) wrote: Hi, This series of patches fixes PR61441. The fix is broken into 5 patches. The first one adds REAL_VALUE_ISSIGNALING_NAN. 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * real.c (real_issignaling_nan): New. * real.h (real_issignaling_nan, REAL_VALUE_ISSIGNALING_NAN): New. If you haven't set up write-access to the repository, please go ahead and get that process started: https://www.gnu.org/software/gcc/svnwrite.html You can list me as your sponsor on the form. Once your account is set up, you can commit patches which have been approved. I'll go ahead and approve #1, #2 and #4. Richi has approved #3. I'm still looking at #5. Jeff
Re: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
On 11/26/2015 01:38 AM, Saraswati, Sujoy (OSTL) wrote: Hi, This patch avoids various transformations with signaling NaN operands when flag_signaling_nans is on, to avoid folding which would lose exceptions. A test case for this change is also added as part of this patch. Regards, Sujoy 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * 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 an sNaN. (fold_convert_const_real_from_real): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (integer_valued_real_unary_p): Update comment stating it returns false for sNaN values. (integer_valued_real_binary_p, integer_valued_real_call_p): Same. (integer_valued_real_single_p): Same. (integer_valued_real_invalid_p, integer_valued_real_p): Same. * fold-const-call.c (fold_const_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (fold_const_builtin_load_exponent) Same. (fold_const_call_sss): Same for BUILT_IN_POWI. * gimple-fold.c (gimple_assign_integer_valued_real_p): Same. (gimple_call_integer_valued_real_p): Same. (gimple_phi_integer_valued_real_p): Same. (gimple_stmt_integer_valued_real_p): Same. * simplify-rtx.c (simplify_const_unary_operation): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (simplify_const_binary_operation): Same. * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. PR tree-optimization/61441 * gcc.dg/pr61441.c: New testcase. === diff -u -p a/gcc/fold-const.c b/gcc/fold-const.c --- a/gcc/fold-const.c 2015-11-25 15:24:49.656116740 +0530 +++ b/gcc/fold-const.c 2015-11-25 15:25:07.712117294 +0530 @@ -1166,9 +1166,21 @@ const_binop (enum tree_code code, tree a /* 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; + } I was a bit worried about this hunk, but by the time we get here we already know that at least one operand is a sNaN and that we're not honoring sNaNs. inexact = real_arithmetic (, code, , ); real_convert (, mode, ); @@ -1538,6 +1550,15 @@ const_binop (enum tree_code code, tree t 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_ISSIGNALING_NAN (TREE_REAL_CST (arg0)) + && code != NEGATE_EXPR + && code != ABS_EXPR) +return NULL_TREE; Why let NEGATE_EXPR and ABS_EXPR pass through here? I realize that these can often be implemented with bit-twiddling, so they're usually considered special. BUt in this case aren't we just dealing with constants and wouldn't we want to still express the neg/abs so that we get a signal when the input value is sNaN rather than collapse down to a constant? /* Return true if the floating point result of (CODE OP0) has an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. s/signalling/signaling/ I think it shows up in multiple places, so check for it using search/replace. Also watch for using 8 spaces rather than a tab in your patches. I think I see occurrences of that mistake in this patch. SO just check everything you changed to be sure you aren't adding new instances of that nit. I think a bit of explanation why you're letting NEGATE/ABS though in const_unop, fixing the spelling goof and the instead of 8 spaces nit need to be addressed before this can be committed. jeff
Re: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
On Wed, 2 Dec 2015, Jeff Law wrote: > Why let NEGATE_EXPR and ABS_EXPR pass through here? I realize that these can > often be implemented with bit-twiddling, so they're usually considered > special. BUt in this case aren't we just dealing with constants and wouldn't > we want to still express the neg/abs so that we get a signal when the input > value is sNaN rather than collapse down to a constant? See IEEE 754-2008, 5.5.1. "Implementations shall provide the following homogeneous quiet-computational sign bit operations for all supported arithmetic formats; they only affect the sign bit. The operations treat floating-point numbers and NaNs alike, and signal no exception. These operations may propagate non-canonical encodings.". -- Joseph S. Myers jos...@codesourcery.com
Re: Fix 61441 [5/5] Disable various transformations for signaling NaN operands
On 12/02/2015 12:08 PM, Joseph Myers wrote: On Wed, 2 Dec 2015, Jeff Law wrote: Why let NEGATE_EXPR and ABS_EXPR pass through here? I realize that these can often be implemented with bit-twiddling, so they're usually considered special. BUt in this case aren't we just dealing with constants and wouldn't we want to still express the neg/abs so that we get a signal when the input value is sNaN rather than collapse down to a constant? See IEEE 754-2008, 5.5.1. "Implementations shall provide the following homogeneous quiet-computational sign bit operations for all supported arithmetic formats; they only affect the sign bit. The operations treat floating-point numbers and NaNs alike, and signal no exception. These operations may propagate non-canonical encodings.". Ah, in that case, nevermind :-) So I think it's just the spelling and whitespace nits that need to be fixed. jeff
RE: Fix 61441
Hi, > I think the general principle is: > > * The caller decides whether folding is desirable (whether it would lose > exceptions, for example). > > * The real.c code is called only when the caller has decided that folding is > desirable, and should always produce the correct output (which for a > conversion means producing a quiet NaN from a signaling NaN). > > So both places need changes, but real_convert is where the code that makes > it a quiet NaN should go. > > Another place in the patch that looks incorrect: the changes to fold-const- > call.c calling real_powi and checking if the result is a signaling NaN. The > result > of real_powi should never be a signaling NaN. > Rather, real_powi should produce a quiet NaN if its input is a signaling NaN, > and the callers should check if the argument is a signaling NaN when deciding > whether to fold, not if the result is. I made the changes accordingly and will post the patches now. Regards, Sujoy > -- > Joseph S. Myers > jos...@codesourcery.com
Fix 61441 [ 1/5] Add REAL_VALUE_ISSIGNALING_NAN
Hi, This series of patches fixes PR61441. The fix is broken into 5 patches. The first one adds REAL_VALUE_ISSIGNALING_NAN. 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * real.c (real_issignaling_nan): New. * real.h (real_issignaling_nan, REAL_VALUE_ISSIGNALING_NAN): New. Index: gcc/real.c === --- gcc/real.c (revision 230851) +++ gcc/real.c (working copy) @@ -1195,6 +1195,13 @@ real_isnan (const REAL_VALUE_TYPE *r) return (r->cl == rvc_nan); } +/* Determine whether a floating-point value X is a signalling NaN. */ +bool +real_issignaling_nan (const REAL_VALUE_TYPE *r) +{ + return real_isnan (r) && r->signalling; +} + /* Determine whether a floating-point value X is finite. */ bool Index: gcc/real.h === --- gcc/real.h (revision 230851) +++ gcc/real.h (working copy) @@ -262,6 +262,9 @@ extern bool real_isinf (const REAL_VALUE_TYPE *); /* Determine whether a floating-point value X is a NaN. */ extern bool real_isnan (const REAL_VALUE_TYPE *); +/* Determine whether a floating-point value X is a signalling NaN. */ +extern bool real_issignaling_nan (const REAL_VALUE_TYPE *); + /* Determine whether a floating-point value X is finite. */ extern bool real_isfinite (const REAL_VALUE_TYPE *); @@ -357,6 +360,9 @@ extern const struct real_format arm_half_format; /* Determine whether a floating-point value X is a NaN. */ #define REAL_VALUE_ISNAN(x)real_isnan (&(x)) +/* Determine whether a floating-point value X is a signalling NaN. */ +#define REAL_VALUE_ISSIGNALING_NAN(x) real_issignaling_nan (&(x)) + /* Determine whether a floating-point value X is negative. */ #define REAL_VALUE_NEGATIVE(x) real_isneg (&(x))
Fix 61441 [2/5] Use REAL_VALUE_ISSIGNALING_NAN instead of REAL_VALUE_ISNAN where appropriate
This patch uses REAL_VALUE_ISSIGNALING_NAN instead of REAL_VALUE_ISNAN to avoid the operation for sNaN. Regards, Sujoy 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * fold-const.c (const_binop): Use REAL_VALUE_ISSIGNALING_NAN instead of REAL_VALUE_ISNAN to avoid the operation for sNaN. * simplify-rtx.c (simplify_const_binary_operation) Same. Index: gcc/fold-const.c === --- gcc/fold-const.c(revision 230851) +++ gcc/fold-const.c(working copy) @@ -1150,9 +1150,10 @@ const_binop (enum tree_code code, tree arg1, tree mode = TYPE_MODE (type); /* Don't perform operation if we honor signaling NaNs and -either operand is a NaN. */ +either operand is a signaling NaN. */ if (HONOR_SNANS (mode) - && (REAL_VALUE_ISNAN (d1) || REAL_VALUE_ISNAN (d2))) + && (REAL_VALUE_ISSIGNALING_NAN (d1) + || REAL_VALUE_ISSIGNALING_NAN (d2))) return NULL_TREE; /* Don't perform operation if it would raise a division Index: gcc/simplify-rtx.c === --- gcc/simplify-rtx.c (revision 230851) +++ gcc/simplify-rtx.c (working copy) @@ -3892,7 +3892,8 @@ simplify_const_binary_operation (enum rtx_code cod real_convert (, mode, CONST_DOUBLE_REAL_VALUE (op1)); if (HONOR_SNANS (mode) - && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1))) + && (REAL_VALUE_ISSIGNALING_NAN (f0) + || REAL_VALUE_ISSIGNALING_NAN (f1))) return 0; if (code == DIV
Fix 61441 [3/5] Remove flag_errno_math check for RINT
Hi, This patch removes flag_errno_math check for RINT, treating it similar to nearbyint. Regards, Sujoy 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * match.pd (f(x) -> x): Removed flag_errno_math check for RINT. Index: gcc/match.pd === --- gcc/match.pd(revision 230851) +++ gcc/match.pd(working copy) @@ -2565,16 +2565,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (fns (fns @0)) (fns @0))) /* f(x) -> x if x is integer valued and f does nothing for such values. */ -(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT) +(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT RINT) (simplify (fns integer_valued_real_p@0) @0)) -/* Same for rint. We have to check flag_errno_math because - integer_valued_real_p accepts +Inf, -Inf and NaNs as integers. */ -(if (!flag_errno_math) - (simplify - (RINT integer_valued_real_p@0) - @0)) /* hypot(x,0) and hypot(0,x) -> abs(x). */ (simplify
Fix 61441 [4/5] Produce quiet NaN for real value operations
Hi, This patch makes resulting NaN values to be quiet NaN for real value operations, irrespective of the flag_signaling_nans flag. The caller has the responsibility to avoid the operation if flag_signaling_nans is on. Regards, Sujoy 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * real.c (do_add): Make resulting NaN value to be qNaN. (do_multiply, do_divide, do_fix_trunc): Same. (real_arithmetic, real_ldexp, real_convert): Same. (real_isinteger): Updated comment stating it returns false for sNaN. === diff -u -p a/gcc/real.c b/gcc/real.c --- a/gcc/real.c2015-11-25 10:35:29.059583459 +0530 +++ b/gcc/real.c2015-11-25 15:07:53.604085529 +0530 @@ -541,6 +541,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_V 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; @@ -554,6 +558,10 @@ do_add (REAL_VALUE_TYPE *r, const REAL_V 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): @@ -676,6 +684,10 @@ do_multiply (REAL_VALUE_TYPE *r, const R 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; @@ -684,6 +696,10 @@ do_multiply (REAL_VALUE_TYPE *r, const R 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; @@ -826,6 +842,10 @@ do_divide (REAL_VALUE_TYPE *r, const REA 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; @@ -834,6 +854,10 @@ do_divide (REAL_VALUE_TYPE *r, const REA 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; @@ -964,6 +988,10 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const 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: @@ -1022,7 +1050,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int 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 @@ -1031,7 +1065,13 @@ real_arithmetic (REAL_VALUE_TYPE *r, int 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 @@ -1162,6 +1202,10 @@ real_ldexp (REAL_VALUE_TYPE *r, const RE 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: @@ -2731,6 +2775,12 @@ real_convert (REAL_VALUE_TYPE *r, format round_for_format (fmt, r); + /* Make resulting NaN value to be qNaN. The caller has the + responsibility to avoid the operation if flag_signaling_nans + is on. */ + if (r->cl == rvc_nan) +r->signalling = 0; + /* round_for_format de-normalizes denormals. Undo just that
Fix 61441 [5/5] Disable various transformations for signaling NaN operands
Hi, This patch avoids various transformations with signaling NaN operands when flag_signaling_nans is on, to avoid folding which would lose exceptions. A test case for this change is also added as part of this patch. Regards, Sujoy 2015-11-26 Sujoy SaraswatiPR tree-optimization/61441 * 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 an sNaN. (fold_convert_const_real_from_real): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (integer_valued_real_unary_p): Update comment stating it returns false for sNaN values. (integer_valued_real_binary_p, integer_valued_real_call_p): Same. (integer_valued_real_single_p): Same. (integer_valued_real_invalid_p, integer_valued_real_p): Same. * fold-const-call.c (fold_const_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (fold_const_builtin_load_exponent) Same. (fold_const_call_sss): Same for BUILT_IN_POWI. * gimple-fold.c (gimple_assign_integer_valued_real_p): Same. (gimple_call_integer_valued_real_p): Same. (gimple_phi_integer_valued_real_p): Same. (gimple_stmt_integer_valued_real_p): Same. * simplify-rtx.c (simplify_const_unary_operation): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (simplify_const_binary_operation): Same. * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. PR tree-optimization/61441 * gcc.dg/pr61441.c: New testcase. === diff -u -p a/gcc/fold-const.c b/gcc/fold-const.c --- a/gcc/fold-const.c 2015-11-25 15:24:49.656116740 +0530 +++ b/gcc/fold-const.c 2015-11-25 15:25:07.712117294 +0530 @@ -1166,9 +1166,21 @@ const_binop (enum tree_code code, tree a /* 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 (, code, , ); real_convert (, mode, ); @@ -1538,6 +1550,15 @@ const_binop (enum tree_code code, tree t 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_ISSIGNALING_NAN (TREE_REAL_CST (arg0)) + && code != NEGATE_EXPR + && code != ABS_EXPR) +return NULL_TREE; + switch (code) { CASE_CONVERT: @@ -1949,6 +1970,12 @@ fold_convert_const_real_from_real (tree 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_ISSIGNALING_NAN (TREE_REAL_CST (arg1))) +return NULL_TREE; + real_convert (, TYPE_MODE (type), _REAL_CST (arg1)); t = build_real (type, value); @@ -13420,7 +13447,7 @@ tree_single_nonzero_warnv_p (tree t, boo /* Return true if the floating point result of (CODE OP0) has an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13453,7 +13480,7 @@ integer_valued_real_unary_p (tree_code c /* Return true if the floating point result of (CODE OP0 OP1) has an integer value. We also allow +Inf, -Inf and NaN to be considered - integer values. + integer values. Return false for signalling NaN. DEPTH is the current nesting depth of the query. */ @@ -13477,8 +13504,8 @@ integer_valued_real_binary_p (tree_code /* Return true if the floating point result of calling FNDECL with arguments ARG0 and ARG1 has an integer value. We also allow +Inf, -Inf and NaN to be - considered integer values. If FNDECL takes fewer than 2 arguments, - the remaining ARGn are null. + considered integer values. Return
Re: Fix 61441 [3/5] Remove flag_errno_math check for RINT
On Thu, Nov 26, 2015 at 9:31 AM, Saraswati, Sujoy (OSTL)wrote: > Hi, > This patch removes flag_errno_math check for RINT, treating it similar to > nearbyint. > Regards, > Sujoy Ok. Richard. > 2015-11-26 Sujoy Saraswati > > PR tree-optimization/61441 > * match.pd (f(x) -> x): Removed flag_errno_math check for RINT. > > Index: gcc/match.pd > === > --- gcc/match.pd(revision 230851) > +++ gcc/match.pd(working copy) > @@ -2565,16 +2565,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) >(fns (fns @0)) >(fns @0))) > /* f(x) -> x if x is integer valued and f does nothing for such values. */ > -(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT) > +(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT RINT) > (simplify >(fns integer_valued_real_p@0) >@0)) > -/* Same for rint. We have to check flag_errno_math because > - integer_valued_real_p accepts +Inf, -Inf and NaNs as integers. */ > -(if (!flag_errno_math) > - (simplify > - (RINT integer_valued_real_p@0) > - @0)) > > /* hypot(x,0) and hypot(0,x) -> abs(x). */ > (simplify
Re: Fix 61441
On Fri, 6 Nov 2015, Sujoy Saraswati wrote: > > Shouldn't real_convert do this rather than the caller needing to do it? > > Yes, it should be. I had started by doing this within real_convert but > then saw that there are quite a few callers where I should add the > check for flag_signaling_nans. This was making the patch bigger, so > instead decided to change the caller in this particular case. I will > try to make the change in real_convert now that we are planning to > break the patch. I think the general principle is: * The caller decides whether folding is desirable (whether it would lose exceptions, for example). * The real.c code is called only when the caller has decided that folding is desirable, and should always produce the correct output (which for a conversion means producing a quiet NaN from a signaling NaN). So both places need changes, but real_convert is where the code that makes it a quiet NaN should go. Another place in the patch that looks incorrect: the changes to fold-const-call.c calling real_powi and checking if the result is a signaling NaN. The result of real_powi should never be a signaling NaN. Rather, real_powi should produce a quiet NaN if its input is a signaling NaN, and the callers should check if the argument is a signaling NaN when deciding whether to fold, not if the result is. -- Joseph S. Myers jos...@codesourcery.com
Re: Fix 61441
Hi, > It seems this code has moved to fold-const.c, so the patch will need > updating. I have updated the patch and sending again. > Now, is it actually correct for integer_valued_real_single_p (now) to > treat sNaN as an integer? Looking at existing uses, they all appear to be > in match.pd: it's used for removing redundant trunc / floor / ceil / round > / nearbyint on integer values. In such cases, it's *incorrect* to count > sNaN as an integer, because while those functions map qNaN quietly to > qNaN, they should map sNaN to qNaN and raise "invalid" in the process. So > I don't think you should have this change at all. Ok. I have also updated the comments for the functions stating they return false for sNaN. > (I don't see why the handling of rint checks flag_errno_math. rint should > quietly return infinite and qNaN arguments just like nearbyint; it never > needs to set errno and distinguishing rint / nearbyint here is spurious; > the only difference is regarding the "inexact" exception.) With these changes, real_isinteger returns false for sNaN. This in turn means that integer_valued_real_p would return false with sNaN. This means that for sNaN, rint will not go to the path of checking flag_errno_math. Anyway, I modified that also as part of this patch to make rint similar to nearbyint. > I realise this corresponds to some existing code (in const_binop, at > least), but I don't think that existing code is a good model. > > If -fsignaling-nans, it's still perfectly fine to fold when the argument > is a quiet NaN. So what you actually want in such cases where you have a > known constant argument - as opposed to an unknown argument that might or > might not be constant - is to check whether that argument is itself a > signaling NaN. So you want to add a new REAL_VALUE_ISSIGNALING, or > something like that. And then find existing code that has the wrong (NaN > and sNaNs supported) check and convert it to checking (this value is > sNaN). > > (This code has also moved to another function in fold-const.c, it seems.) > > Cf. the match.pd handling of fmin / fmax checking for signaling NaN > arguments explicitly. > > Some other places in this patch have similar issues with checking > HONOR_SNANS && REAL_VALUE_ISNAN when they should check if the particular > value is sNaN. I modified the code to check for sNaN specifically. The modified patch is below. Bootstrap and regression tests on x86_64-linux-gnu passed with changes done on trunk. Is this fine ? Regards, Sujoy 2015-11-04 Sujoy SaraswatiPR tree-optimization/61441 * fold-const-call.c (fold_const_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (fold_const_call_sss): Same for BUILT_IN_POWI. * 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 an sNaN. (fold_convert_const_real_from_real): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (integer_valued_real_unary_p): Update comment stating it returns false for sNaN values. (integer_valued_real_binary_p, integer_valued_real_call_p): Same. (integer_valued_real_single_p): Same. (integer_valued_real_invalid_p, integer_valued_real_p): Same. * gimple-fold.c (gimple_assign_integer_valued_real_p): Same. (gimple_call_integer_valued_real_p): Same. (gimple_phi_integer_valued_real_p): Same. (gimple_stmt_integer_valued_real_p): Same. * match.pd (f(x) -> x): Removed flag_errno_math check for RINT. * real.c (do_add): Make resulting NaN value to be qNaN. (do_multiply, do_divide, do_fix_trunc): Same. (real_arithmetic, real_ldexp): Same. (real_issignaling_nan): New. (real_isinteger): Updated comment stating it returns false for sNaN. * real.h (real_issignaling_nan, REAL_VALUE_ISSIGNALING_NAN): New. * simplify-rtx.c (simplify_const_unary_operation): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. (simplify_const_binary_operation): Check for sNaN instead of NaN. * tree-ssa-math-opts.c (gimple_expand_builtin_pow): Avoid the operation if flag_signaling_nans is on and the operand is an sNaN. PR tree-optimization/61441 * gcc.dg/pr61441.c: New testcase. Index: gcc/fold-const-call.c === --- gcc/fold-const-call.c (revision 229805) +++ gcc/fold-const-call.c (working copy) @@ -484,7 +484,11 @@ fold_const_pow (real_value *result, const real_val || !real_equal (arg0, ))) { bool inexact = real_powi (result, format, arg0, n1); - if (flag_unsafe_math_optimizations || !inexact) + /* Avoid the folding if flag_signaling_nans is on. */ +
Re: Fix 61441
On Thu, 5 Nov 2015, Sujoy Saraswati wrote: > > Some other places in this patch have similar issues with checking > > HONOR_SNANS && REAL_VALUE_ISNAN when they should check if the particular > > value is sNaN. > > I modified the code to check for sNaN specifically. The modified patch > is below. This is looking pretty close to ready to go in, but the patch also seems to be doing several things at once and it might be easier to review if split into separate logical pieces. For example (this is an illustration, not necessarily saying it should be exactly this way): (1) Add REAL_VALUE_ISSIGNALING_NAN and convert existing logic that already does something equivalent (so no semantic change, just cleanup). (2) Convert existing code that checks for all NaNs in cases where REAL_VALUE_ISSIGNALING_NAN would be enough. (3) Treat rint and nearbyint the same. (4) Make real.c operations properly produce quiet NaNs for operations with signaling NaN input. (5) Disable various transformations for signaling NaN operands, where folding them loses exceptions. This patch is also getting big enough that it would be a good idea to complete the copyright assignment paperwork, certainly if you plan to make more contributions in future, if you're not covered by a corporate assignment. > @@ -1943,7 +1965,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_ISSIGNALING_NAN (TREE_REAL_CST (arg1))) > +return NULL_TREE; > + >real_convert (, TYPE_MODE (type), _REAL_CST (arg1)); > + /* Make resulting NaN value to be qNaN when flag_signaling_nans > + is off. */ > + if (REAL_VALUE_ISSIGNALING_NAN (value)) > +value.signalling = 0; Shouldn't real_convert do this rather than the caller needing to do it? -- Joseph S. Myers jos...@codesourcery.com
Re: Fix 61441
Hi, > This is looking pretty close to ready to go in, but the patch also seems > to be doing several things at once and it might be easier to review if > split into separate logical pieces. For example (this is an illustration, > not necessarily saying it should be exactly this way): (1) Add > REAL_VALUE_ISSIGNALING_NAN and convert existing logic that already does > something equivalent (so no semantic change, just cleanup). (2) Convert > existing code that checks for all NaNs in cases where > REAL_VALUE_ISSIGNALING_NAN would be enough. (3) Treat rint and nearbyint > the same. (4) Make real.c operations properly produce quiet NaNs for > operations with signaling NaN input. (5) Disable various transformations > for signaling NaN operands, where folding them loses exceptions. Thanks, I will break it up into multiple patches as you proposed. > This patch is also getting big enough that it would be a good idea to > complete the copyright assignment paperwork, certainly if you plan to make > more contributions in future, if you're not covered by a corporate > assignment. I have a corporate assignment, I will post the patches from my corporate email id. >> @@ -1943,7 +1965,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_ISSIGNALING_NAN (TREE_REAL_CST (arg1))) >> +return NULL_TREE; >> + >>real_convert (, TYPE_MODE (type), _REAL_CST (arg1)); >> + /* Make resulting NaN value to be qNaN when flag_signaling_nans >> + is off. */ >> + if (REAL_VALUE_ISSIGNALING_NAN (value)) >> +value.signalling = 0; > > Shouldn't real_convert do this rather than the caller needing to do it? Yes, it should be. I had started by doing this within real_convert but then saw that there are quite a few callers where I should add the check for flag_signaling_nans. This was making the patch bigger, so instead decided to change the caller in this particular case. I will try to make the change in real_convert now that we are planning to break the patch. Regards, Sujoy > -- > Joseph S. Myers > jos...@codesourcery.com
Re: Fix 61441
On Tue, 13 Oct 2015, Sujoy Saraswati wrote: > 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; It seems this code has moved to fold-const.c, so the patch will need updating. Now, is it actually correct for integer_valued_real_single_p (now) to treat sNaN as an integer? Looking at existing uses, they all appear to be in match.pd: it's used for removing redundant trunc / floor / ceil / round / nearbyint on integer values. In such cases, it's *incorrect* to count sNaN as an integer, because while those functions map qNaN quietly to qNaN, they should map sNaN to qNaN and raise "invalid" in the process. So I don't think you should have this change at all. (I don't see why the handling of rint checks flag_errno_math. rint should quietly return infinite and qNaN arguments just like nearbyint; it never needs to set errno and distinguishing rint / nearbyint here is spurious; the only difference is regarding the "inexact" exception.) > @@ -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 (, TYPE_MODE (type), ); > - return build_real (type, r); > + /* Avoid the folding if flag_signaling_nans is on. */ > + if (!(HONOR_SNANS (TYPE_MODE (type)) > +&& REAL_VALUE_ISNAN (x))) I realise this corresponds to some existing code (in const_binop, at least), but I don't think that existing code is a good model. If -fsignaling-nans, it's still perfectly fine to fold when the argument is a quiet NaN. So what you actually want in such cases where you have a known constant argument - as opposed to an unknown argument that might or might not be constant - is to check whether that argument is itself a signaling NaN. So you want to add a new REAL_VALUE_ISSIGNALING, or something like that. And then find existing code that has the wrong (NaN and sNaNs supported) check and convert it to checking (this value is sNaN). (This code has also moved to another function in fold-const.c, it seems.) Cf. the match.pd handling of fmin / fmax checking for signaling NaN arguments explicitly. Some other places in this patch have similar issues with checking HONOR_SNANS && REAL_VALUE_ISNAN when they should check if the particular value is sNaN. -- Joseph S. Myers jos...@codesourcery.com
Re: [Ping] Fix 61441
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 (, TYPE_MODE (type), ); > - 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 (, TYPE_MODE (type), ); > +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 (, TYPE_MODE (type), , 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 (, TYPE_MODE (type), , 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 (, TYPE_MODE (type), , 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 >
Re: Fix 61441
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 SaraswatiPR 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 (, TYPE_MODE (type), ); - 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 (, TYPE_MODE (type), ); +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 (, TYPE_MODE (type), , 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 (, TYPE_MODE (type), , 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 (, TYPE_MODE (type), , 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 (, code, , ); real_convert (, mode, ); @@ -1557,6 +1569,15 @@ const_binop (enum tree_code code, tree type, tree tree const_unop (enum tree_code code,
Re: Fix 61441
Hi, >> I'll leave the correctness part of the patch to Joseph who knows FP >> arithmetic better than me, >> implementation-wise this is ok if you fix the REAL_CST sharing issue. Ok, will change this. > Changing fold_abs_const is wrong - abs of sNaN is sNaN, no exceptions > raised. Changing real_arithmetic is wrong for the NEGATE_EXPR and > ABS_EXPR cases, both of which should just affect the sign bit without > quieting sNaNs. Right, I had thought unary operators will be similar to binary operators for this. Will fix this. > All the comments in the patch should end with ". " (full stop, two > spaces). Ok. > 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. > Inside static initializers, expressions involving sNaNs still need to be > folded (so sNaN + 1 becomes qNaN inside such an initializer, for example, > with the translation-time exception being discarded). Again, existing > code should handle this: START_FOLD_INIT / END_FOLD_INIT already handle > clearing and restoring flag_signaling_nans. Yes. > My understanding of the design of the existing code is that real.c will do > the arithmetic regardless of whether it might raise an exception or have > rounding-mode-dependent results, with fold-const.c being responsible for > deciding whether the result can be used to fold the expression in > question. That is, you shouldn't need any flag_signaling_nans conditions > in real.c; rather, if IEEE semantics mean an sNaN is quieted, real.c > should do so unconditionally. It should be the callers in fold-const.c > that check HONOR_SNANS and disallow folding when it would lose exceptions. I had added the flag_signaling_nans condition within real.c so that the callers can do the folding, with the sNaN value converted to qNaN. However, as you mention, the real.c design should do this irrespective of the signaling flag and leave it for the callers to disallow the folding. I will make the modifications and post a patch. Regards, Sujoy > > -- > Joseph S. Myers > jos...@codesourcery.com
Re: Fix 61441
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
Re: Fix 61441
On Thu, Sep 10, 2015 at 9:30 AM, Sujoy Saraswatiwrote: > Hi, > Here is a modified patch for this. The change this time is in > fold-const.c and real.c. > > 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-09-10 Sujoy Saraswati > > PR tree-optimization/61441 > * fold-const.c (const_binop, fold_abs_const): Convert > sNaN to qNaN when flag_signaling_nans is off. > * real.c (do_add, do_multiply, do_divide, do_fix_trunc): Same. > (real_arithmetic, real_ldexp, real_convert): Same > > PR tree-optimization/61441 > * gcc.dg/pr61441.c: New testcase. > > Index: gcc/fold-const.c > === > --- gcc/fold-const.c(revision 227584) > +++ gcc/fold-const.c(working copy) > @@ -1183,9 +1183,19 @@ 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)) > + { > +/* Convert sNaN to qNaN when flag_signaling_nans is off */ > +if (!flag_signaling_nans) > + (TREE_REAL_CST_PTR (arg1))->signalling = 0; As REAL_CSTs can be shared you need to build a new one, you can't modify it in place. I'll leave the correctness part of the patch to Joseph who knows FP arithmetic better than me, implementation-wise this is ok if you fix the REAL_CST sharing issue. Thanks, Richard. > return arg1; > + } >else if (REAL_VALUE_ISNAN (d2)) > + { > +/* Convert sNaN to qNaN when flag_signaling_nans is off */ > +if (!flag_signaling_nans) > + (TREE_REAL_CST_PTR (arg1))->signalling = 0; > return arg2; > + } > >inexact = real_arithmetic (, code, , ); >real_convert (, mode, ); > @@ -13644,6 +13654,9 @@ fold_abs_const (tree arg0, tree type) > t = build_real (type, real_value_negate (_REAL_CST (arg0))); >else > t = arg0; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +(TREE_REAL_CST_PTR (t))->signalling = 0; >break; > > default: > Index: gcc/real.c > === > --- gcc/real.c (revision 227584) > +++ gcc/real.c (working copy) > @@ -545,6 +545,9 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE > case CLASS2 (rvc_normal, rvc_inf): >/* R + Inf = Inf. */ >*r = *b; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >r->sign = sign ^ subtract_p; >return false; > > @@ -558,6 +561,9 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE > case CLASS2 (rvc_inf, rvc_normal): >/* Inf + R = Inf. */ >*r = *a; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >return false; > > case CLASS2 (rvc_inf, rvc_inf): > @@ -680,6 +686,9 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_ > case CLASS2 (rvc_nan, rvc_nan): >/* ANY * NaN = NaN. */ >*r = *b; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >r->sign = sign; >return false; > > @@ -688,6 +697,9 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_ > case CLASS2 (rvc_nan, rvc_inf): >/* NaN * ANY = NaN. */ >*r = *a; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >r->sign = sign; >return false; > > @@ -830,6 +842,9 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY > case CLASS2 (rvc_nan, rvc_nan): >/* ANY / NaN = NaN. */ >*r = *b; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >r->sign = sign; >return false; > > @@ -838,6 +853,9 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY > case CLASS2 (rvc_nan, rvc_inf): >/* NaN / ANY = NaN. */ >*r = *a; > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >r->sign = sign; >return false; > > @@ -968,6 +986,9 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE > case rvc_zero: > case rvc_inf: > case rvc_nan: > + /* Convert sNaN to qNaN when flag_signaling_nans is off */ > + if (!flag_signaling_nans) > +r->signalling = 0; >break; > > case rvc_normal: > @@ -1059,6 +1080,11 @@ real_arithmetic
Re: Fix 61441
On Mon, 14 Sep 2015, Richard Biener wrote: > I'll leave the correctness part of the patch to Joseph who knows FP > arithmetic better than me, > implementation-wise this is ok if you fix the REAL_CST sharing issue. Changing fold_abs_const is wrong - abs of sNaN is sNaN, no exceptions raised. Changing real_arithmetic is wrong for the NEGATE_EXPR and ABS_EXPR cases, both of which should just affect the sign bit without quieting sNaNs. All the comments in the patch should end with ". " (full stop, two spaces). 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). Inside static initializers, expressions involving sNaNs still need to be folded (so sNaN + 1 becomes qNaN inside such an initializer, for example, with the translation-time exception being discarded). Again, existing code should handle this: START_FOLD_INIT / END_FOLD_INIT already handle clearing and restoring flag_signaling_nans. My understanding of the design of the existing code is that real.c will do the arithmetic regardless of whether it might raise an exception or have rounding-mode-dependent results, with fold-const.c being responsible for deciding whether the result can be used to fold the expression in question. That is, you shouldn't need any flag_signaling_nans conditions in real.c; rather, if IEEE semantics mean an sNaN is quieted, real.c should do so unconditionally. It should be the callers in fold-const.c that check HONOR_SNANS and disallow folding when it would lose exceptions. -- Joseph S. Myers jos...@codesourcery.com
Re: Fix 61441
Hi, Here is a modified patch for this. The change this time is in fold-const.c and real.c. 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-09-10 Sujoy SaraswatiPR tree-optimization/61441 * fold-const.c (const_binop, fold_abs_const): Convert sNaN to qNaN when flag_signaling_nans is off. * real.c (do_add, do_multiply, do_divide, do_fix_trunc): Same. (real_arithmetic, real_ldexp, real_convert): Same PR tree-optimization/61441 * gcc.dg/pr61441.c: New testcase. Index: gcc/fold-const.c === --- gcc/fold-const.c(revision 227584) +++ gcc/fold-const.c(working copy) @@ -1183,9 +1183,19 @@ 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)) + { +/* Convert sNaN to qNaN when flag_signaling_nans is off */ +if (!flag_signaling_nans) + (TREE_REAL_CST_PTR (arg1))->signalling = 0; return arg1; + } else if (REAL_VALUE_ISNAN (d2)) + { +/* Convert sNaN to qNaN when flag_signaling_nans is off */ +if (!flag_signaling_nans) + (TREE_REAL_CST_PTR (arg1))->signalling = 0; return arg2; + } inexact = real_arithmetic (, code, , ); real_convert (, mode, ); @@ -13644,6 +13654,9 @@ fold_abs_const (tree arg0, tree type) t = build_real (type, real_value_negate (_REAL_CST (arg0))); else t = arg0; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +(TREE_REAL_CST_PTR (t))->signalling = 0; break; default: Index: gcc/real.c === --- gcc/real.c (revision 227584) +++ gcc/real.c (working copy) @@ -545,6 +545,9 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE case CLASS2 (rvc_normal, rvc_inf): /* R + Inf = Inf. */ *r = *b; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; r->sign = sign ^ subtract_p; return false; @@ -558,6 +561,9 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE case CLASS2 (rvc_inf, rvc_normal): /* Inf + R = Inf. */ *r = *a; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; return false; case CLASS2 (rvc_inf, rvc_inf): @@ -680,6 +686,9 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_ case CLASS2 (rvc_nan, rvc_nan): /* ANY * NaN = NaN. */ *r = *b; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; r->sign = sign; return false; @@ -688,6 +697,9 @@ do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_ case CLASS2 (rvc_nan, rvc_inf): /* NaN * ANY = NaN. */ *r = *a; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; r->sign = sign; return false; @@ -830,6 +842,9 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY case CLASS2 (rvc_nan, rvc_nan): /* ANY / NaN = NaN. */ *r = *b; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; r->sign = sign; return false; @@ -838,6 +853,9 @@ do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TY case CLASS2 (rvc_nan, rvc_inf): /* NaN / ANY = NaN. */ *r = *a; + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; r->sign = sign; return false; @@ -968,6 +986,9 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE case rvc_zero: case rvc_inf: case rvc_nan: + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; break; case rvc_normal: @@ -1059,6 +1080,11 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, co default: gcc_unreachable (); } + + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; + return false; } @@ -1150,6 +1176,9 @@ real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_T case rvc_zero: case rvc_inf: case rvc_nan: + /* Convert sNaN to qNaN when flag_signaling_nans is off */ + if (!flag_signaling_nans) +r->signalling = 0; break; case rvc_normal: @@ -2718,6 +2747,10 @@ real_convert (REAL_VALUE_TYPE *r, machine_mode mod
Re: Fix 61441
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 #include 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>> >> 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 >>
Re: Fix 61441
On Wed, Sep 2, 2015 at 1:36 PM, Sujoy Saraswatiwrote: > 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 > #include > > 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 >>> >>> 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
Re: Fix 61441
> 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 SaraswatiPR 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 +#include + +int main (void) +{ + float sNaN = __builtin_nansf (""); + double x = (double) sNaN; + if (issignaling(x)) + { +__builtin_abort(); + } + return 0; +}
Fix 61441
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 SaraswatiPR 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 +#include + +int main (void) +{ + float sNaN = __builtin_nansf (""); + double x = (double) sNaN; + if (issignaling(x)) + { +__builtin_abort(); + } + return 0; +}
Re: Fix 61441
On Tue, Sep 1, 2015 at 12:23 PM, Sujoy Saraswatiwrote: > 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 > > 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 > +#include > + > +int main (void) > +{ > + float sNaN = __builtin_nansf (""); > + double x = (double) sNaN; > + if (issignaling(x)) > + { > +__builtin_abort(); > + } > + return 0; > +}