diff options
author | CoprDistGit <infra@openeuler.org> | 2023-10-17 02:15:03 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2023-10-17 02:15:03 +0000 |
commit | cc47ed6ddebfece0584ad7ee706549614d16c0f0 (patch) | |
tree | 973a28470803b27c914f813f43d43f8932763ea3 /0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch | |
parent | 1e2198a988cc8d2ea55ab6ca2a1835e60149ab5c (diff) |
automatic import of gccopeneuler22.03_LTS_SP2
Diffstat (limited to '0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch')
-rw-r--r-- | 0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch b/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch new file mode 100644 index 0000000..df34234 --- /dev/null +++ b/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch @@ -0,0 +1,251 @@ +From 77398954ce517aa011b7a254c7aa2858521b2093 Mon Sep 17 00:00:00 2001 +From: Richard Biener <rguenther@suse.de> +Date: Mon, 15 Nov 2021 15:19:36 +0100 +Subject: [PATCH 18/35] [Backport] tree-optimization/102880 - make PHI-OPT + recognize more CFGs + +Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=f98f373dd822b35c52356b753d528924e9f89678 + +This allows extra edges into the middle BB for the PHI-OPT +transforms using replace_phi_edge_with_variable that do not +end up moving stmts from that middle BB. This avoids regressing +gcc.dg/tree-ssa/ssa-hoist-4.c with the actual fix for PR102880 +where CFG cleanup has the choice to remove two forwarders and +picks "the wrong" leading to + + if (a > b) / + /\ / + / <BB> + / | + # PHI <a, b> + +rather than + + if (a > b) | + /\ | + <BB> \ | + / \ | + # PHI <a, b, b> + +but it's relatively straight-forward to support extra edges +into the middle-BB in paths ending in replace_phi_edge_with_variable +and that do not require moving stmts. That's because we really +only want to remove the edge from the condition to the middle BB. +Of course actually doing that means updating dominators in non-trival +ways which is why I kept the original code for the single edge +case and simply defer to CFG cleanup by adjusting the condition for +the complicated case. + +The testcase needs to be a GIMPLE one since it's quite unreliable +to produce the desired CFG. + +2021-11-15 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102880 + * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Push + single_pred (bb1) condition to places that really need it. + (match_simplify_replacement): Likewise. + (value_replacement): Likewise. + (replace_phi_edge_with_variable): Deal with extra edges + into the middle BB. + + * gcc.dg/tree-ssa/phi-opt-26.c: New testcase. +--- + gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c | 31 +++++++++ + gcc/tree-ssa-phiopt.c | 73 +++++++++++++--------- + 2 files changed, 75 insertions(+), 29 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c + +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c +new file mode 100644 +index 000000000..21aa66e38 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-26.c +@@ -0,0 +1,31 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O -fgimple -fdump-tree-phiopt1" } */ ++ ++int __GIMPLE (ssa,startwith("phiopt")) ++foo (int a, int b, int flag) ++{ ++ int res; ++ ++ __BB(2): ++ if (flag_2(D) != 0) ++ goto __BB6; ++ else ++ goto __BB4; ++ ++ __BB(4): ++ if (a_3(D) > b_4(D)) ++ goto __BB7; ++ else ++ goto __BB6; ++ ++ __BB(6): ++ goto __BB7; ++ ++ __BB(7): ++ res_1 = __PHI (__BB4: a_3(D), __BB6: b_4(D)); ++ return res_1; ++} ++ ++/* We should be able to detect MAX despite the extra edge into ++ the middle BB. */ ++/* { dg-final { scan-tree-dump "MAX" "phiopt1" } } */ +diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c +index 21ac08145..079d29e74 100644 +--- a/gcc/tree-ssa-phiopt.c ++++ b/gcc/tree-ssa-phiopt.c +@@ -219,7 +219,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + + /* If either bb1's succ or bb2 or bb2's succ is non NULL. */ + if (EDGE_COUNT (bb1->succs) == 0 +- || bb2 == NULL + || EDGE_COUNT (bb2->succs) == 0) + continue; + +@@ -279,14 +278,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + || (e1->flags & EDGE_FALLTHRU) == 0) + continue; + +- /* Also make sure that bb1 only have one predecessor and that it +- is bb. */ +- if (!single_pred_p (bb1) +- || single_pred (bb1) != bb) +- continue; +- + if (do_store_elim) + { ++ /* Also make sure that bb1 only have one predecessor and that it ++ is bb. */ ++ if (!single_pred_p (bb1) ++ || single_pred (bb1) != bb) ++ continue; ++ + /* bb1 is the middle block, bb2 the join block, bb the split block, + e1 the fallthrough edge from bb1 to bb2. We can't do the + optimization if the join block has more than two predecessors. */ +@@ -331,10 +330,11 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + node. */ + gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); + +- gphi *newphi = factor_out_conditional_conversion (e1, e2, phi, +- arg0, arg1, +- cond_stmt); +- if (newphi != NULL) ++ gphi *newphi; ++ if (single_pred_p (bb1) ++ && (newphi = factor_out_conditional_conversion (e1, e2, phi, ++ arg0, arg1, ++ cond_stmt))) + { + phi = newphi; + /* factor_out_conditional_conversion may create a new PHI in +@@ -355,12 +355,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) + cfgchanged = true; + else if (!early_p ++ && single_pred_p (bb1) + && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2, + phi, arg0, arg1)) + 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)) ++ else if (single_pred_p (bb1) ++ && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) + cfgchanged = true; + } + } +@@ -391,35 +393,41 @@ replace_phi_edge_with_variable (basic_block cond_block, + edge e, gphi *phi, tree new_tree) + { + basic_block bb = gimple_bb (phi); +- basic_block block_to_remove; + gimple_stmt_iterator gsi; + + /* Change the PHI argument to new. */ + SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree); + + /* Remove the empty basic block. */ ++ edge edge_to_remove; + if (EDGE_SUCC (cond_block, 0)->dest == bb) ++ edge_to_remove = EDGE_SUCC (cond_block, 1); ++ else ++ edge_to_remove = EDGE_SUCC (cond_block, 0); ++ if (EDGE_COUNT (edge_to_remove->dest->preds) == 1) + { +- EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU; +- EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); +- EDGE_SUCC (cond_block, 0)->probability = profile_probability::always (); +- +- block_to_remove = EDGE_SUCC (cond_block, 1)->dest; ++ e->flags |= EDGE_FALLTHRU; ++ e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); ++ e->probability = profile_probability::always (); ++ delete_basic_block (edge_to_remove->dest); ++ ++ /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ ++ gsi = gsi_last_bb (cond_block); ++ gsi_remove (&gsi, true); + } + else + { +- EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU; +- EDGE_SUCC (cond_block, 1)->flags +- &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); +- EDGE_SUCC (cond_block, 1)->probability = profile_probability::always (); +- +- block_to_remove = EDGE_SUCC (cond_block, 0)->dest; ++ /* If there are other edges into the middle block make ++ CFG cleanup deal with the edge removal to avoid ++ updating dominators here in a non-trivial way. */ ++ gcond *cond = as_a <gcond *> (last_stmt (cond_block)); ++ if (edge_to_remove->flags & EDGE_TRUE_VALUE) ++ gimple_cond_make_false (cond); ++ else ++ gimple_cond_make_true (cond); + } +- delete_basic_block (block_to_remove); + +- /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ +- gsi = gsi_last_bb (cond_block); +- gsi_remove (&gsi, true); ++ statistics_counter_event (cfun, "Replace PHI with variable", 1); + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, +@@ -846,6 +854,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, + allow it and move it once the transformation is done. */ + if (!empty_block_p (middle_bb)) + { ++ if (!single_pred_p (middle_bb)) ++ return false; ++ + stmt_to_move = last_and_only_stmt (middle_bb); + if (!stmt_to_move) + return false; +@@ -1225,6 +1236,11 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, + } + else + { ++ if (!single_pred_p (middle_bb)) ++ return 0; ++ statistics_counter_event (cfun, "Replace PHI with " ++ "variable/value_replacement", 1); ++ + /* Replace the PHI arguments with arg. */ + SET_PHI_ARG_DEF (phi, e0->dest_idx, arg); + SET_PHI_ARG_DEF (phi, e1->dest_idx, arg); +@@ -1239,7 +1255,6 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, + } + return 1; + } +- + } + + /* Now optimize (x != 0) ? x + y : y to just x + y. */ +-- +2.27.0.windows.1 + |