https://gcc.gnu.org/g:3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78
commit 3ed1ed8f0533f3f3f4372a2280c4e1c29304cd78 Author: Alexandre Oliva <ol...@gnu.org> Date: Thu Sep 19 02:43:51 2024 -0300 refactor ifcombine Diff: --- gcc/tree-ssa-ifcombine.cc | 181 +++++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 92 deletions(-) diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc index eb4317bebdfb..3d57c615d827 100644 --- a/gcc/tree-ssa-ifcombine.cc +++ b/gcc/tree-ssa-ifcombine.cc @@ -107,6 +107,14 @@ recognize_if_then_else (basic_block cond_bb, if (!*else_bb) *else_bb = e->dest; + gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (cond_bb)); + if (!cond) + return false; + + if (CONSTANT_CLASS_P (gimple_cond_lhs (cond)) + && CONSTANT_CLASS_P (gimple_cond_rhs (cond))) + return false; + return true; } @@ -407,15 +415,67 @@ fold_truth_andor_maybe_separate (location_t loc, enum tree_code rcode, tree rl_arg, tree rr_arg, tree *separatep); +/* Replace the conditions in INNER_COND and OUTER_COND with COND and COND2. + COND and COND2 are computed for insertion at INNER_COND, with OUTER_COND + replaced with a constant, but if there are intervening blocks, it's best to + adjust COND for insertion at OUTER_COND, placing COND2 at INNER_COND. */ + +static tree +ifcombine_replace_cond (gcond *inner_cond, bool inner_inv, + gcond *outer_cond, bool outer_inv, + tree cond, bool must_canon, + tree cond2) +{ + tree t = cond; + bool result_inv = inner_inv; + + /* ??? Support intervening blocks. */ + if (single_pred (gimple_bb (inner_cond)) != gimple_bb (outer_cond)) + return NULL_TREE; + + /* ??? Use both conditions. */ + if (cond2) + t = fold_build2 (TRUTH_AND_EXPR, TREE_TYPE (t), cond, cond2); + + /* ??? Insert at outer_cond. */ + if (result_inv) + t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t); + tree ret = t; + + if (tree tcanon = canonicalize_cond_expr_cond (t)) + ret = t = tcanon; + else if (must_canon) + return NULL_TREE; + if (!is_gimple_condexpr_for_cond (t)) + { + gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond); + t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond, + NULL, true, GSI_SAME_STMT); + } + gimple_cond_set_condition_from_tree (inner_cond, t); + update_stmt (inner_cond); + + /* Leave CFG optimization to cfg_cleanup. */ + gimple_cond_set_condition_from_tree (outer_cond, + outer_inv + ? boolean_false_node + : boolean_true_node); + update_stmt (outer_cond); + + update_profile_after_ifcombine (gimple_bb (inner_cond), + gimple_bb (outer_cond)); + + return ret; +} + /* If-convert on a and pattern with a common else block. The inner if is specified by its INNER_COND_BB, the outer by OUTER_COND_BB. - inner_inv, outer_inv and result_inv indicate whether the conditions - are inverted. + inner_inv, outer_inv indicate whether the conditions are inverted. Returns true if the edges to the common else basic-block were merged. */ static bool ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, - basic_block outer_cond_bb, bool outer_inv, bool result_inv) + basic_block outer_cond_bb, bool outer_inv) { gimple_stmt_iterator gsi; tree name1, name2, bit1, bit2, bits1, bits2; @@ -454,26 +514,13 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, t2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t); t2 = force_gimple_operand_gsi (&gsi, t2, true, NULL_TREE, true, GSI_SAME_STMT); - t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR, - boolean_type_node, t2, t); - t = canonicalize_cond_expr_cond (t); - if (!t) - return false; - if (!is_gimple_condexpr_for_cond (t)) - { - gsi = gsi_for_stmt (inner_cond); - t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond, - NULL, true, GSI_SAME_STMT); - } - gimple_cond_set_condition_from_tree (inner_cond, t); - update_stmt (inner_cond); - /* Leave CFG optimization to cfg_cleanup. */ - gimple_cond_set_condition_from_tree (outer_cond, - outer_inv ? boolean_false_node : boolean_true_node); - update_stmt (outer_cond); + t = fold_build2 (EQ_EXPR, boolean_type_node, t2, t); - update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb); + if (!ifcombine_replace_cond (inner_cond, inner_inv, + outer_cond, outer_inv, + t, true, NULL_TREE)) + return false; if (dump_file) { @@ -493,17 +540,10 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, In that case remove the outer test and change the inner one to test for name & (bits1 | bits2) != 0. */ else if (recognize_bits_test (inner_cond, &name1, &bits1, !inner_inv) - && recognize_bits_test (outer_cond, &name2, &bits2, !outer_inv)) + && recognize_bits_test (outer_cond, &name2, &bits2, !outer_inv)) { - gimple_stmt_iterator gsi; tree t; - if ((TREE_CODE (name1) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) - || (TREE_CODE (name2) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))) - return false; - /* Find the common name which is bit-tested. */ if (name1 == name2) ; @@ -519,6 +559,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, else return false; + if ((TREE_CODE (name1) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name1)) + || (TREE_CODE (name2) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name2))) + return false; + /* As we strip non-widening conversions in finding a common name that is tested make sure to end up with an integral type for building the bit operations. */ @@ -538,33 +584,14 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, bits1 = fold_convert (TREE_TYPE (bits2), bits1); } - /* Do it. */ - gsi = gsi_for_stmt (inner_cond); t = fold_build2 (BIT_IOR_EXPR, TREE_TYPE (name1), bits1, bits2); - t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, - true, GSI_SAME_STMT); t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (name1), name1, t); - t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, - true, GSI_SAME_STMT); - t = fold_build2 (result_inv ? NE_EXPR : EQ_EXPR, boolean_type_node, t, + t = fold_build2 (EQ_EXPR, boolean_type_node, t, build_int_cst (TREE_TYPE (t), 0)); - t = canonicalize_cond_expr_cond (t); - if (!t) + if (!ifcombine_replace_cond (inner_cond, inner_inv, + outer_cond, outer_inv, + t, false, NULL_TREE)) return false; - if (!is_gimple_condexpr_for_cond (t)) - { - gsi = gsi_for_stmt (inner_cond); - t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond, - NULL, true, GSI_SAME_STMT); - } - gimple_cond_set_condition_from_tree (inner_cond, t); - update_stmt (inner_cond); - - /* Leave CFG optimization to cfg_cleanup. */ - gimple_cond_set_condition_from_tree (outer_cond, - outer_inv ? boolean_false_node : boolean_true_node); - update_stmt (outer_cond); - update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb); if (dump_file) { @@ -584,7 +611,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison) { - tree t, ts = NULL_TREE; + tree t, ts = NULL_TREE, ts2 = NULL_TREE; enum tree_code inner_cond_code = gimple_cond_code (inner_cond); enum tree_code outer_cond_code = gimple_cond_code (outer_cond); @@ -617,7 +644,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, inner_cond_code, gimple_cond_lhs (inner_cond), gimple_cond_rhs (inner_cond), - NULL)))) + &ts2)))) { { tree t1, t2; @@ -643,38 +670,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, t = fold_build2_loc (gimple_location (inner_cond), TRUTH_AND_EXPR, boolean_type_node, t1, t2); } - gimplify_after_fold: - if (result_inv) - { - t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t); - result_inv = false; - } - gsi = gsi_for_stmt (inner_cond); - t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond, - NULL, true, GSI_SAME_STMT); } - /* ??? Fold should avoid this. */ - else if (ts && !is_gimple_condexpr_for_cond (t)) - goto gimplify_after_fold; - if (result_inv) - t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t); - t = canonicalize_cond_expr_cond (t); - if (!t) - return false; - if (!is_gimple_condexpr_for_cond (t)) - { - gsi = gsi_for_stmt (inner_cond); - t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond, - NULL, true, GSI_SAME_STMT); - } - gimple_cond_set_condition_from_tree (inner_cond, t); - update_stmt (inner_cond); - /* Leave CFG optimization to cfg_cleanup. */ - gimple_cond_set_condition_from_tree (outer_cond, - outer_inv ? boolean_false_node : boolean_true_node); - update_stmt (outer_cond); - update_profile_after_ifcombine (inner_cond_bb, outer_cond_bb); + if (!(t = ifcombine_replace_cond (inner_cond, inner_inv, + outer_cond, outer_inv, + t, false, ts2))) + return false; if (dump_file) { @@ -716,8 +717,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb, <else_bb> ... */ - return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, false, - false); + return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, false); } /* And a version where the outer condition is negated. */ @@ -734,8 +734,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb, <else_bb> ... */ - return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, true, - false); + return ifcombine_ifandif (inner_cond_bb, false, outer_cond_bb, true); } /* The || form is characterized by a common then_bb with the @@ -754,8 +753,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb, <then_bb> ... */ - return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, true, - true); + return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, true); } /* And a version where the outer condition is negated. */ @@ -771,8 +769,7 @@ tree_ssa_ifcombine_bb_1 (basic_block inner_cond_bb, basic_block outer_cond_bb, <then_bb> ... */ - return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, false, - true); + return ifcombine_ifandif (inner_cond_bb, true, outer_cond_bb, false); } return false;