[gcc r17-2707] fold: Allow combining eq/ne with a trapping to get a trapping [PR126138]

Andrea Pinski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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" } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.