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.