From: Kyrylo Tkachov <[email protected]>
The three noce conversion routines that rewrite the CFG on success -
noce_process_if_block, noce_convert_multiple_sets and
cond_move_process_if_block - each open-code the same steps: delete the
THEN (and ELSE) blocks, or for an if-then drop the fall-through edge that
bypassed THEN, redirect the test block to the join block and merge the two
when possible.
Move this into noce_finish_if_conversion and call it from all three. The
if-then case (no ELSE) is handled through if_info->else_bb being null,
matching what noce_convert_multiple_sets previously did by hand. No
functional change.
gcc/ChangeLog:
* ifcvt.cc (noce_finish_if_conversion): New function.
(noce_convert_multiple_sets): Use it. Remove now-unused locals.
(noce_process_if_block): Likewise.
(cond_move_process_if_block): Likewise.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/ifcvt.cc | 105 ++++++++++++++++++++-------------------------------
1 file changed, 41 insertions(+), 64 deletions(-)
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 0e7a6ab4e82..3d7054314b9 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -4099,6 +4099,42 @@ try_emit_cmove_seq (struct noce_if_info *if_info, rtx
temp,
return seq;
}
+/* Finish a successful noce if-conversion of IF_INFO whose replacement insns
+ have already been emitted before the branch. Delete the now-dead THEN
+ block, and ELSE too if this was a diamond. An IF-THEN-JOIN also has an edge
+ from TEST_BB straight to JOIN_BB that bypassed THEN, and that goes as well.
+ An IF-THEN-ELSE-JOIN has no such edge, and deleting ELSE_BB removes its two
+ edges instead. Redirect TEST_BB to JOIN_BB and merge the two when the tail
+ no longer needs its own block. */
+
+static void
+noce_finish_if_conversion (noce_if_info *if_info)
+{
+ basic_block test_bb = if_info->test_bb;
+ basic_block then_bb = if_info->then_bb;
+ basic_block else_bb = if_info->else_bb;
+ basic_block join_bb = if_info->join_bb;
+
+ if (else_bb)
+ {
+ delete_basic_block (else_bb);
+ num_true_changes++;
+ }
+ else
+ remove_edge (find_edge (test_bb, join_bb));
+
+ remove_edge (find_edge (then_bb, join_bb));
+ redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
+ delete_basic_block (then_bb);
+ num_true_changes++;
+
+ if (can_merge_blocks_p (test_bb, join_bb))
+ {
+ merge_blocks (test_bb, join_bb);
+ num_true_changes++;
+ }
+}
+
/* We have something like:
if (x > y)
@@ -4149,7 +4185,6 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
basic_block test_bb = if_info->test_bb;
basic_block then_bb = if_info->then_bb;
basic_block else_bb = if_info->else_bb;
- basic_block join_bb = if_info->join_bb;
rtx_insn *jump = if_info->jump;
rtx_insn *cond_earliest;
rtx_insn *insn;
@@ -4305,27 +4340,7 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
emit_insn_before_setloc (seq, if_info->jump, sequence_location);
- /* Clean up the THEN (and, for a diamond, ELSE) block and the edges into and
- out of the if-region. An IF-THEN-ELSE-JOIN has no test->join edge.
- Deleting ELSE_BB removes the test->else and else->join edges instead. */
- if (else_bb)
- {
- delete_basic_block (else_bb);
- num_true_changes++;
- }
- else
- remove_edge (find_edge (test_bb, join_bb));
- remove_edge (find_edge (then_bb, join_bb));
- redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
- delete_basic_block (then_bb);
- num_true_changes++;
-
- /* Maybe merge blocks now the jump is simple enough. */
- if (can_merge_blocks_p (test_bb, join_bb))
- {
- merge_blocks (test_bb, join_bb);
- num_true_changes++;
- }
+ noce_finish_if_conversion (if_info);
num_updated_if_blocks++;
if_info->transform_name = "noce_convert_multiple_sets";
@@ -4927,7 +4942,6 @@ noce_process_if_block (struct noce_if_info *if_info)
basic_block test_bb = if_info->test_bb; /* test block */
basic_block then_bb = if_info->then_bb; /* THEN */
basic_block else_bb = if_info->else_bb; /* ELSE or NULL */
- basic_block join_bb = if_info->join_bb; /* JOIN */
rtx_insn *jump = if_info->jump;
rtx cond = if_info->cond;
rtx_insn *insn_a, *insn_b;
@@ -5234,27 +5248,9 @@ noce_process_if_block (struct noce_if_info *if_info)
emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
}
- /* The original THEN and ELSE blocks may now be removed. The test block
- must now jump to the join block. If the test block and the join block
- can be merged, do so. */
- if (else_bb)
- {
- delete_basic_block (else_bb);
- num_true_changes++;
- }
- else
- remove_edge (find_edge (test_bb, join_bb));
-
- remove_edge (find_edge (then_bb, join_bb));
- redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
- delete_basic_block (then_bb);
- num_true_changes++;
-
- if (can_merge_blocks_p (test_bb, join_bb))
- {
- merge_blocks (test_bb, join_bb);
- num_true_changes++;
- }
+ /* The original THEN and ELSE blocks may now be removed and the test block
+ redirected to the join block. */
+ noce_finish_if_conversion (if_info);
num_updated_if_blocks++;
return true;
@@ -5420,10 +5416,8 @@ cond_move_convert_if_block (struct noce_if_info
*if_infop,
static bool
cond_move_process_if_block (struct noce_if_info *if_info)
{
- basic_block test_bb = if_info->test_bb;
basic_block then_bb = if_info->then_bb;
basic_block else_bb = if_info->else_bb;
- basic_block join_bb = if_info->join_bb;
rtx_insn *jump = if_info->jump;
rtx cond = if_info->cond;
rtx_insn *seq, *loc_insn;
@@ -5509,24 +5503,7 @@ cond_move_process_if_block (struct noce_if_info *if_info)
}
emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
- if (else_bb)
- {
- delete_basic_block (else_bb);
- num_true_changes++;
- }
- else
- remove_edge (find_edge (test_bb, join_bb));
-
- remove_edge (find_edge (then_bb, join_bb));
- redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
- delete_basic_block (then_bb);
- num_true_changes++;
-
- if (can_merge_blocks_p (test_bb, join_bb))
- {
- merge_blocks (test_bb, join_bb);
- num_true_changes++;
- }
+ noce_finish_if_conversion (if_info);
num_updated_if_blocks++;
success_p = true;
--
2.50.1 (Apple Git-155)