[PATCH] Fix floating point handling in dom (PR tree-optimization/84235)

Jakub Jelinek jakub@redhat.com
Tue Feb 6 20:40:00 GMT 2018


Hi!

As the following testcase shows, dom2 miscompiles floating point x - x
into 0.0 even when x could be infinity and x - x then a NaN.
The corresponding match.pd optimization is:
/* Simplify x - x.
   This is unsafe for certain floats even in non-IEEE formats.
   In IEEE, it is unsafe because it does wrong for NaNs.
   Also note that operand_equal_p is always false if an operand
   is volatile.  */
(simplify
 (minus @0 @0)
 (if (!FLOAT_TYPE_P (type) || !HONOR_NANS (type))
  { build_zero_cst (type); }))
The patch makes it match what match.pd does.
We also have:
 /* X / X is one.  */
 (simplify
  (div @0 @0)
  /* But not for 0 / 0 so that we can get the proper warnings and errors.
     And not for _Fract types where we can't build 1.  */
  (if (!integer_zerop (@0) && !ALL_FRACT_MODE_P (TYPE_MODE (type)))
   { build_one_cst (type); }))
We can ignore the 0 / 0 case, we have both operands SSA_NAMEs and match.pd
only avoids optimizing away literal 0 / 0, but the rest is valid, some fract
types don't have a way to express 1.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-02-06  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/84235
	* tree-ssa-scopedtables.c
	(avail_exprs_stack::simplify_binary_operation): Fir MINUS_EXPR, punt
	if the subtraction is performed in floating point type where NaNs are
	honored.  For *DIV_EXPR, punt for ALL_FRACT_MODE_Ps where we can't
	build 1.  Formatting fix.

	* gcc.c-torture/execute/ieee/pr84235.c: New test.

--- gcc/tree-ssa-scopedtables.c.jj	2018-01-03 10:19:54.528533857 +0100
+++ gcc/tree-ssa-scopedtables.c	2018-02-06 14:58:08.944673984 +0100
@@ -182,8 +182,15 @@ avail_exprs_stack::simplify_binary_opera
 		      case BIT_AND_EXPR:
 			return gimple_assign_rhs1 (stmt);
 
-		      case BIT_XOR_EXPR:
 		      case MINUS_EXPR:
+			/* This is unsafe for certain floats even in non-IEEE
+			   formats.  In IEEE, it is unsafe because it does
+			   wrong for NaNs.  */
+			if (FLOAT_TYPE_P (result_type)
+			    && HONOR_NANS (result_type))
+			  break;
+			/* FALLTHRU */
+		      case BIT_XOR_EXPR:
 		      case TRUNC_MOD_EXPR:
 		      case CEIL_MOD_EXPR:
 		      case FLOOR_MOD_EXPR:
@@ -195,6 +202,9 @@ avail_exprs_stack::simplify_binary_opera
 		      case FLOOR_DIV_EXPR:
 		      case ROUND_DIV_EXPR:
 		      case EXACT_DIV_EXPR:
+			/* Avoid _Fract types where we can't build 1.  */
+			if (ALL_FRACT_MODE_P (TYPE_MODE (result_type)))
+			  break;
 			return build_one_cst (result_type);
 
 		      default:
@@ -204,8 +214,8 @@ avail_exprs_stack::simplify_binary_opera
 		break;
 	      }
 
-	      default:
-		break;
+	    default:
+	      break;
 	    }
 	}
     }
--- gcc/testsuite/gcc.c-torture/execute/ieee/pr84235.c.jj	2018-02-06 15:04:26.528454766 +0100
+++ gcc/testsuite/gcc.c-torture/execute/ieee/pr84235.c	2018-02-06 15:05:06.836341334 +0100
@@ -0,0 +1,11 @@
+/* PR tree-optimization/84235 */
+
+int
+main ()
+{
+  double d = 1.0 / 0.0;
+  _Bool b = d == d && (d - d) != (d - d);
+  if (!b)
+    __builtin_abort ();
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list