On Wed, May 05, 2021 at 01:39:32PM +0200, Richard Biener wrote:
> Can you in the above IL snippets mark COND_BB and MIDDLE_BB?
...

Thanks.
Here is an updated patch (attached) and interdiff from previous patch.
Ok for trunk if it passes bootstrap/regtest?

--- gcc/tree-ssa-phiopt.c       2021-05-03 17:49:54.233300624 +0200
+++ gcc/tree-ssa-phiopt.c       2021-05-05 15:06:23.253189139 +0200
@@ -65,7 +65,7 @@
 static bool xor_replacement (basic_block, basic_block,
                             edge, edge, gimple *, tree, tree);
 static bool spaceship_replacement (basic_block, basic_block,
-                                  edge, edge, gimple *, tree, tree);
+                                  edge, edge, gphi *, tree, tree);
 static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
                                                      edge, edge, gimple *,
                                                      tree, tree);
@@ -1840,53 +1840,53 @@
 
 /* Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
    For strong ordering <=> try to match something like:
-    <bb 2> :
+    <bb 2> :  // cond3_bb (== cond2_bb)
     if (x_4(D) != y_5(D))
       goto <bb 3>; [INV]
     else
       goto <bb 6>; [INV]
 
-    <bb 3> :
+    <bb 3> :  // cond_bb
     if (x_4(D) < y_5(D))
       goto <bb 6>; [INV]
     else
       goto <bb 4>; [INV]
 
-    <bb 4> :
+    <bb 4> :  // middle_bb
 
-    <bb 6> :
+    <bb 6> :  // phi_bb
     # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
     _1 = iftmp.0_2 == 0;
 
    and for partial ordering <=> something like:
 
-    <bb 2> :
+    <bb 2> :  // cond3_bb
     if (a_3(D) == b_5(D))
       goto <bb 6>; [50.00%]
     else
       goto <bb 3>; [50.00%]
 
-    <bb 3> [local count: 536870913]:
+    <bb 3> [local count: 536870913]:  // cond2_bb
     if (a_3(D) < b_5(D))
       goto <bb 6>; [50.00%]
     else
       goto <bb 4>; [50.00%]
 
-    <bb 4> [local count: 268435456]:
+    <bb 4> [local count: 268435456]:  // cond_bb
     if (a_3(D) > b_5(D))
       goto <bb 6>; [50.00%]
     else
       goto <bb 5>; [50.00%]
 
-    <bb 5> [local count: 134217728]:
+    <bb 5> [local count: 134217728]:  // middle_bb
 
-    <bb 6> [local count: 1073741824]:
+    <bb 6> [local count: 1073741824]:  // phi_bb
     # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
     _2 = SR.27_4 > 0;  */
 
 static bool
 spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
-                      edge e0, edge e1, gimple *phi,
+                      edge e0, edge e1, gphi *phi,
                       tree arg0, tree arg1)
 {
   if (!INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (phi)))
@@ -1897,6 +1897,11 @@
       || !IN_RANGE (tree_to_shwi (arg1), -1, 2))
     return false;
 
+  basic_block phi_bb = gimple_bb (phi);
+  gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
+  if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
+    return false;
+
   use_operand_p use_p;
   gimple *use_stmt;
   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
@@ -1953,11 +1958,6 @@
   if (!empty_block_p (middle_bb))
     return false;
 
-  basic_block phi_bb = gimple_bb (phi);
-  gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
-  if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
-    return false;
-
   gcond *cond1 = as_a <gcond *> (last_stmt (cond_bb));
   enum tree_code cmp1 = gimple_cond_code (cond1);
   if (cmp1 != LT_EXPR && cmp1 != GT_EXPR)
@@ -1965,7 +1965,7 @@
   tree lhs1 = gimple_cond_lhs (cond1);
   tree rhs1 = gimple_cond_rhs (cond1);
   /* The optimization may be unsafe due to NaNs.  */
-  if (HONOR_NANS (TREE_TYPE (lhs1)) || HONOR_SIGNED_ZEROS (TREE_TYPE (lhs1)))
+  if (HONOR_NANS (TREE_TYPE (lhs1)))
     return false;
   if (TREE_CODE (lhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs1))
     return false;
@@ -2180,11 +2180,6 @@
       gimple_assign_set_rhs1 (use_stmt, cond);
     }
   update_stmt (use_stmt);
-  if (cmp3 == EQ_EXPR)
-    gimple_cond_make_true (as_a <gcond *> (cond3));
-  else
-    gimple_cond_make_false (as_a <gcond *> (cond3));
-  update_stmt (cond3);
 
   if (MAY_HAVE_DEBUG_BIND_STMTS)
     {
@@ -2201,6 +2196,13 @@
 
       if (has_debug_uses)
        {
+         /* If there are debug uses, emit something like:
+            # DEBUG D#1 => i_2(D) > j_3(D) ? 1 : -1
+            # DEBUG D#2 => i_2(D) == j_3(D) ? 0 : D#1
+            where > stands for the comparison that yielded 1
+            and replace debug uses of phi result with that D#2.
+            Ignore the value of 2, because if NaNs aren't expected,
+            all floating point numbers should be comparable.  */
          gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
          tree type = TREE_TYPE (PHI_RESULT (phi));
          tree temp1 = make_node (DEBUG_EXPR_DECL);
@@ -2224,6 +2226,9 @@
        }
     }
 
+  gimple_stmt_iterator psi = gsi_for_stmt (phi);
+  remove_phi_node (&psi, true);
+
   return true;
 }
 


        Jakub
