diff options
Diffstat (limited to '0061-Backport-Replace-conditional_replacement-with-match-.patch')
-rw-r--r-- | 0061-Backport-Replace-conditional_replacement-with-match-.patch | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/0061-Backport-Replace-conditional_replacement-with-match-.patch b/0061-Backport-Replace-conditional_replacement-with-match-.patch new file mode 100644 index 0000000..12808be --- /dev/null +++ b/0061-Backport-Replace-conditional_replacement-with-match-.patch @@ -0,0 +1,249 @@ +From 406071e8c1838c824f06c35ef3cf9419aa543e6e Mon Sep 17 00:00:00 2001 +From: Andrew Pinski <apinski@marvell.com> +Date: Tue, 1 Jun 2021 01:05:09 +0000 +Subject: [PATCH 13/35] [Backport] Replace conditional_replacement with match + and simplify + +Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=9f55df63154a39d67ef5b24def7044bf87300831 + +This is the first of series of patches to simplify phi-opt +to use match and simplify in many cases. This simplification +will more things to optimize. + +This is what Richard requested in +https://gcc.gnu.org/pipermail/gcc-patches/2021-May/571197.html +and I think it is the right thing to do too. + +OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. + +gcc/ChangeLog: + + PR tree-optimization/25290 + * tree-ssa-phiopt.c (match_simplify_replacement): + New function. + (tree_ssa_phiopt_worker): Use match_simplify_replacement. + (two_value_replacement): Change the comment about + conditional_replacement. + (conditional_replacement): Delete. +--- + gcc/tree-ssa-phiopt.c | 144 ++++++++++++------------------------------ + 1 file changed, 39 insertions(+), 105 deletions(-) + +diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c +index 269eda21c..9fa6363b6 100644 +--- a/gcc/tree-ssa-phiopt.c ++++ b/gcc/tree-ssa-phiopt.c +@@ -52,8 +52,8 @@ along with GCC; see the file COPYING3. If not see + static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); + static bool two_value_replacement (basic_block, basic_block, edge, gphi *, + tree, tree); +-static bool conditional_replacement (basic_block, basic_block, +- edge, edge, gphi *, tree, tree); ++static bool match_simplify_replacement (basic_block, basic_block, ++ edge, edge, gphi *, tree, tree); + static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, + gimple *); + static int value_replacement (basic_block, basic_block, +@@ -349,8 +349,8 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1)) + cfgchanged = true; + else if (!early_p +- && conditional_replacement (bb, bb1, e1, e2, phi, +- arg0, arg1)) ++ && match_simplify_replacement (bb, bb1, e1, e2, phi, ++ arg0, arg1)) + cfgchanged = true; + else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) + cfgchanged = true; +@@ -662,7 +662,7 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb, + } + + /* Defer boolean x ? 0 : {1,-1} or x ? {1,-1} : 0 to +- conditional_replacement. */ ++ match_simplify_replacement. */ + if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE + && (integer_zerop (arg0) + || integer_zerop (arg1) +@@ -763,137 +763,71 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb, + return true; + } + +-/* The function conditional_replacement does the main work of doing the +- conditional replacement. Return true if the replacement is done. ++/* The function match_simplify_replacement does the main work of doing the ++ replacement using match and simplify. 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 PHI. Likewise for ARG1. */ + + static bool +-conditional_replacement (basic_block cond_bb, basic_block middle_bb, +- edge e0, edge e1, gphi *phi, +- tree arg0, tree arg1) ++match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, ++ edge e0, edge e1, gphi *phi, ++ tree arg0, tree arg1) + { +- tree result; + gimple *stmt; +- gassign *new_stmt; + tree cond; + gimple_stmt_iterator gsi; + edge true_edge, false_edge; +- tree new_var, new_var2; +- bool neg = false; +- int shift = 0; +- tree nonzero_arg; +- +- /* FIXME: Gimplification of complex type is too hard for now. */ +- /* We aren't prepared to handle vectors either (and it is a question +- if it would be worthwhile anyway). */ +- if (!(INTEGRAL_TYPE_P (TREE_TYPE (arg0)) +- || POINTER_TYPE_P (TREE_TYPE (arg0))) +- || !(INTEGRAL_TYPE_P (TREE_TYPE (arg1)) +- || POINTER_TYPE_P (TREE_TYPE (arg1)))) +- return false; ++ gimple_seq seq = NULL; ++ tree result; + +- /* The PHI arguments have the constants 0 and 1, or 0 and -1 or +- 0 and (1 << cst), then convert it to the conditional. */ +- if (integer_zerop (arg0)) +- nonzero_arg = arg1; +- else if (integer_zerop (arg1)) +- nonzero_arg = arg0; +- else +- return false; +- if (integer_pow2p (nonzero_arg)) +- { +- shift = tree_log2 (nonzero_arg); +- if (shift && POINTER_TYPE_P (TREE_TYPE (nonzero_arg))) +- return false; +- } +- else if (integer_all_onesp (nonzero_arg)) +- neg = true; +- else ++ if (!empty_block_p (middle_bb)) + return false; + +- if (!empty_block_p (middle_bb)) ++ /* Special case A ? B : B as this will always simplify to B. */ ++ if (operand_equal_for_phi_arg_p (arg0, arg1)) + return false; + +- /* At this point we know we have a GIMPLE_COND with two successors. ++ /* At this point we know we have a GIMPLE_COND with two successors. + One successor is BB, the other successor is an empty block which + falls through into BB. + +- There is a single PHI node at the join point (BB) and its arguments +- are constants (0, 1) or (0, -1) or (0, (1 << shift)). +- +- So, given the condition COND, and the two PHI arguments, we can +- rewrite this PHI into non-branching code: ++ There is a single PHI node at the join point (BB). + +- dest = (COND) or dest = COND' or dest = (COND) << shift +- +- We use the condition as-is if the argument associated with the +- true edge has the value one or the argument associated with the +- false edge as the value zero. Note that those conditions are not +- the same since only one of the outgoing edges from the GIMPLE_COND +- will directly reach BB and thus be associated with an argument. */ ++ So, given the condition COND, and the two PHI arguments, match and simplify ++ can happen on (COND) ? arg0 : arg1. */ + + stmt = last_stmt (cond_bb); +- result = PHI_RESULT (phi); + + /* To handle special cases like floating point comparison, it is easier and + less error-prone to build a tree and gimplify it on the fly though it is +- less efficient. */ +- cond = fold_build2_loc (gimple_location (stmt), +- gimple_cond_code (stmt), boolean_type_node, +- gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); ++ less efficient. ++ Don't use fold_build2 here as that might create (bool)a instead of just ++ "a != 0". */ ++ cond = build2_loc (gimple_location (stmt), ++ gimple_cond_code (stmt), boolean_type_node, ++ gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); + + /* We need to know which is the true edge and which is the false + edge so that we know when to invert the condition below. */ + extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); +- if ((e0 == true_edge && integer_zerop (arg0)) +- || (e0 == false_edge && !integer_zerop (arg0)) +- || (e1 == true_edge && integer_zerop (arg1)) +- || (e1 == false_edge && !integer_zerop (arg1))) +- cond = fold_build1_loc (gimple_location (stmt), +- TRUTH_NOT_EXPR, TREE_TYPE (cond), cond); +- +- if (neg) +- { +- cond = fold_convert_loc (gimple_location (stmt), +- TREE_TYPE (result), cond); +- cond = fold_build1_loc (gimple_location (stmt), +- NEGATE_EXPR, TREE_TYPE (cond), cond); +- } +- else if (shift) +- { +- cond = fold_convert_loc (gimple_location (stmt), +- TREE_TYPE (result), cond); +- cond = fold_build2_loc (gimple_location (stmt), +- LSHIFT_EXPR, TREE_TYPE (cond), cond, +- build_int_cst (integer_type_node, shift)); +- } ++ if (e1 == true_edge || e0 == false_edge) ++ std::swap (arg0, arg1); + +- /* Insert our new statements at the end of conditional block before the +- COND_STMT. */ +- gsi = gsi_for_stmt (stmt); +- new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true, +- GSI_SAME_STMT); ++ tree type = TREE_TYPE (gimple_phi_result (phi)); ++ result = gimple_simplify (COND_EXPR, type, ++ cond, ++ arg0, arg1, ++ &seq, NULL); ++ if (!result) ++ return false; + +- if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var))) +- { +- location_t locus_0, locus_1; ++ gsi = gsi_last_bb (cond_bb); + +- new_var2 = make_ssa_name (TREE_TYPE (result)); +- new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var); +- gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); +- new_var = new_var2; +- +- /* Set the locus to the first argument, unless is doesn't have one. */ +- locus_0 = gimple_phi_arg_location (phi, 0); +- locus_1 = gimple_phi_arg_location (phi, 1); +- if (locus_0 == UNKNOWN_LOCATION) +- locus_0 = locus_1; +- gimple_set_location (new_stmt, locus_0); +- } ++ if (seq) ++ gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); + +- replace_phi_edge_with_variable (cond_bb, e1, phi, new_var); ++ replace_phi_edge_with_variable (cond_bb, e1, phi, result); + + /* Note that we optimized this PHI. */ + return true; +@@ -3905,7 +3839,7 @@ gate_hoist_loads (void) + Conditional Replacement + ----------------------- + +- This transformation, implemented in conditional_replacement, ++ This transformation, implemented in match_simplify_replacement, + replaces + + bb0: +-- +2.27.0.windows.1 + |