aboutsummaryrefslogtreecommitdiff
path: root/gcc/simplify-rtx.c
diff options
context:
space:
mode:
authorSujoy Saraswati <sujoy.saraswati@hpe.com>2015-12-22 14:04:30 +0000
committerSujoy Saraswati <ssaraswati@gcc.gnu.org>2015-12-22 14:04:30 +0000
commit5a00b0aaf036edadc48861b91d3804796525c2d5 (patch)
treeb911e1bd2a2f7a4a924f976f2156da6ea60dc25c /gcc/simplify-rtx.c
parent9643ce888b6634d4f6c44ad3c48bd105f38474e8 (diff)
downloadgcc-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.c39
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)))