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