2021-05-05  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/94589
        * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Call
        spaceship_replacement.
        (cond_only_block_p, spaceship_replacement): New functions.

        * gcc.dg/pr94589-1.c: New test.
        * gcc.dg/pr94589-2.c: New test.
        * gcc.dg/pr94589-3.c: New test.
        * gcc.dg/pr94589-4.c: New test.
        * g++.dg/opt/pr94589-1.C: New test.
        * g++.dg/opt/pr94589-2.C: New test.
        * g++.dg/opt/pr94589-3.C: New test.
        * g++.dg/opt/pr94589-4.C: New test.

--- gcc/tree-ssa-phiopt.c.jj    2021-05-04 21:02:24.182799741 +0200
+++ gcc/tree-ssa-phiopt.c       2021-05-05 15:06:23.253189139 +0200
@@ -64,6 +64,8 @@ static bool abs_replacement (basic_block
                             edge, edge, gimple *, tree, tree);
 static bool xor_replacement (basic_block, basic_block,
                             edge, edge, gimple *, tree, tree);
+static bool spaceship_replacement (basic_block, basic_block,
+                                  edge, edge, gphi *, tree, tree);
 static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
                                                      edge, edge, gimple *,
                                                      tree, tree);
@@ -359,6 +361,8 @@ tree_ssa_phiopt_worker (bool do_store_el
            cfgchanged = true;
          else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
            cfgchanged = true;
+         else if (spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
+           cfgchanged = true;
        }
     }
 
@@ -1808,6 +1812,425 @@ minmax_replacement (basic_block cond_bb,
 
   return true;
 }
