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 Saraswati <sujoy.sarasw...@hpe.com>

             PR 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 (&value, code, &d1, &d2);
        real_convert (&result, mode, &value);
@@ -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 <tab> instead of 8 spaces nit need to be addressed before this can be committed.

jeff

Reply via email to