On Thu, Oct 23, 2025 at 5:51 AM Andrew Pinski <[email protected]> wrote: > > Now all of the optimizations are done in match from > minmax_replacement. We can now remove minmax_replacement. :) > This keeps around the special case for fp `a CMP b ? a : b` that was > added with r14-2699-g9f8f37f5490076 (PR 88540) and moves it to > match_simplify_replacement. > > Bootsrapped and tested on x86_64-linux-gnu. > > Note bool-12.c needed to be updated since phiopt1 rejecting the > BIT_AND/BIT_IOR with a cast and not getting MIN/MAX any more.
Yay. OK. Thanks, Richard. > gcc/ChangeLog: > > PR tree-optimization/101024 > * tree-ssa-phiopt.cc (match_simplify_replacement): Special > case fp `a CMP b ? a : b` when not creating a min/max. > (strip_bit_not): Remove. > (invert_minmax_code): Remove. > (minmax_replacement): Remove. > (pass_phiopt::execute): Update pass comment. > Don't call minmax_replacement. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/bool-12.c: Update based on when BIT_AND/BIT_IOR > is created and no longer MIN/MAX. > > Signed-off-by: Andrew Pinski <[email protected]> > --- > gcc/testsuite/gcc.dg/tree-ssa/bool-12.c | 17 +- > gcc/tree-ssa-phiopt.cc | 671 +----------------------- > 2 files changed, 36 insertions(+), 652 deletions(-) > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-12.c > b/gcc/testsuite/gcc.dg/tree-ssa/bool-12.c > index e62594e1dad..244e5627f66 100644 > --- a/gcc/testsuite/gcc.dg/tree-ssa/bool-12.c > +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-12.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-original > -fdump-tree-phiopt1 -fdump-tree-forwprop2" } */ > +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-original > -fdump-tree-phiopt2-raw" } */ > #define bool _Bool > int maxbool(bool ab, bool bb) > { > @@ -28,15 +28,12 @@ int minbool(bool ab, bool bb) > /* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "original" } } */ > /* { dg-final { scan-tree-dump-times "if " 2 "original" } } */ > > -/* PHI-OPT1 should have converted it into min/max */ > -/* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ > -/* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ > -/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1" } } */ > - > -/* Forwprop2 (after ccp) will convert it into &\| */ > -/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "forwprop2" } } */ > -/* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "forwprop2" } } */ > -/* { dg-final { scan-tree-dump-times "if " 0 "forwprop2" } } */ > +/* PHI-OPT2 should have converted it into &\| */ > +/* { dg-final { scan-tree-dump-not "min_expr, " "phiopt2" } } */ > +/* { dg-final { scan-tree-dump-not "max_expr, " "phiopt2" } } */ > +/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 1 "phiopt2" } } */ > +/* { dg-final { scan-tree-dump-times "bit_and_expr, " 1 "phiopt2" } } */ > +/* { dg-final { scan-tree-dump-times "gimple_cond " 0 "phiopt2" } } */ > > /* By optimize there should be no min/max nor if */ > /* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "optimized" } } */ > diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc > index 031184d9e58..88153d37720 100644 > --- a/gcc/tree-ssa-phiopt.cc > +++ b/gcc/tree-ssa-phiopt.cc > @@ -1007,7 +1007,34 @@ match_simplify_replacement (basic_block cond_bb, > basic_block middle_bb, > } > > if (!result) > - return false; > + { > + /* If we don't get back a MIN/MAX_EXPR still make sure the expression > + stays in a form to be recognized by ISA that map to IEEE x > y ? x : > y > + semantics (that's not IEEE max semantics). */ > + if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)) > + return false; > + if (stmt_to_move || stmt_to_move_alt) > + return false; > + tree_code cmp = gimple_cond_code (stmt); > + if (cmp != LT_EXPR && cmp != LE_EXPR > + && cmp != GT_EXPR && cmp != GE_EXPR) > + return false; > + tree lhs = gimple_cond_lhs (stmt); > + tree rhs = gimple_cond_rhs (stmt); > + /* `lhs CMP rhs ? lhs : rhs` or `lhs CMP rhs ? rhs : lhs` > + are only acceptable case here. */ > + if ((!operand_equal_for_phi_arg_p (lhs, arg_false) > + || !operand_equal_for_phi_arg_p (rhs, arg_true)) > + && (!operand_equal_for_phi_arg_p (rhs, arg_false) > + || !operand_equal_for_phi_arg_p (lhs, arg_true))) > + return false; > + seq = nullptr; > + result = gimple_build (&seq, cmp, boolean_type_node, lhs, rhs); > + result = gimple_build (&seq, COND_EXPR, type, result, > + arg_true, arg_false); > + statistics_counter_event (cfun, "Non-IEEE FP MIN/MAX PHI replacement", > + 1); > + } > if (dump_file && (dump_flags & TDF_FOLDING)) > fprintf (dump_file, "accepted the phiopt match-simplify.\n"); > > @@ -1767,622 +1794,6 @@ value_replacement (basic_block cond_bb, basic_block > middle_bb, > return 0; > } > > -/* If VAR is an SSA_NAME that points to a BIT_NOT_EXPR then return the TREE > for > - the value being inverted. */ > - > -static tree > -strip_bit_not (tree var) > -{ > - if (TREE_CODE (var) != SSA_NAME) > - return NULL_TREE; > - > - gimple *assign = SSA_NAME_DEF_STMT (var); > - if (gimple_code (assign) != GIMPLE_ASSIGN) > - return NULL_TREE; > - > - if (gimple_assign_rhs_code (assign) != BIT_NOT_EXPR) > - return NULL_TREE; > - > - return gimple_assign_rhs1 (assign); > -} > - > -/* Invert a MIN to a MAX or a MAX to a MIN expression CODE. */ > - > -enum tree_code > -invert_minmax_code (enum tree_code code) > -{ > - switch (code) { > - case MIN_EXPR: > - return MAX_EXPR; > - case MAX_EXPR: > - return MIN_EXPR; > - default: > - gcc_unreachable (); > - } > -} > - > -/* The function minmax_replacement does the main work of doing the minmax > - replacement. Return true if the replacement is done. Otherwise return > - false. > - BB is the basic block where the replacement is going to be done on. ARG0 > - is argument 0 from the PHI. Likewise for ARG1. > - > - If THREEWAY_P then expect the BB to be laid out in diamond shape with > each > - BB containing only a MIN or MAX expression. */ > - > -static bool > -minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block > alt_middle_bb, > - edge e0, edge e1, gphi *phi, tree arg0, tree arg1, bool > threeway_p) > -{ > - tree result; > - edge true_edge, false_edge; > - enum tree_code minmax, ass_code; > - tree smaller, larger, arg_true, arg_false; > - gimple_stmt_iterator gsi, gsi_from; > - > - tree type = TREE_TYPE (gimple_phi_result (phi)); > - > - gcond *cond = as_a <gcond *> (*gsi_last_bb (cond_bb)); > - enum tree_code cmp = gimple_cond_code (cond); > - tree rhs = gimple_cond_rhs (cond); > - > - /* Turn EQ/NE of extreme values to order comparisons. */ > - if ((cmp == NE_EXPR || cmp == EQ_EXPR) > - && TREE_CODE (rhs) == INTEGER_CST > - && INTEGRAL_TYPE_P (TREE_TYPE (rhs))) > - { > - if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs)))) > - { > - cmp = (cmp == EQ_EXPR) ? LT_EXPR : GE_EXPR; > - rhs = wide_int_to_tree (TREE_TYPE (rhs), > - wi::min_value (TREE_TYPE (rhs)) + 1); > - } > - else if (wi::eq_p (wi::to_wide (rhs), wi::max_value (TREE_TYPE (rhs)))) > - { > - cmp = (cmp == EQ_EXPR) ? GT_EXPR : LE_EXPR; > - rhs = wide_int_to_tree (TREE_TYPE (rhs), > - wi::max_value (TREE_TYPE (rhs)) - 1); > - } > - } > - > - /* This transformation is only valid for order comparisons. Record which > - operand is smaller/larger if the result of the comparison is true. */ > - tree alt_smaller = NULL_TREE; > - tree alt_larger = NULL_TREE; > - if (cmp == LT_EXPR || cmp == LE_EXPR) > - { > - smaller = gimple_cond_lhs (cond); > - larger = rhs; > - /* If we have smaller < CST it is equivalent to smaller <= CST-1. > - Likewise smaller <= CST is equivalent to smaller < CST+1. */ > - if (TREE_CODE (larger) == INTEGER_CST > - && INTEGRAL_TYPE_P (TREE_TYPE (larger))) > - { > - if (cmp == LT_EXPR) > - { > - wi::overflow_type overflow; > - wide_int alt = wi::sub (wi::to_wide (larger), 1, > - TYPE_SIGN (TREE_TYPE (larger)), > - &overflow); > - if (! overflow) > - alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt); > - } > - else > - { > - wi::overflow_type overflow; > - wide_int alt = wi::add (wi::to_wide (larger), 1, > - TYPE_SIGN (TREE_TYPE (larger)), > - &overflow); > - if (! overflow) > - alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt); > - } > - } > - } > - else if (cmp == GT_EXPR || cmp == GE_EXPR) > - { > - smaller = rhs; > - larger = gimple_cond_lhs (cond); > - /* If we have larger > CST it is equivalent to larger >= CST+1. > - Likewise larger >= CST is equivalent to larger > CST-1. */ > - if (TREE_CODE (smaller) == INTEGER_CST > - && INTEGRAL_TYPE_P (TREE_TYPE (smaller))) > - { > - wi::overflow_type overflow; > - if (cmp == GT_EXPR) > - { > - wide_int alt = wi::add (wi::to_wide (smaller), 1, > - TYPE_SIGN (TREE_TYPE (smaller)), > - &overflow); > - if (! overflow) > - alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt); > - } > - else > - { > - wide_int alt = wi::sub (wi::to_wide (smaller), 1, > - TYPE_SIGN (TREE_TYPE (smaller)), > - &overflow); > - if (! overflow) > - alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt); > - } > - } > - } > - else > - return false; > - > - /* Handle the special case of (signed_type)x < 0 being equivalent > - to x > MAX_VAL(signed_type) and (signed_type)x >= 0 equivalent > - to x <= MAX_VAL(signed_type). */ > - if ((cmp == GE_EXPR || cmp == LT_EXPR) > - && INTEGRAL_TYPE_P (type) > - && TYPE_UNSIGNED (type) > - && integer_zerop (rhs)) > - { > - tree op = gimple_cond_lhs (cond); > - if (TREE_CODE (op) == SSA_NAME > - && INTEGRAL_TYPE_P (TREE_TYPE (op)) > - && !TYPE_UNSIGNED (TREE_TYPE (op))) > - { > - gimple *def_stmt = SSA_NAME_DEF_STMT (op); > - if (gimple_assign_cast_p (def_stmt)) > - { > - tree op1 = gimple_assign_rhs1 (def_stmt); > - if (INTEGRAL_TYPE_P (TREE_TYPE (op1)) > - && TYPE_UNSIGNED (TREE_TYPE (op1)) > - && (TYPE_PRECISION (TREE_TYPE (op)) > - == TYPE_PRECISION (TREE_TYPE (op1))) > - && useless_type_conversion_p (type, TREE_TYPE (op1))) > - { > - wide_int w1 = wi::max_value (TREE_TYPE (op)); > - wide_int w2 = wi::add (w1, 1); > - if (cmp == LT_EXPR) > - { > - larger = op1; > - smaller = wide_int_to_tree (TREE_TYPE (op1), w1); > - alt_smaller = wide_int_to_tree (TREE_TYPE (op1), w2); > - alt_larger = NULL_TREE; > - } > - else > - { > - smaller = op1; > - larger = wide_int_to_tree (TREE_TYPE (op1), w1); > - alt_larger = wide_int_to_tree (TREE_TYPE (op1), w2); > - alt_smaller = NULL_TREE; > - } > - } > - } > - } > - } > - > - /* We need to know which is the true edge and which is the false > - edge so that we know if have abs or negative abs. */ > - extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); > - > - /* Forward the edges over the middle basic block. */ > - if (true_edge->dest == middle_bb) > - true_edge = EDGE_SUCC (true_edge->dest, 0); > - if (false_edge->dest == middle_bb) > - false_edge = EDGE_SUCC (false_edge->dest, 0); > - > - /* When THREEWAY_P then e1 will point to the edge of the final transition > - from middle-bb to end. */ > - if (true_edge == e0) > - { > - if (!threeway_p) > - gcc_assert (false_edge == e1); > - arg_true = arg0; > - arg_false = arg1; > - } > - else > - { > - gcc_assert (false_edge == e0); > - if (!threeway_p) > - gcc_assert (true_edge == e1); > - arg_true = arg1; > - arg_false = arg0; > - } > - > - if (empty_block_p (middle_bb) > - && (!threeway_p > - || empty_block_p (alt_middle_bb))) > - { > - if ((operand_equal_for_phi_arg_p (arg_true, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (arg_true, alt_smaller))) > - && (operand_equal_for_phi_arg_p (arg_false, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (arg_true, alt_larger)))) > - { > - /* Case > - > - if (smaller < larger) > - rslt = smaller; > - else > - rslt = larger; */ > - minmax = MIN_EXPR; > - } > - else if ((operand_equal_for_phi_arg_p (arg_false, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (arg_false, alt_smaller))) > - && (operand_equal_for_phi_arg_p (arg_true, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (arg_true, > alt_larger)))) > - minmax = MAX_EXPR; > - else > - return false; > - } > - else if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type)) > - /* The optimization may be unsafe due to NaNs. */ > - return false; > - else if (middle_bb != alt_middle_bb && threeway_p) > - { > - /* Recognize the following case: > - > - if (smaller < larger) > - a = MIN (smaller, c); > - else > - b = MIN (larger, c); > - x = PHI <a, b> > - > - This is equivalent to > - > - a = MIN (smaller, c); > - x = MIN (larger, a); */ > - > - gimple *assign = last_and_only_stmt (middle_bb); > - tree lhs, op0, op1, bound; > - tree alt_lhs, alt_op0, alt_op1; > - bool invert = false; > - > - /* When THREEWAY_P then e1 will point to the edge of the final > transition > - from middle-bb to end. */ > - if (true_edge == e0) > - gcc_assert (false_edge == EDGE_PRED (e1->src, 0)); > - else > - gcc_assert (true_edge == EDGE_PRED (e1->src, 0)); > - > - bool valid_minmax_p = false; > - gimple_stmt_iterator it1 > - = gsi_start_nondebug_after_labels_bb (middle_bb); > - gimple_stmt_iterator it2 > - = gsi_start_nondebug_after_labels_bb (alt_middle_bb); > - if (gsi_one_nondebug_before_end_p (it1) > - && gsi_one_nondebug_before_end_p (it2)) > - { > - gimple *stmt1 = gsi_stmt (it1); > - gimple *stmt2 = gsi_stmt (it2); > - if (is_gimple_assign (stmt1) && is_gimple_assign (stmt2)) > - { > - enum tree_code code1 = gimple_assign_rhs_code (stmt1); > - enum tree_code code2 = gimple_assign_rhs_code (stmt2); > - valid_minmax_p = (code1 == MIN_EXPR || code1 == MAX_EXPR) > - && (code2 == MIN_EXPR || code2 == MAX_EXPR); > - } > - } > - > - if (!valid_minmax_p) > - return false; > - > - if (!assign > - || gimple_code (assign) != GIMPLE_ASSIGN) > - return false; > - > - /* There cannot be any phi nodes in the middle bb. */ > - if (!gimple_seq_empty_p (phi_nodes (middle_bb))) > - return false; > - > - lhs = gimple_assign_lhs (assign); > - ass_code = gimple_assign_rhs_code (assign); > - if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) > - return false; > - > - op0 = gimple_assign_rhs1 (assign); > - op1 = gimple_assign_rhs2 (assign); > - > - assign = last_and_only_stmt (alt_middle_bb); > - if (!assign > - || gimple_code (assign) != GIMPLE_ASSIGN) > - return false; > - > - /* There cannot be any phi nodes in the alt middle bb. */ > - if (!gimple_seq_empty_p (phi_nodes (alt_middle_bb))) > - return false; > - > - alt_lhs = gimple_assign_lhs (assign); > - if (ass_code != gimple_assign_rhs_code (assign)) > - return false; > - > - if (!operand_equal_for_phi_arg_p (lhs, arg_true) > - || !operand_equal_for_phi_arg_p (alt_lhs, arg_false)) > - return false; > - > - alt_op0 = gimple_assign_rhs1 (assign); > - alt_op1 = gimple_assign_rhs2 (assign); > - > - if ((operand_equal_for_phi_arg_p (op0, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (op0, alt_smaller))) > - && (operand_equal_for_phi_arg_p (alt_op0, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (alt_op0, alt_larger)))) > - { > - /* We got here if the condition is true, i.e., SMALLER < LARGER. */ > - if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > - return false; > - > - if ((arg0 = strip_bit_not (op0)) != NULL > - && (arg1 = strip_bit_not (alt_op0)) != NULL > - && (bound = strip_bit_not (op1)) != NULL) > - { > - minmax = MAX_EXPR; > - ass_code = invert_minmax_code (ass_code); > - invert = true; > - } > - else > - { > - bound = op1; > - minmax = MIN_EXPR; > - arg0 = op0; > - arg1 = alt_op0; > - } > - } > - else if ((operand_equal_for_phi_arg_p (op0, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (op0, alt_larger))) > - && (operand_equal_for_phi_arg_p (alt_op0, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (alt_op0, > alt_smaller)))) > - { > - /* We got here if the condition is true, i.e., SMALLER > LARGER. */ > - if (!operand_equal_for_phi_arg_p (op1, alt_op1)) > - return false; > - > - if ((arg0 = strip_bit_not (op0)) != NULL > - && (arg1 = strip_bit_not (alt_op0)) != NULL > - && (bound = strip_bit_not (op1)) != NULL) > - { > - minmax = MIN_EXPR; > - ass_code = invert_minmax_code (ass_code); > - invert = true; > - } > - else > - { > - bound = op1; > - minmax = MAX_EXPR; > - arg0 = op0; > - arg1 = alt_op0; > - } > - } > - else > - return false; > - > - /* Emit the statement to compute min/max. */ > - location_t locus = gimple_location (last_nondebug_stmt (cond_bb)); > - gimple_seq stmts = NULL; > - tree phi_result = gimple_phi_result (phi); > - result = gimple_build (&stmts, locus, minmax, TREE_TYPE (phi_result), > - arg0, arg1); > - result = gimple_build (&stmts, locus, ass_code, TREE_TYPE (phi_result), > - result, bound); > - if (invert) > - result = gimple_build (&stmts, locus, BIT_NOT_EXPR, TREE_TYPE > (phi_result), > - result); > - > - gsi = gsi_last_bb (cond_bb); > - gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); > - > - replace_phi_edge_with_variable (cond_bb, e1, phi, result); > - > - return true; > - } > - else if (!threeway_p > - || empty_block_p (alt_middle_bb)) > - { > - /* Recognize the following case, assuming d <= u: > - > - if (a <= u) > - b = MAX (a, d); > - x = PHI <b, u> > - > - This is equivalent to > - > - b = MAX (a, d); > - x = MIN (b, u); */ > - > - gimple *assign = last_and_only_stmt (middle_bb); > - tree lhs, op0, op1, bound; > - > - if (!single_pred_p (middle_bb)) > - return false; > - > - if (!assign > - || gimple_code (assign) != GIMPLE_ASSIGN) > - return false; > - > - /* There cannot be any phi nodes in the middle bb. */ > - if (!gimple_seq_empty_p (phi_nodes (middle_bb))) > - return false; > - > - lhs = gimple_assign_lhs (assign); > - ass_code = gimple_assign_rhs_code (assign); > - if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) > - return false; > - op0 = gimple_assign_rhs1 (assign); > - op1 = gimple_assign_rhs2 (assign); > - > - if (true_edge->src == middle_bb) > - { > - /* We got here if the condition is true, i.e., SMALLER < LARGER. */ > - if (!operand_equal_for_phi_arg_p (lhs, arg_true)) > - return false; > - > - if (operand_equal_for_phi_arg_p (arg_false, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (arg_false, alt_larger))) > - { > - /* Case > - > - if (smaller < larger) > - { > - r' = MAX_EXPR (smaller, bound) > - } > - r = PHI <r', larger> --> to be turned to MIN_EXPR. */ > - if (ass_code != MAX_EXPR) > - return false; > - > - minmax = MIN_EXPR; > - if (operand_equal_for_phi_arg_p (op0, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (op0, alt_smaller))) > - bound = op1; > - else if (operand_equal_for_phi_arg_p (op1, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (op1, alt_smaller))) > - bound = op0; > - else > - return false; > - > - /* We need BOUND <= LARGER. */ > - if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node, > - bound, arg_false))) > - return false; > - } > - else if (operand_equal_for_phi_arg_p (arg_false, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (arg_false, > alt_smaller))) > - { > - /* Case > - > - if (smaller < larger) > - { > - r' = MIN_EXPR (larger, bound) > - } > - r = PHI <r', smaller> --> to be turned to MAX_EXPR. */ > - if (ass_code != MIN_EXPR) > - return false; > - > - minmax = MAX_EXPR; > - if (operand_equal_for_phi_arg_p (op0, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (op0, alt_larger))) > - bound = op1; > - else if (operand_equal_for_phi_arg_p (op1, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (op1, alt_larger))) > - bound = op0; > - else > - return false; > - > - /* We need BOUND >= SMALLER. */ > - if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node, > - bound, arg_false))) > - return false; > - } > - else > - return false; > - } > - else > - { > - /* We got here if the condition is false, i.e., SMALLER > LARGER. > */ > - if (!operand_equal_for_phi_arg_p (lhs, arg_false)) > - return false; > - > - if (operand_equal_for_phi_arg_p (arg_true, larger) > - || (alt_larger > - && operand_equal_for_phi_arg_p (arg_true, alt_larger))) > - { > - /* Case > - > - if (smaller > larger) > - { > - r' = MIN_EXPR (smaller, bound) > - } > - r = PHI <r', larger> --> to be turned to MAX_EXPR. */ > - if (ass_code != MIN_EXPR) > - return false; > - > - minmax = MAX_EXPR; > - if (operand_equal_for_phi_arg_p (op0, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (op0, alt_smaller))) > - bound = op1; > - else if (operand_equal_for_phi_arg_p (op1, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (op1, alt_smaller))) > - bound = op0; > - else > - return false; > - > - /* We need BOUND >= LARGER. */ > - if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node, > - bound, arg_true))) > - return false; > - } > - else if (operand_equal_for_phi_arg_p (arg_true, smaller) > - || (alt_smaller > - && operand_equal_for_phi_arg_p (arg_true, > alt_smaller))) > - { > - /* Case > - > - if (smaller > larger) > - { > - r' = MAX_EXPR (larger, bound) > - } > - r = PHI <r', smaller> --> to be turned to MIN_EXPR. */ > - if (ass_code != MAX_EXPR) > - return false; > - > - minmax = MIN_EXPR; > - if (operand_equal_for_phi_arg_p (op0, larger)) > - bound = op1; > - else if (operand_equal_for_phi_arg_p (op1, larger)) > - bound = op0; > - else > - return false; > - > - /* We need BOUND <= SMALLER. */ > - if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node, > - bound, arg_true))) > - return false; > - } > - else > - return false; > - } > - > - /* Move the statement from the middle block. */ > - gsi = gsi_last_bb (cond_bb); > - gsi_from = gsi_last_nondebug_bb (middle_bb); > - reset_flow_sensitive_info (SINGLE_SSA_TREE_OPERAND (gsi_stmt > (gsi_from), > - SSA_OP_DEF)); > - gsi_move_before (&gsi_from, &gsi); > - } > - else > - return false; > - > - /* Emit the statement to compute min/max. */ > - gimple_seq stmts = NULL; > - tree phi_result = gimple_phi_result (phi); > - > - /* When we can't use a MIN/MAX_EXPR still make sure the expression > - stays in a form to be recognized by ISA that map to IEEE x > y ? x : y > - semantics (that's not IEEE max semantics). */ > - if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type)) > - { > - result = gimple_build (&stmts, cmp, boolean_type_node, > - gimple_cond_lhs (cond), rhs); > - result = gimple_build (&stmts, COND_EXPR, TREE_TYPE (phi_result), > - result, arg_true, arg_false); > - } > - else > - result = gimple_build (&stmts, minmax, TREE_TYPE (phi_result), arg0, > arg1); > - > - gsi = gsi_last_bb (cond_bb); > - gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); > - > - replace_phi_edge_with_variable (cond_bb, e1, phi, result); > - > - 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) > @@ -4365,9 +3776,8 @@ execute_over_cond_phis (func_type func) > But in this case bb1/bb2 can only be forwarding basic blocks. > > This fully replaces the old "Conditional Replacement", > - "ABS Replacement" transformations as they are now > + "ABS Replacement" and "MIN/MAX Replacement" transformations as they are > now > implmeneted in match.pd. > - Some parts of the "MIN/MAX Replacement" are re-implemented in match.pd. > > Value Replacement > ----------------- > @@ -4409,26 +3819,6 @@ execute_over_cond_phis (func_type func) > t3 = t1 & t2; > x = a; > > - MIN/MAX Replacement > - ------------------- > - > - This transformation, minmax_replacement replaces > - > - bb0: > - if (a <= b) goto bb2; else goto bb1; > - bb1: > - bb2: > - x = PHI <b (bb1), a (bb0), ...>; > - > - with > - > - bb0: > - x' = MIN_EXPR (a, b) > - bb2: > - x = PHI <x' (bb0), ...>; > - > - A similar transformation is done for MAX_EXPR. > - > > This pass also performs a fifth transformation of a slightly different > flavor. > @@ -4642,9 +4032,6 @@ pass_phiopt::execute (function *) > && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2, > phi, arg0, arg1)) > cfgchanged = true; > - else if (minmax_replacement (bb, bb1, bb2, e1, e2, phi, arg0, arg1, > - diamond_p)) > - cfgchanged = true; > else if (single_pred_p (bb1) > && !diamond_p > && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) > -- > 2.43.0 >
