https://gcc.gnu.org/g:8b90726a28bb63038b4f80242c7f5af7f53b60ff

commit r17-4921-g8b90726a28bb63038b4f80242c7f5af7f53b60ff
Author: Richard Biener <[email protected]>
Date:   Mon Sep 28 15:44:56 2026 +0200

    Preserve comparison operand order whem if-combining
    
    When combining conditions ifcombine_ifandif passes inner_cond_code as the
    first comparison and outer_cond_code as the second to
    maybe_fold_and_comparisons and maybe_fold_and_comparisons calls
    and_comparisons_1 with both comparison orders.  Both defeats preserving
    IEEE exceptions of trapping outer comparisons which combine_comparisons
    handles, but only when the order of the comparisons is preserved correctly.
    
    This disables some optimization in and_comparisons_1 which only looks
    through SSA defs for the first comparison.  This requires larger
    refactoring and the overall design seems dubious with recursions
    going in ways that with the swapping look exponential.
    
            PR tree-optimization/53805
            * tree-ssa-ifcombine.cc (ifcombine_ifandif): Pass comparisons
            in the correct order.
            * gimple-fold.cc (and_comparisons_1): Add FIXME comment.
            (maybe_fold_and_comparisons): Do not call and_comparisons_1 with
            swapped comparisons.
    
            * gcc.dg/tree-ssa/fp-trapping-cmp-6.c: New testcase
            * gcc.dg/tree-ssa/fp-trapping-cmp-7.c: Likewise.

Diff:
---
 gcc/gimple-fold.cc                                |  7 +++----
 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-6.c | 14 ++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-7.c | 14 ++++++++++++++
 gcc/tree-ssa-ifcombine.cc                         |  8 ++++----
 4 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 3f4c979793bc..63e289c0d449 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7623,6 +7623,9 @@ and_comparisons_1 (tree type, enum tree_code code1, tree 
op1a, tree op1b,
   /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
      NAME's definition is a truth value.  See if there are any simplifications
      that can be done against the NAME's definition.  */
+  /* ???  Do the same for op2a, but as we are recursing we have to track
+     whether we swap the order of the comparsions since that's important
+     with respect to exceptions.  */
   if (TREE_CODE (op1a) == SSA_NAME
       && (code1 == NE_EXPR || code1 == EQ_EXPR)
       && (integer_zerop (op1b) || integer_onep (op1b)))
@@ -9314,10 +9317,6 @@ maybe_fold_and_comparisons (tree type,
                                  outer_cond_bb))
     return t;
 
-  if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b,
-                                 outer_cond_bb))
-    return t;
-
   if (tree t = maybe_fold_comparisons_from_match_pd (type, BIT_AND_EXPR, code1,
                                                     op1a, op1b, code2, op2a,
                                                     op2b, outer_cond_bb))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-6.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-6.c
new file mode 100644
index 000000000000..4ffb5a140c0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftrapping-math -fdump-tree-ifcombine-details" } */
+
+int
+f (double a, double b)
+{
+  if (a > b)
+    if (a < b)
+      return 1;
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "optimizing trapping cond to" "ifcombine" } 
} */
+/* { dg-final { scan-tree-dump-not "optimizing two comparisons to" "ifcombine" 
} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-7.c 
b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-7.c
new file mode 100644
index 000000000000..5916344877f6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/fp-trapping-cmp-7.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftrapping-math -fdump-tree-ifcombine-details" } */
+
+int
+f (double a, double b)
+{
+  if (a > b)
+    if (a == b)
+      return 1;
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "optimizing trapping cond to" "ifcombine" } 
} */
+/* { dg-final { scan-tree-dump "optimizing two comparisons to _\[0-9\]\+ & 
_\[0-9\]\+" "ifcombine" } } */
diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
index 1b6ee9207cc1..0b1fdc7960b0 100644
--- a/gcc/tree-ssa-ifcombine.cc
+++ b/gcc/tree-ssa-ifcombine.cc
@@ -1096,12 +1096,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool 
inner_inv,
        return false;
       /* Don't return false so fast, try maybe_fold_or_comparisons?  */
 
-      if (!(t = maybe_fold_and_comparisons (boolean_type_node, inner_cond_code,
-                                           gimple_cond_lhs (inner_cond),
-                                           gimple_cond_rhs (inner_cond),
-                                           outer_cond_code,
+      if (!(t = maybe_fold_and_comparisons (boolean_type_node, outer_cond_code,
                                            gimple_cond_lhs (outer_cond),
                                            gimple_cond_rhs (outer_cond),
+                                           inner_cond_code,
+                                           gimple_cond_lhs (inner_cond),
+                                           gimple_cond_rhs (inner_cond),
                                            gimple_bb (outer_cond)))
          && !(t = (fold_truth_andor_for_ifcombine
                    (TRUTH_ANDIF_EXPR, boolean_type_node,

Reply via email to