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