summaryrefslogtreecommitdiff
path: root/0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-10-17 02:15:03 +0000
committerCoprDistGit <infra@openeuler.org>2023-10-17 02:15:03 +0000
commitcc47ed6ddebfece0584ad7ee706549614d16c0f0 (patch)
tree973a28470803b27c914f813f43d43f8932763ea3 /0066-Backport-tree-optimization-102880-make-PHI-OPT-recog.patch
parent1e2198a988cc8d2ea55ab6ca2a1835e60149ab5c (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.patch251
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
+