From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 727B13857405 for ; Wed, 5 May 2021 13:18:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 727B13857405 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-40-GKvzZ-EGP1irge8759vUIg-1; Wed, 05 May 2021 09:18:17 -0400 X-MC-Unique: GKvzZ-EGP1irge8759vUIg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 42478107ACCA; Wed, 5 May 2021 13:18:16 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-114-59.ams2.redhat.com [10.36.114.59]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6B11560875; Wed, 5 May 2021 13:18:15 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 145DICUx3261251 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 5 May 2021 15:18:12 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 145DICAj3261250; Wed, 5 May 2021 15:18:12 +0200 Date: Wed, 5 May 2021 15:18:12 +0200 From: Jakub Jelinek To: Richard Biener Cc: Jonathan Wakely , Jason Merrill , gcc-patches@gcc.gnu.org Subject: [PATCH] phiopt, v2: Optimize (x <=> y) cmp z [PR94589] Message-ID: <20210505131812.GQ1179226@tucnak> Reply-To: Jakub Jelinek References: <20210504074413.GI1179226@tucnak> MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="Sh7h4lnU5nPTsIof" Content-Disposition: inline X-Spam-Status: No, score=-5.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SCC_10_SHORT_WORD_LINES, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 May 2021 13:18:23 -0000 --Sh7h4lnU5nPTsIof Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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: - : + : // cond3_bb (== cond2_bb) if (x_4(D) != y_5(D)) goto ; [INV] else goto ; [INV] - : + : // cond_bb if (x_4(D) < y_5(D)) goto ; [INV] else goto ; [INV] - : + : // middle_bb - : + : // phi_bb # iftmp.0_2 = PHI <1(4), 0(2), -1(3)> _1 = iftmp.0_2 == 0; and for partial ordering <=> something like: - : + : // cond3_bb if (a_3(D) == b_5(D)) goto ; [50.00%] else goto ; [50.00%] - [local count: 536870913]: + [local count: 536870913]: // cond2_bb if (a_3(D) < b_5(D)) goto ; [50.00%] else goto ; [50.00%] - [local count: 268435456]: + [local count: 268435456]: // cond_bb if (a_3(D) > b_5(D)) goto ; [50.00%] else goto ; [50.00%] - [local count: 134217728]: + [local count: 134217728]: // middle_bb - [local count: 1073741824]: + [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 (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 (cond3)); - else - gimple_cond_make_false (as_a (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 --Sh7h4lnU5nPTsIof Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=S932 2021-05-05 Jakub Jelinek 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: + : // cond3_bb (== cond2_bb) + if (x_4(D) != y_5(D)) + goto ; [INV] + else + goto ; [INV] + + : // cond_bb + if (x_4(D) < y_5(D)) + goto ; [INV] + else + goto ; [INV] + + : // middle_bb + + : // phi_bb + # iftmp.0_2 = PHI <1(4), 0(2), -1(3)> + _1 = iftmp.0_2 == 0; + + and for partial ordering <=> something like: + + : // cond3_bb + if (a_3(D) == b_5(D)) + goto ; [50.00%] + else + goto ; [50.00%] + + [local count: 536870913]: // cond2_bb + if (a_3(D) < b_5(D)) + goto ; [50.00%] + else + goto ; [50.00%] + + [local count: 268435456]: // cond_bb + if (a_3(D) > b_5(D)) + goto ; [50.00%] + else + goto ; [50.00%] + + [local count: 134217728]: // middle_bb + + [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 (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 (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 + +#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 + +#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); +} --Sh7h4lnU5nPTsIof--