+
+/* Return true if the only executable statement in BB is a GIMPLE_COND.  */
+
+static bool
+cond_only_block_p (basic_block bb)
+{
+  /* BB must have no executable statements.  */
+  gimple_stmt_iterator gsi = gsi_after_labels (bb);
+  if (phi_nodes (bb))
+    return false;
+  while (!gsi_end_p (gsi))
+    {
+      gimple *stmt = gsi_stmt (gsi);
+      if (is_gimple_debug (stmt))
+       ;
+      else if (gimple_code (stmt) == GIMPLE_NOP
+              || gimple_code (stmt) == GIMPLE_PREDICT
+              || gimple_code (stmt) == GIMPLE_COND)
+       ;
+      else
+       return false;
+      gsi_next (&gsi);
+    }
+  return true;
+}
+
+/* Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
+   For strong ordering <=> try to match something like:
+    <bb 2> :  // cond3_bb (== cond2_bb)
+    if (x_4(D) != y_5(D))
+      goto <bb 3>; [INV]
+    else
+      goto <bb 6>; [INV]
+
+    <bb 3> :  // cond_bb
+    if (x_4(D) < y_5(D))
+      goto <bb 6>; [INV]
+    else
+      goto <bb 4>; [INV]
+
+    <bb 4> :  // middle_bb
+
+    <bb 6> :  // phi_bb
+    # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
+    _1 = iftmp.0_2 == 0;
+
+   and for partial ordering <=> something like:
+
+    <bb 2> :  // cond3_bb
+    if (a_3(D) == b_5(D))
+      goto <bb 6>; [50.00%]
+    else
+      goto <bb 3>; [50.00%]
+
+    <bb 3> [local count: 536870913]:  // cond2_bb
+    if (a_3(D) < b_5(D))
+      goto <bb 6>; [50.00%]
+    else
+      goto <bb 4>; [50.00%]
+
+    <bb 4> [local count: 268435456]:  // cond_bb
+    if (a_3(D) > b_5(D))
+      goto <bb 6>; [50.00%]
+    else
+      goto <bb 5>; [50.00%]
+
+    <bb 5> [local count: 134217728]:  // middle_bb
+
+    <bb 6> [local count: 1073741824]:  // phi_bb
+    # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
+    _2 = SR.27_4 > 0;  */
+
+static bool
+spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
+                      edge e0, edge e1, gphi *phi,
+                      tree arg0, tree arg1)
+{
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (PHI_RESULT (phi)))
+      || TYPE_UNSIGNED (TREE_TYPE (PHI_RESULT (phi)))
+      || !tree_fits_shwi_p (arg0)
+      || !tree_fits_shwi_p (arg1)
+      || !IN_RANGE (tree_to_shwi (arg0), -1, 2)
+      || !IN_RANGE (tree_to_shwi (arg1), -1, 2))
+    return false;
+
+  basic_block phi_bb = gimple_bb (phi);
+  gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
+  if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
+    return false;
+
+  use_operand_p use_p;
+  gimple *use_stmt;
+  if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
+    return false;
+  if (!single_imm_use (PHI_RESULT (phi), &use_p, &use_stmt))
+    return false;
+  enum tree_code cmp;
+  tree lhs, rhs;
+  if (gimple_code (use_stmt) == GIMPLE_COND)
+    {
+      cmp = gimple_cond_code (use_stmt);
+      lhs = gimple_cond_lhs (use_stmt);
+      rhs = gimple_cond_rhs (use_stmt);
+    }
+  else if (is_gimple_assign (use_stmt))
+    {
+      if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
+       {
+         cmp = gimple_assign_rhs_code (use_stmt);
+         lhs = gimple_assign_rhs1 (use_stmt);
+         rhs = gimple_assign_rhs2 (use_stmt);
+       }
+      else if (gimple_assign_rhs_code (use_stmt) == COND_EXPR)
+       {
+         tree cond = gimple_assign_rhs1 (use_stmt);
+         if (!COMPARISON_CLASS_P (cond))
+           return false;
+         cmp = TREE_CODE (cond);
+         lhs = TREE_OPERAND (cond, 0);
+         rhs = TREE_OPERAND (cond, 1);
+       }
+      else
+       return false;
+    }
+  else
+    return false;
+  switch (cmp)
+    {
+    case EQ_EXPR:
+    case NE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+      break;
+    default:
+      return false;
+    }
+  if (lhs != PHI_RESULT (phi)
+      || !tree_fits_shwi_p (rhs)
+      || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
+    return false;
+
+  if (!empty_block_p (middle_bb))
+    return false;
+
+  gcond *cond1 = as_a <gcond *> (last_stmt (cond_bb));
+  enum tree_code cmp1 = gimple_cond_code (cond1);
+  if (cmp1 != LT_EXPR && cmp1 != GT_EXPR)
+    return false;
+  tree lhs1 = gimple_cond_lhs (cond1);
+  tree rhs1 = gimple_cond_rhs (cond1);
+  /* The optimization may be unsafe due to NaNs.  */
+  if (HONOR_NANS (TREE_TYPE (lhs1)))
+    return false;
+  if (TREE_CODE (lhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs1))
+    return false;
+  if (TREE_CODE (rhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
+    return false;
+
+  if (!single_pred_p (cond_bb) || !cond_only_block_p (cond_bb))
+    return false;
+
+  basic_block cond2_bb = single_pred (cond_bb);
+  if (EDGE_COUNT (cond2_bb->succs) != 2)
+    return false;
+  edge cond2_phi_edge;
+  if (EDGE_SUCC (cond2_bb, 0)->dest == cond_bb)
+    {
+      if (EDGE_SUCC (cond2_bb, 1)->dest != phi_bb)
+       return false;
+      cond2_phi_edge = EDGE_SUCC (cond2_bb, 1);
+    }
+  else if (EDGE_SUCC (cond2_bb, 0)->dest != phi_bb)
+    return false;
+  else
+    cond2_phi_edge = EDGE_SUCC (cond2_bb, 0);
+  tree arg2 = gimple_phi_arg_def (phi, cond2_phi_edge->dest_idx);
+  if (!tree_fits_shwi_p (arg2))
+    return false;
+  gimple *cond2 = last_stmt (cond2_bb);
+  if (cond2 == NULL || gimple_code (cond2) != GIMPLE_COND)
+    return false;
+  enum tree_code cmp2 = gimple_cond_code (cond2);
+  tree lhs2 = gimple_cond_lhs (cond2);
+  tree rhs2 = gimple_cond_rhs (cond2);
+  if (lhs2 == lhs1)
+    {
+      if (!operand_equal_p (rhs2, rhs1, 0))
+       return false;
+    }
+  else if (lhs2 == rhs1)
+    {
+      if (rhs2 != lhs1)
+       return false;
+    }
+  else
+    return false;
+  tree arg3 = arg2;
+  basic_block cond3_bb = cond2_bb;
+  edge cond3_phi_edge = cond2_phi_edge;
+  gimple *cond3 = cond2;
+  enum tree_code cmp3 = cmp2;
+  tree lhs3 = lhs2;
+  tree rhs3 = rhs2;
+  if (EDGE_COUNT (phi_bb->preds) == 4)
+    {
+      if (absu_hwi (tree_to_shwi (arg2)) != 1)
+       return false;
+      if (e1->flags & EDGE_TRUE_VALUE)
+       {
+         if (tree_to_shwi (arg0) != 2
+             || absu_hwi (tree_to_shwi (arg1)) != 1
+             || wi::to_widest (arg1) == wi::to_widest (arg2))
+           return false;
+       }
+      else if (tree_to_shwi (arg1) != 2
+              || absu_hwi (tree_to_shwi (arg0)) != 1
+              || wi::to_widest (arg0) == wi::to_widest (arg1))
+       return false;
+      if (cmp2 != LT_EXPR && cmp2 != GT_EXPR)
+       return false;
+      /* if (x < y) goto phi_bb; else fallthru;
+        if (x > y) goto phi_bb; else fallthru;
+        bbx:;
+        phi_bb:;
+        is ok, but if x and y are swapped in one of the comparisons,
+        or the comparisons are the same and operands not swapped,
+        or second goto phi_bb is not the true edge, it is not.  */
+      if ((lhs2 == lhs1)
+         ^ (cmp2 == cmp1)
+         ^ ((e1->flags & EDGE_TRUE_VALUE) != 0))
+       return false;
+      if ((cond2_phi_edge->flags & EDGE_TRUE_VALUE) == 0)
+       return false;
+      if (!single_pred_p (cond2_bb) || !cond_only_block_p (cond2_bb))
+       return false;
+      cond3_bb = single_pred (cond2_bb);
+      if (EDGE_COUNT (cond2_bb->succs) != 2)
+       return false;
+      if (EDGE_SUCC (cond3_bb, 0)->dest == cond2_bb)
+       {
+         if (EDGE_SUCC (cond3_bb, 1)->dest != phi_bb)
+           return false;
+         cond3_phi_edge = EDGE_SUCC (cond3_bb, 1);
+       }
+      else if (EDGE_SUCC (cond3_bb, 0)->dest != phi_bb)
+       return false;
+      else
+       cond3_phi_edge = EDGE_SUCC (cond3_bb, 0);
+      arg3 = gimple_phi_arg_def (phi, cond3_phi_edge->dest_idx);
+      cond3 = last_stmt (cond3_bb);
+      if (cond3 == NULL || gimple_code (cond3) != GIMPLE_COND)
+       return false;
+      cmp3 = gimple_cond_code (cond3);
+      lhs3 = gimple_cond_lhs (cond3);
+      rhs3 = gimple_cond_rhs (cond3);
+      if (lhs3 == lhs1)
+       {
+         if (!operand_equal_p (rhs3, rhs1, 0))
+           return false;
+       }
+      else if (lhs3 == rhs1)
+       {
+         if (rhs3 != lhs1)
+           return false;
+       }
+      else
+       return false;
+    }
+  else if (absu_hwi (tree_to_shwi (arg0)) != 1
+          || absu_hwi (tree_to_shwi (arg1)) != 1
+          || wi::to_widest (arg0) == wi::to_widest (arg1))
+    return false;
+
+  if (!integer_zerop (arg3) || (cmp3 != EQ_EXPR && cmp3 != NE_EXPR))
+    return false;
+  if ((cond3_phi_edge->flags & (cmp3 == EQ_EXPR
+                               ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) == 0)
+    return false;
+
+  /* lhs1 one_cmp rhs1 results in PHI_RESULT (phi) of 1.  */
+  enum tree_code one_cmp;
+  if ((cmp1 == LT_EXPR)
+      ^ (!integer_onep ((e1->flags & EDGE_TRUE_VALUE) ? arg1 : arg0)))
+    one_cmp = LT_EXPR;
+  else
+    one_cmp = GT_EXPR;
+
+  enum tree_code res_cmp;
+  switch (cmp)
+    {
+    case EQ_EXPR:
+      if (integer_zerop (rhs))
+       res_cmp = EQ_EXPR;
+      else if (integer_minus_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+      else if (integer_onep (rhs))
+       res_cmp = one_cmp;
+      else
+       return false;
+      break;
+    case NE_EXPR:
+      if (integer_zerop (rhs))
+       res_cmp = NE_EXPR;
+      else if (integer_minus_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+      else if (integer_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+      else
+       return false;
+      break;
+    case LT_EXPR:
+      if (integer_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+      else if (integer_zerop (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+      else
+       return false;
+      break;
+    case LE_EXPR:
+      if (integer_zerop (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
+      else if (integer_minus_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
+      else
+       return false;
+      break;
+    case GT_EXPR:
+      if (integer_minus_onep (rhs))
+       res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+      else if (integer_zerop (rhs))
+       res_cmp = one_cmp;
+      else
+       return false;
+      break;
+    case GE_EXPR:
+      if (integer_zerop (rhs))
+       res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
+      else if (integer_onep (rhs))
+       res_cmp = one_cmp;
+      else
+       return false;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (gimple_code (use_stmt) == GIMPLE_COND)
+    {
+      gcond *use_cond = as_a <gcond *> (use_stmt);
+      gimple_cond_set_code (use_cond, res_cmp);
+      gimple_cond_set_lhs (use_cond, lhs1);
+      gimple_cond_set_rhs (use_cond, rhs1);
+    }
+  else if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
+    {
+      gimple_assign_set_rhs_code (use_stmt, res_cmp);
+      gimple_assign_set_rhs1 (use_stmt, lhs1);
+      gimple_assign_set_rhs2 (use_stmt, rhs1);
+    }
+  else
+    {
+      tree cond = build2 (res_cmp, TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
+                         lhs1, rhs1);
+      gimple_assign_set_rhs1 (use_stmt, cond);
+    }
+  update_stmt (use_stmt);
+
+  if (MAY_HAVE_DEBUG_BIND_STMTS)
+    {
+      use_operand_p use_p;
+      imm_use_iterator iter;
+      bool has_debug_uses = false;
+      FOR_EACH_IMM_USE_FAST (use_p, iter, PHI_RESULT (phi))
+       {
+         gimple *use_stmt = USE_STMT (use_p);
+         gcc_assert (is_gimple_debug (use_stmt));
+         has_debug_uses = true;
+         break;
+       }
+
+      if (has_debug_uses)
+       {
+         /* If there are debug uses, emit something like:
+            # DEBUG D#1 => i_2(D) > j_3(D) ? 1 : -1
+            # DEBUG D#2 => i_2(D) == j_3(D) ? 0 : D#1
+            where > stands for the comparison that yielded 1
+            and replace debug uses of phi result with that D#2.
+            Ignore the value of 2, because if NaNs aren't expected,
+            all floating point numbers should be comparable.  */
+         gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
+         tree type = TREE_TYPE (PHI_RESULT (phi));
+         tree temp1 = make_node (DEBUG_EXPR_DECL);
+         DECL_ARTIFICIAL (temp1) = 1;
+         TREE_TYPE (temp1) = type;
+         SET_DECL_MODE (temp1, TYPE_MODE (type));
+         tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
+         t = build3 (COND_EXPR, type, t, build_one_cst (type),
+                     build_int_cst (type, -1));
+         gimple *g = gimple_build_debug_bind (temp1, t, phi);
+         gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+         tree temp2 = make_node (DEBUG_EXPR_DECL);
+         DECL_ARTIFICIAL (temp2) = 1;
+         TREE_TYPE (temp2) = type;
+         SET_DECL_MODE (temp2, TYPE_MODE (type));
+         t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
+         t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
+         g = gimple_build_debug_bind (temp2, t, phi);
+         gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+         replace_uses_by (PHI_RESULT (phi), temp2);
+       }
+    }
+
+  gimple_stmt_iterator psi = gsi_for_stmt (phi);
+  remove_phi_node (&psi, true);
+
+  return true;
+}
 
 /* Convert
 
--- gcc/testsuite/gcc.dg/pr94589-1.c.jj 2021-05-05 14:36:34.041150771 +0200
+++ gcc/testsuite/gcc.dg/pr94589-1.c    2021-05-05 14:36:34.041150771 +0200
@@ -0,0 +1,35 @@
+/* PR tree-optimization/94589 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g0 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[45]" 14 "optimized" } } */
+
+#define A __attribute__((noipa))
+A int f1 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 0; }
+A int f2 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 0; }
+A int f3 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > 0; }
+A int f4 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 0; }
+A int f5 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 0; }
+A int f6 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= 0; }
+A int f7 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == -1; 
}
+A int f8 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != -1; 
}
+A int f9 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c > -1; }
+A int f10 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c <= 
-1; }
+A int f11 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c == 1; 
}
+A int f12 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c != 1; 
}
+A int f13 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c < 1; }
+A int f14 (int i, int j) { int c = i == j ? 0 : i < j ? -1 : 1; return c >= 1; 
}
+A int f15 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 0; }
+A int f16 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 0; }
+A int f17 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > 0; }
+A int f18 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 0; }
+A int f19 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 0; }
+A int f20 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= 0; }
+A int f21 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == -1; }
+A int f22 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != -1; }
+A int f23 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c > -1; }
+A int f24 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c <= -1; }
+A int f25 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c == 1; }
+A int f26 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c != 1; }
+A int f27 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c < 1; }
+A int f28 (int i) { int c = i == 5 ? 0 : i < 5 ? -1 : 1; return c >= 1; }
--- gcc/testsuite/gcc.dg/pr94589-2.c.jj 2021-05-05 14:36:34.041150771 +0200
+++ gcc/testsuite/gcc.dg/pr94589-2.c    2021-05-05 14:36:34.041150771 +0200
@@ -0,0 +1,35 @@
+/* PR tree-optimization/94589 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[ij]_\[0-9]+\\(D\\)" 14 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
5\\.0" 14 "optimized" } } */
+
+#define A __attribute__((noipa))
+A int f1 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c == 0; }
+A int f2 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c != 0; }
+A int f3 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c > 0; }
+A int f4 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c < 0; }
+A int f5 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c >= 0; }
+A int f6 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c <= 0; }
+A int f7 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c == -1; }
+A int f8 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c != -1; }
+A int f9 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c > -1; }
+A int f10 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c <= -1; }
+A int f11 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c == 1; }
+A int f12 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c != 1; }
+A int f13 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c < 1; }
+A int f14 (double i, double j) { int c; if (i == j) c = 0; else if (i < j) c = 
-1; else if (i > j) c = 1; else c = 2; return c >= 1; }
+A int f15 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c == 0; }
+A int f16 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c != 0; }
+A int f17 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c > 0; }
+A int f18 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c < 0; }
+A int f19 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c >= 0; }
+A int f20 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c <= 0; }
+A int f21 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c == -1; }
+A int f22 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c != -1; }
+A int f23 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c > -1; }
+A int f24 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c <= -1; }
+A int f25 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c == 1; }
+A int f26 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c != 1; }
+A int f27 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c < 1; }
+A int f28 (double i) { int c; if (i == 5.0) c = 0; else if (i < 5.0) c = -1; 
else if (i > 5.0) c = 1; else c = 2; return c >= 1; }
--- gcc/testsuite/gcc.dg/pr94589-3.c.jj 2021-05-05 14:36:34.041150771 +0200
+++ gcc/testsuite/gcc.dg/pr94589-3.c    2021-05-05 14:36:34.041150771 +0200
@@ -0,0 +1,97 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -g" } */
+
+#include "pr94589-1.c"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+  C (f1, 7, 8, 0);
+  C (f1, 8, 8, 1);
+  C (f1, 9, 8, 0);
+  C (f2, 7, 8, 1);
+  C (f2, 8, 8, 0);
+  C (f2, 9, 8, 1);
+  C (f3, 7, 8, 0);
+  C (f3, 8, 8, 0);
+  C (f3, 9, 8, 1);
+  C (f4, 7, 8, 1);
+  C (f4, 8, 8, 0);
+  C (f4, 9, 8, 0);
+  C (f5, 7, 8, 0);
+  C (f5, 8, 8, 1);
+  C (f5, 9, 8, 1);
+  C (f6, 7, 8, 1);
+  C (f6, 8, 8, 1);
+  C (f6, 9, 8, 0);
+  C (f7, 7, 8, 1);
+  C (f7, 8, 8, 0);
+  C (f7, 9, 8, 0);
+  C (f8, 7, 8, 0);
+  C (f8, 8, 8, 1);
+  C (f8, 9, 8, 1);
+  C (f9, 7, 8, 0);
+  C (f9, 8, 8, 1);
+  C (f9, 9, 8, 1);
+  C (f10, 7, 8, 1);
+  C (f10, 8, 8, 0);
+  C (f10, 9, 8, 0);
+  C (f11, 7, 8, 0);
+  C (f11, 8, 8, 0);
+  C (f11, 9, 8, 1);
+  C (f12, 7, 8, 1);
+  C (f12, 8, 8, 1);
+  C (f12, 9, 8, 0);
+  C (f13, 7, 8, 1);
+  C (f13, 8, 8, 1);
+  C (f13, 9, 8, 0);
+  C (f14, 7, 8, 0);
+  C (f14, 8, 8, 0);
+  C (f14, 9, 8, 1);
+  D (f15, 4, 0);
+  D (f15, 5, 1);
+  D (f15, 6, 0);
+  D (f16, 4, 1);
+  D (f16, 5, 0);
+  D (f16, 6, 1);
+  D (f17, 4, 0);
+  D (f17, 5, 0);
+  D (f17, 6, 1);
+  D (f18, 4, 1);
+  D (f18, 5, 0);
+  D (f18, 6, 0);
+  D (f19, 4, 0);
+  D (f19, 5, 1);
+  D (f19, 6, 1);
+  D (f20, 4, 1);
+  D (f20, 5, 1);
+  D (f20, 6, 0);
+  D (f21, 4, 1);
+  D (f21, 5, 0);
+  D (f21, 6, 0);
+  D (f22, 4, 0);
+  D (f22, 5, 1);
+  D (f22, 6, 1);
+  D (f23, 4, 0);
+  D (f23, 5, 1);
+  D (f23, 6, 1);
+  D (f24, 4, 1);
+  D (f24, 5, 0);
+  D (f24, 6, 0);
+  D (f25, 4, 0);
+  D (f25, 5, 0);
+  D (f25, 6, 1);
+  D (f26, 4, 1);
+  D (f26, 5, 1);
+  D (f26, 6, 0);
+  D (f27, 4, 1);
+  D (f27, 5, 1);
+  D (f27, 6, 0);
+  D (f28, 4, 0);
+  D (f28, 5, 0);
+  D (f28, 6, 1);
+  return 0;
+}
--- gcc/testsuite/gcc.dg/pr94589-4.c.jj 2021-05-05 14:36:34.041150771 +0200
+++ gcc/testsuite/gcc.dg/pr94589-4.c    2021-05-05 14:36:34.041150771 +0200
@@ -0,0 +1,97 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -g -ffast-math" } */
+
+#include "pr94589-2.c"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+  C (f1, 7.0, 8.0, 0);
+  C (f1, 8.0, 8.0, 1);
+  C (f1, 9.0, 8.0, 0);
+  C (f2, 7.0, 8.0, 1);
+  C (f2, 8.0, 8.0, 0);
+  C (f2, 9.0, 8.0, 1);
+  C (f3, 7.0, 8.0, 0);
+  C (f3, 8.0, 8.0, 0);
+  C (f3, 9.0, 8.0, 1);
+  C (f4, 7.0, 8.0, 1);
+  C (f4, 8.0, 8.0, 0);
+  C (f4, 9.0, 8.0, 0);
+  C (f5, 7.0, 8.0, 0);
+  C (f5, 8.0, 8.0, 1);
+  C (f5, 9.0, 8.0, 1);
+  C (f6, 7.0, 8.0, 1);
+  C (f6, 8.0, 8.0, 1);
+  C (f6, 9.0, 8.0, 0);
+  C (f7, 7.0, 8.0, 1);
+  C (f7, 8.0, 8.0, 0);
+  C (f7, 9.0, 8.0, 0);
+  C (f8, 7.0, 8.0, 0);
+  C (f8, 8.0, 8.0, 1);
+  C (f8, 9.0, 8.0, 1);
+  C (f9, 7.0, 8.0, 0);
+  C (f9, 8.0, 8.0, 1);
+  C (f9, 9.0, 8.0, 1);
+  C (f10, 7.0, 8.0, 1);
+  C (f10, 8.0, 8.0, 0);
+  C (f10, 9.0, 8.0, 0);
+  C (f11, 7.0, 8.0, 0);
+  C (f11, 8.0, 8.0, 0);
+  C (f11, 9.0, 8.0, 1);
+  C (f12, 7.0, 8.0, 1);
+  C (f12, 8.0, 8.0, 1);
+  C (f12, 9.0, 8.0, 0);
+  C (f13, 7.0, 8.0, 1);
+  C (f13, 8.0, 8.0, 1);
+  C (f13, 9.0, 8.0, 0);
+  C (f14, 7.0, 8.0, 0);
+  C (f14, 8.0, 8.0, 0);
+  C (f14, 9.0, 8.0, 1);
+  D (f15, 4.0, 0);
+  D (f15, 5.0, 1);
+  D (f15, 6.0, 0);
+  D (f16, 4.0, 1);
+  D (f16, 5.0, 0);
+  D (f16, 6.0, 1);
+  D (f17, 4.0, 0);
+  D (f17, 5.0, 0);
+  D (f17, 6.0, 1);
+  D (f18, 4.0, 1);
+  D (f18, 5.0, 0);
+  D (f18, 6.0, 0);
+  D (f19, 4.0, 0);
+  D (f19, 5.0, 1);
+  D (f19, 6.0, 1);
+  D (f20, 4.0, 1);
+  D (f20, 5.0, 1);
+  D (f20, 6.0, 0);
+  D (f21, 4.0, 1);
+  D (f21, 5.0, 0);
+  D (f21, 6.0, 0);
+  D (f22, 4.0, 0);
+  D (f22, 5.0, 1);
+  D (f22, 6.0, 1);
+  D (f23, 4.0, 0);
+  D (f23, 5.0, 1);
+  D (f23, 6.0, 1);
+  D (f24, 4.0, 1);
+  D (f24, 5.0, 0);
+  D (f24, 6.0, 0);
+  D (f25, 4.0, 0);
+  D (f25, 5.0, 0);
+  D (f25, 6.0, 1);
+  D (f26, 4.0, 1);
+  D (f26, 5.0, 1);
+  D (f26, 6.0, 0);
+  D (f27, 4.0, 1);
+  D (f27, 5.0, 1);
+  D (f27, 6.0, 0);
+  D (f28, 4.0, 0);
+  D (f28, 5.0, 0);
+  D (f28, 6.0, 1);
+  return 0;
+}
--- gcc/testsuite/g++.dg/opt/pr94589-1.C.jj     2021-05-05 14:36:34.041150771 
+0200
+++ gcc/testsuite/g++.dg/opt/pr94589-1.C        2021-05-05 14:36:34.041150771 
+0200
@@ -0,0 +1,33 @@
+// PR tree-optimization/94589
+// { dg-do compile { target c++20 } }
+// { dg-options "-O2 -g0 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[ij]_\[0-9]+\\(D\\)" 12 "optimized" } }
+// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[45]" 12 "optimized" } }
+
+#include <compare>
+
+#define A __attribute__((noipa))
+A bool f1 (int i, int j) { auto c = i <=> j; return c == 0; }
+A bool f2 (int i, int j) { auto c = i <=> j; return c != 0; }
+A bool f3 (int i, int j) { auto c = i <=> j; return c > 0; }
+A bool f4 (int i, int j) { auto c = i <=> j; return c < 0; }
+A bool f5 (int i, int j) { auto c = i <=> j; return c >= 0; }
+A bool f6 (int i, int j) { auto c = i <=> j; return c <= 0; }
+A bool f7 (int i, int j) { auto c = i <=> j; return c == 
std::strong_ordering::less; }
+A bool f8 (int i, int j) { auto c = i <=> j; return c != 
std::strong_ordering::less; }
+A bool f9 (int i, int j) { auto c = i <=> j; return c == 
std::strong_ordering::equal; }
+A bool f10 (int i, int j) { auto c = i <=> j; return c != 
std::strong_ordering::equal; }
+A bool f11 (int i, int j) { auto c = i <=> j; return c == 
std::strong_ordering::greater; }
+A bool f12 (int i, int j) { auto c = i <=> j; return c != 
std::strong_ordering::greater; }
+A bool f13 (int i) { auto c = i <=> 5; return c == 0; }
+A bool f14 (int i) { auto c = i <=> 5; return c != 0; }
+A bool f15 (int i) { auto c = i <=> 5; return c > 0; }
+A bool f16 (int i) { auto c = i <=> 5; return c < 0; }
+A bool f17 (int i) { auto c = i <=> 5; return c >= 0; }
+A bool f18 (int i) { auto c = i <=> 5; return c <= 0; }
+A bool f19 (int i) { auto c = i <=> 5; return c == std::strong_ordering::less; 
}
+A bool f20 (int i) { auto c = i <=> 5; return c != std::strong_ordering::less; 
}
+A bool f21 (int i) { auto c = i <=> 5; return c == 
std::strong_ordering::equal; }
+A bool f22 (int i) { auto c = i <=> 5; return c != 
std::strong_ordering::equal; }
+A bool f23 (int i) { auto c = i <=> 5; return c == 
std::strong_ordering::greater; }
+A bool f24 (int i) { auto c = i <=> 5; return c != 
std::strong_ordering::greater; }
--- gcc/testsuite/g++.dg/opt/pr94589-2.C.jj     2021-05-05 14:36:34.041150771 
+0200
+++ gcc/testsuite/g++.dg/opt/pr94589-2.C        2021-05-05 14:36:34.041150771 
+0200
@@ -0,0 +1,33 @@
+// PR tree-optimization/94589
+// { dg-do compile { target c++20 } }
+// { dg-options "-O2 -g0 -ffast-math -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump-times "\[ij]_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
\[ij]_\[0-9]+\\(D\\)" 14 "optimized" } }
+// { dg-final { scan-tree-dump-times "i_\[0-9]+\\(D\\) (?:<|<=|==|!=|>|>=) 
5\\.0" 14 "optimized" } }
+
+#include <compare>
+
+#define A __attribute__((noipa))
+A bool f1 (double i, double j) { auto c = i <=> j; return c == 0; }
+A bool f2 (double i, double j) { auto c = i <=> j; return c != 0; }
+A bool f3 (double i, double j) { auto c = i <=> j; return c > 0; }
+A bool f4 (double i, double j) { auto c = i <=> j; return c < 0; }
+A bool f5 (double i, double j) { auto c = i <=> j; return c >= 0; }
+A bool f6 (double i, double j) { auto c = i <=> j; return c <= 0; }
+A bool f7 (double i, double j) { auto c = i <=> j; return c == 
std::partial_ordering::less; }
+A bool f8 (double i, double j) { auto c = i <=> j; return c != 
std::partial_ordering::less; }
+A bool f9 (double i, double j) { auto c = i <=> j; return c == 
std::partial_ordering::equivalent; }
+A bool f10 (double i, double j) { auto c = i <=> j; return c != 
std::partial_ordering::equivalent; }
+A bool f11 (double i, double j) { auto c = i <=> j; return c == 
std::partial_ordering::greater; }
+A bool f12 (double i, double j) { auto c = i <=> j; return c != 
std::partial_ordering::greater; }
+A bool f13 (double i) { auto c = i <=> 5.0; return c == 0; }
+A bool f14 (double i) { auto c = i <=> 5.0; return c != 0; }
+A bool f15 (double i) { auto c = i <=> 5.0; return c > 0; }
+A bool f16 (double i) { auto c = i <=> 5.0; return c < 0; }
+A bool f17 (double i) { auto c = i <=> 5.0; return c >= 0; }
+A bool f18 (double i) { auto c = i <=> 5.0; return c <= 0; }
+A bool f19 (double i) { auto c = i <=> 5.0; return c == 
std::partial_ordering::less; }
+A bool f20 (double i) { auto c = i <=> 5.0; return c != 
std::partial_ordering::less; }
+A bool f21 (double i) { auto c = i <=> 5.0; return c == 
std::partial_ordering::equivalent; }
+A bool f22 (double i) { auto c = i <=> 5.0; return c != 
std::partial_ordering::equivalent; }
+A bool f23 (double i) { auto c = i <=> 5.0; return c == 
std::partial_ordering::greater; }
+A bool f24 (double i) { auto c = i <=> 5.0; return c != 
std::partial_ordering::greater; }
--- gcc/testsuite/g++.dg/opt/pr94589-3.C.jj     2021-05-05 14:36:34.041150771 
+0200
+++ gcc/testsuite/g++.dg/opt/pr94589-3.C        2021-05-05 14:36:34.041150771 
+0200
@@ -0,0 +1,84 @@
+// { dg-do run { target c++20 } }
+// { dg-options "-O2 -g" }
+
+#include "pr94589-1.C"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+  C (f1, 7, 8, false);
+  C (f1, 8, 8, true);
+  C (f1, 9, 8, false);
+  C (f2, 7, 8, true);
+  C (f2, 8, 8, false);
+  C (f2, 9, 8, true);
+  C (f3, 7, 8, false);
+  C (f3, 8, 8, false);
+  C (f3, 9, 8, true);
+  C (f4, 7, 8, true);
+  C (f4, 8, 8, false);
+  C (f4, 9, 8, false);
+  C (f5, 7, 8, false);
+  C (f5, 8, 8, true);
+  C (f5, 9, 8, true);
+  C (f6, 7, 8, true);
+  C (f6, 8, 8, true);
+  C (f6, 9, 8, false);
+  C (f7, 7, 8, true);
+  C (f7, 8, 8, false);
+  C (f7, 9, 8, false);
+  C (f8, 7, 8, false);
+  C (f8, 8, 8, true);
+  C (f8, 9, 8, true);
+  C (f9, 7, 8, false);
+  C (f9, 8, 8, true);
+  C (f9, 9, 8, false);
+  C (f10, 7, 8, true);
+  C (f10, 8, 8, false);
+  C (f10, 9, 8, true);
+  C (f11, 7, 8, false);
+  C (f11, 8, 8, false);
+  C (f11, 9, 8, true);
+  C (f12, 7, 8, true);
+  C (f12, 8, 8, true);
+  C (f12, 9, 8, false);
+  D (f13, 4, false);
+  D (f13, 5, true);
+  D (f13, 6, false);
+  D (f14, 4, true);
+  D (f14, 5, false);
+  D (f14, 6, true);
+  D (f15, 4, false);
+  D (f15, 5, false);
+  D (f15, 6, true);
+  D (f16, 4, true);
+  D (f16, 5, false);
+  D (f16, 6, false);
+  D (f17, 4, false);
+  D (f17, 5, true);
+  D (f17, 6, true);
+  D (f18, 4, true);
+  D (f18, 5, true);
+  D (f18, 6, false);
+  D (f19, 4, true);
+  D (f19, 5, false);
+  D (f19, 6, false);
+  D (f20, 4, false);
+  D (f20, 5, true);
+  D (f20, 6, true);
+  D (f21, 4, false);
+  D (f21, 5, true);
+  D (f21, 6, false);
+  D (f22, 4, true);
+  D (f22, 5, false);
+  D (f22, 6, true);
+  D (f23, 4, false);
+  D (f23, 5, false);
+  D (f23, 6, true);
+  D (f24, 4, true);
+  D (f24, 5, true);
+  D (f24, 6, false);
+}
--- gcc/testsuite/g++.dg/opt/pr94589-4.C.jj     2021-05-05 14:36:34.042150760 
+0200
+++ gcc/testsuite/g++.dg/opt/pr94589-4.C        2021-05-05 14:36:34.042150760 
+0200
@@ -0,0 +1,84 @@
+// { dg-do run { target c++20 } }
+// { dg-options "-O2 -g -ffast-math" }
+
+#include "pr94589-2.C"
+
+#define C(fn, i, j, r) if (fn (i, j) != r) __builtin_abort ()
+#define D(fn, i, r) if (fn (i) != r) __builtin_abort ()
+
+int
+main ()
+{
+  C (f1, 7.0, 8.0, false);
+  C (f1, 8.0, 8.0, true);
+  C (f1, 9.0, 8.0, false);
+  C (f2, 7.0, 8.0, true);
+  C (f2, 8.0, 8.0, false);
+  C (f2, 9.0, 8.0, true);
+  C (f3, 7.0, 8.0, false);
+  C (f3, 8.0, 8.0, false);
+  C (f3, 9.0, 8.0, true);
+  C (f4, 7.0, 8.0, true);
+  C (f4, 8.0, 8.0, false);
+  C (f4, 9.0, 8.0, false);
+  C (f5, 7.0, 8.0, false);
+  C (f5, 8.0, 8.0, true);
+  C (f5, 9.0, 8.0, true);
+  C (f6, 7.0, 8.0, true);
+  C (f6, 8.0, 8.0, true);
+  C (f6, 9.0, 8.0, false);
+  C (f7, 7.0, 8.0, true);
+  C (f7, 8.0, 8.0, false);
+  C (f7, 9.0, 8.0, false);
+  C (f8, 7.0, 8.0, false);
+  C (f8, 8.0, 8.0, true);
+  C (f8, 9.0, 8.0, true);
+  C (f9, 7.0, 8.0, false);
+  C (f9, 8.0, 8.0, true);
+  C (f9, 9.0, 8.0, false);
+  C (f10, 7.0, 8.0, true);
+  C (f10, 8.0, 8.0, false);
+  C (f10, 9.0, 8.0, true);
+  C (f11, 7.0, 8.0, false);
+  C (f11, 8.0, 8.0, false);
+  C (f11, 9.0, 8.0, true);
+  C (f12, 7.0, 8.0, true);
+  C (f12, 8.0, 8.0, true);
+  C (f12, 9.0, 8.0, false);
+  D (f13, 4.0, false);
+  D (f13, 5.0, true);
+  D (f13, 6.0, false);
+  D (f14, 4.0, true);
+  D (f14, 5.0, false);
+  D (f14, 6.0, true);
+  D (f15, 4.0, false);
+  D (f15, 5.0, false);
+  D (f15, 6.0, true);
+  D (f16, 4.0, true);
+  D (f16, 5.0, false);
+  D (f16, 6.0, false);
+  D (f17, 4.0, false);
+  D (f17, 5.0, true);
+  D (f17, 6.0, true);
+  D (f18, 4.0, true);
+  D (f18, 5.0, true);
+  D (f18, 6.0, false);
+  D (f19, 4.0, true);
+  D (f19, 5.0, false);
+  D (f19, 6.0, false);
+  D (f20, 4.0, false);
+  D (f20, 5.0, true);
+  D (f20, 6.0, true);
+  D (f21, 4.0, false);
+  D (f21, 5.0, true);
+  D (f21, 6.0, false);
+  D (f22, 4.0, true);
+  D (f22, 5.0, false);
+  D (f22, 6.0, true);
+  D (f23, 4.0, false);
+  D (f23, 5.0, false);
+  D (f23, 6.0, true);
+  D (f24, 4.0, true);
+  D (f24, 5.0, true);
+  D (f24, 6.0, false);
+}

Reply via email to