For `(i == j) || (i < j)` this can be combined to just `i <= j` without
worrying about removal of a trap as a NaN would cause the the equal to be
false which will cause not to short circuit and the trapping instruction
will always be executed.

`(i != j) && (i < j)` has the same reasoning.

Bootstrapped and tested on x86_64-linux-gnu.

        PR tree-optimization/126138

gcc/ChangeLog:

        * fold-const.cc (combine_comparisons): Allow eq to combine
        with || and ne combine with eq if the original rcode was trapping
        and the new code is trapping.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/fp-trapping-cmp-1.c: New test.

Signed-off-by: Andrea Pinski <[email protected]>
---
 gcc/fold-const.cc                             | 13 +++++++++---
 .../gcc.dg/tree-ssa/fp-trapping-cmp-1.c       | 21 +++++++++++++++++++
 2 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index d80d6ed1f86..34cdfa243a0 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -3002,14 +3002,21 @@ combine_comparisons (enum tree_code code, enum 
tree_code lcode,
             || (code == TRUTH_ANDIF_EXPR && !(lcompcode & COMPCODE_UNORD)))
           rtrap = false;
 
+       /* Allow combining of `a != b && a < b` since NAN will cause != to be
+          always true, and `a < b` will cause a trap. This is trap neutral.  */
+       if (code == TRUTH_ANDIF_EXPR && lcompcode == COMPCODE_NE && rtrap && 
trap)
+         ;
+       /* Likewise of `a == b || a < b` for the same reason.  */
+       else if (code == TRUTH_ORIF_EXPR && lcompcode == COMPCODE_EQ && rtrap 
&& trap)
+         ;
         /* If the comparison was short-circuited, and only the RHS
           trapped, we may now generate a spurious trap.  */
-       if (rtrap && !ltrap
-           && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
+       else if (rtrap && !ltrap
+                && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
          return ERROR_MARK;
 
        /* If we changed the conditions that cause a trap, we lose.  */
-       if ((ltrap || rtrap) != trap)
+       else if ((ltrap || rtrap) != trap)
          return ERROR_MARK;
       }
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
new file mode 100644
index 00000000000..9d88dc10c2d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftrapping-math -fdump-tree-original 
-fdump-tree-optimized" } */
+/* PR tree-optimization/126138 */
+
+/* (eq || trap) -> trap is fine as eq will be false for NaN
+   which means it is not short circuit and will cause a trap
+   on the trapping instruction always.  */
+int
+f (double i, double j)
+{
+  return (i == j) || (i < j);
+}
+/* (ne && trap) -> trap has a story. */
+int
+f1 (double i, double j)
+{
+  return (i != j) && (i < j);
+}
+/* { dg-final { scan-tree-dump-not " && " "original" } } */
+/* { dg-final { scan-tree-dump-not " \\\|\\\| " "original" } } */
+/* { dg-final { scan-tree-dump-not " if " "optimized" } } */
-- 
2.43.0

Reply via email to