Projects
Mega:23.03
gcc
_service:tar_scm:0061-Backport-Replace-conditio...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0061-Backport-Replace-conditional_replacement-with-match-.patch of Package gcc
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2