https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90356

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2019-05-06
           Assignee|unassigned at gcc dot gnu.org      |jakub at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Untested fix:
--- gcc/match.pd.jj     2019-05-03 15:22:07.370401908 +0200
+++ gcc/match.pd        2019-05-06 11:26:04.701663020 +0200
@@ -152,6 +152,28 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (fold_real_zero_addition_p (type, @1, 1))
   (non_lvalue @0)))

+/* Even if the fold_real_zero_addition_p can't simplify X + 0.0
+   into X, we can optimize (X + 0.0) + 0.0 or (X + 0.0) - 0.0
+   or (X - 0.0) + 0.0 into X + 0.0 and (X - 0.0) - 0.0 into X - 0.0
+   if not -frounding-math.  For sNaNs the first operation would raise
+   exceptions but turn the result into qNan, so the second operation
+   would not raise it.   */
+(for inner_op (plus minus)
+ (for outer_op (plus minus)
+  (simplify
+   (outer_op (inner_op @0 real_zerop@1) real_zerop@2)
+    (if (TREE_CODE (@1) == REAL_CST
+        && TREE_CODE (@2) == REAL_CST
+        && HONOR_SIGNED_ZEROS (element_mode (type))
+        && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type)))
+     (with { bool plus1 = ((inner_op == PLUS_EXPR)
+                          ^ REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)));
+            bool plus2 = ((outer_op == PLUS_EXPR)
+                          ^ REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@2))); }
+      (if (plus2 && !plus1)
+       (outer_op @0 @2)
+       (inner_op @0 @1)))))))
+
 /* 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.

Reply via email to