https://gcc.gnu.org/g:7d781db9c3d5159386b1f645355955da5f844ec4

commit r17-2707-g7d781db9c3d5159386b1f645355955da5f844ec4
Author: Andrea Pinski <[email protected]>
Date:   Sat Jul 11 22:56:40 2026 -0700

    fold: Allow combining eq/ne with a trapping to get a trapping [PR126138]
    
    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 && 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]>

Diff:
---
 gcc/fold-const.cc                                 | 13 ++++++++++---
 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-1.c | 21 +++++++++++++++++++++
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index b4e3a56aeb55..e1793ac89f25 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 000000000000..9d88dc10c2d0
--- /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" } } */

Reply via email to