diff options
author | Andrew Pinski <apinski@marvell.com> | 2023-04-28 16:21:50 -0700 |
---|---|---|
committer | Andrew Pinski <apinski@marvell.com> | 2023-05-04 04:25:38 -0700 |
commit | d256dc28f0eadd0435df3483ddb2b249d5fec75f (patch) | |
tree | c3ff9da08900c0f7c46ba9078e9c535c9a74bca3 /gcc/tree-ssa-phiopt.cc | |
parent | 78b0eea7802698f51377f77aa98453556854a328 (diff) | |
download | gcc-d256dc28f0eadd0435df3483ddb2b249d5fec75f.zip gcc-d256dc28f0eadd0435df3483ddb2b249d5fec75f.tar.gz gcc-d256dc28f0eadd0435df3483ddb2b249d5fec75f.tar.bz2 |
PHIOPT: Improve replace_phi_edge_with_variable for diamond shapped bb
While looking at differences between what minmax_replacement
and match_simplify_replacement does. I noticed that they sometimes
chose different edges to remove. I decided we should be able to do
better and be able to remove both empty basic blocks in the
case of match_simplify_replacement as that moves the statements.
This also updates the testcases as now match_simplify_replacement
will remove the unused MIN/MAX_EXPR and they were checking for
those.
OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
gcc/ChangeLog:
* tree-ssa-phiopt.cc (replace_phi_edge_with_variable): Handle
diamond form bb with forwarder only empty blocks better.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/minmax-15.c: Update test.
* gcc.dg/tree-ssa/minmax-16.c: Update test.
* gcc.dg/tree-ssa/minmax-3.c: Update test.
* gcc.dg/tree-ssa/minmax-4.c: Update test.
* gcc.dg/tree-ssa/minmax-5.c: Update test.
* gcc.dg/tree-ssa/minmax-8.c: Update test.
Diffstat (limited to 'gcc/tree-ssa-phiopt.cc')
-rw-r--r-- | gcc/tree-ssa-phiopt.cc | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 154a5ab..2f70463 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -94,6 +94,7 @@ replace_phi_edge_with_variable (basic_block cond_block, basic_block bb = gimple_bb (phi); gimple_stmt_iterator gsi; tree phi_result = PHI_RESULT (phi); + bool deleteboth = false; /* Duplicate range info if they are the only things setting the target PHI. This is needed as later on, the new_tree will be replacing @@ -137,7 +138,14 @@ replace_phi_edge_with_variable (basic_block cond_block, keep_edge = EDGE_SUCC (cond_block, 1); } else if ((keep_edge = find_edge (cond_block, e->src))) - ; + { + basic_block bb1 = EDGE_SUCC (cond_block, 0)->dest; + basic_block bb2 = EDGE_SUCC (cond_block, 1)->dest; + if (single_pred_p (bb1) && single_pred_p (bb2) + && single_succ_p (bb1) && single_succ_p (bb2) + && empty_block_p (bb1) && empty_block_p (bb2)) + deleteboth = true; + } else gcc_unreachable (); @@ -152,6 +160,31 @@ replace_phi_edge_with_variable (basic_block cond_block, gsi = gsi_last_bb (cond_block); gsi_remove (&gsi, true); } + else if (deleteboth) + { + basic_block bb1 = EDGE_SUCC (cond_block, 0)->dest; + basic_block bb2 = EDGE_SUCC (cond_block, 1)->dest; + + edge newedge = redirect_edge_and_branch (keep_edge, bb); + + /* The new edge should be the same. */ + gcc_assert (newedge == keep_edge); + + keep_edge->flags |= EDGE_FALLTHRU; + keep_edge->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); + keep_edge->probability = profile_probability::always (); + + /* Copy the edge's phi entry from the old one. */ + copy_phi_arg_into_existing_phi (e, keep_edge); + + /* Delete the old 2 empty basic blocks */ + delete_basic_block (bb1); + delete_basic_block (bb2); + + /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ + gsi = gsi_last_bb (cond_block); + gsi_remove (&gsi, true); + } else { /* If there are other edges into the middle block make |