diff options
author | Sujoy Saraswati <sujoy.saraswati@hpe.com> | 2015-12-22 14:04:30 +0000 |
---|---|---|
committer | Sujoy Saraswati <ssaraswati@gcc.gnu.org> | 2015-12-22 14:04:30 +0000 |
commit | 5a00b0aaf036edadc48861b91d3804796525c2d5 (patch) | |
tree | b911e1bd2a2f7a4a924f976f2156da6ea60dc25c /gcc/simplify-rtx.c | |
parent | 9643ce888b6634d4f6c44ad3c48bd105f38474e8 (diff) | |
download | gcc-5a00b0aaf036edadc48861b91d3804796525c2d5.zip gcc-5a00b0aaf036edadc48861b91d3804796525c2d5.tar.gz gcc-5a00b0aaf036edadc48861b91d3804796525c2d5.tar.bz2 |
This series of patches fix PR61441.
This series of patches fix PR61441. This patch avoids various transformations
with signaling NaN operands when flag_signaling_nans is on, to avoid folding
which would lose exceptions.
Bootstrapped & regression-tested on x86_64-linux-gnu.
gcc/
* 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 CASE_CFN_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.
* gcc.dg/pr61441.c: New testcase.
From-SVN: r231901
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 39 |
1 files changed, 32 insertions, 7 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 225742e..44de1555 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1703,6 +1703,12 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, } real_from_integer (&d, mode, std::make_pair (op, op_mode), SIGNED); + + /* Avoid the folding if flag_signaling_nans is on and + operand is a signaling NaN. */ + if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) + return 0; + d = real_value_truncate (mode, d); return const_double_from_real_value (d, mode); } @@ -1721,6 +1727,12 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, } real_from_integer (&d, mode, std::make_pair (op, op_mode), UNSIGNED); + + /* Avoid the folding if flag_signaling_nans is on and + operand is a signaling NaN. */ + if (HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d)) + return 0; + d = real_value_truncate (mode, d); return const_double_from_real_value (d, mode); } @@ -1825,16 +1837,25 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, 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 signaling NaN. */ + if (!(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (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 signaling NaN. */ + if (GET_MODE_CLASS (mode) != GET_MODE_CLASS (GET_MODE (op)) + && !(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (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 signaling NaN. */ + if (!(HONOR_SNANS (mode) && REAL_VALUE_ISSIGNALING_NAN (d))) + real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL); break; case NOT: { @@ -3886,16 +3907,20 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode, else { REAL_VALUE_TYPE f0, f1, value, result; + const REAL_VALUE_TYPE *opr0, *opr1; bool inexact; - real_convert (&f0, mode, CONST_DOUBLE_REAL_VALUE (op0)); - real_convert (&f1, mode, CONST_DOUBLE_REAL_VALUE (op1)); + opr0 = CONST_DOUBLE_REAL_VALUE (op0); + opr1 = CONST_DOUBLE_REAL_VALUE (op1); if (HONOR_SNANS (mode) - && (REAL_VALUE_ISSIGNALING_NAN (f0) - || REAL_VALUE_ISSIGNALING_NAN (f1))) + && (REAL_VALUE_ISSIGNALING_NAN (*opr0) + || REAL_VALUE_ISSIGNALING_NAN (*opr1))) return 0; + real_convert (&f0, mode, opr0); + real_convert (&f1, mode, opr1); + if (code == DIV && real_equal (&f1, &dconst0) && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode))) |