aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-if-conv.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2020-09-25 13:08:48 +0200
committerRichard Biener <rguenther@suse.de>2020-09-25 13:11:53 +0200
commit4dcc7f03b54087638e084ac69d40d7507fe83bd8 (patch)
tree9887a0cbbf9948f9767ed49f93e505fbd81e6ae1 /gcc/tree-if-conv.c
parent8c775bf447e190024fa08c55e38db94dd013a393 (diff)
tree-optimization/97199 - fix virtual operand update in if-conversion
This fixes a corner case with virtual operand update in if-conversion by re-organizing the code to remove edges only after the last point we need virtual PHI operands to be available. 2020-09-25 Richard Biener <rguenther@suse.de> PR tree-optimization/97199 * tree-if-conv.c (combine_blocks): Remove edges only after looking at virtual PHI args.
Diffstat (limited to 'gcc/tree-if-conv.c')
-rw-r--r--gcc/tree-if-conv.c107
1 files changed, 63 insertions, 44 deletions
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 4b8d457867e..2062758f40f 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -2544,8 +2544,7 @@ combine_blocks (class loop *loop)
if (need_to_predicate)
predicate_statements (loop);
- /* Merge basic blocks: first remove all the edges in the loop,
- except for those from the exit block. */
+ /* Merge basic blocks. */
exit_bb = NULL;
bool *predicated = XNEWVEC (bool, orig_loop_num_nodes);
for (i = 0; i < orig_loop_num_nodes; i++)
@@ -2561,43 +2560,6 @@ combine_blocks (class loop *loop)
}
gcc_assert (exit_bb != loop->latch);
- for (i = 1; i < orig_loop_num_nodes; i++)
- {
- bb = ifc_bbs[i];
-
- for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
- {
- if (e->src == exit_bb)
- ei_next (&ei);
- else
- remove_edge (e);
- }
- }
-
- if (exit_bb != NULL)
- {
- if (exit_bb != loop->header)
- {
- /* Connect this node to loop header. */
- make_single_succ_edge (loop->header, exit_bb, EDGE_FALLTHRU);
- set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
- }
-
- /* Redirect non-exit edges to loop->latch. */
- FOR_EACH_EDGE (e, ei, exit_bb->succs)
- {
- if (!loop_exit_edge_p (loop, e))
- redirect_edge_and_branch (e, loop->latch);
- }
- set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
- }
- else
- {
- /* If the loop does not have an exit, reconnect header and latch. */
- make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
- set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
- }
-
merge_target_bb = loop->header;
/* Get at the virtual def valid for uses starting at the first block
@@ -2682,13 +2644,9 @@ combine_blocks (class loop *loop)
last = gsi_last_bb (merge_target_bb);
gsi_insert_seq_after_without_update (&last, bb_seq (bb), GSI_NEW_STMT);
set_bb_seq (bb, NULL);
-
- delete_basic_block (bb);
}
- /* If possible, merge loop header to the block with the exit edge.
- This reduces the number of basic blocks to two, to please the
- vectorizer that handles only loops with two nodes. */
+ /* Fixup virtual operands in the exit block. */
if (exit_bb
&& exit_bb != loop->header)
{
@@ -2698,6 +2656,11 @@ combine_blocks (class loop *loop)
vphi = get_virtual_phi (exit_bb);
if (vphi)
{
+ /* When there's just loads inside the loop a stray virtual
+ PHI merging the uses can appear, update last_vdef from
+ it. */
+ if (!last_vdef)
+ last_vdef = gimple_phi_arg_def (vphi, 0);
imm_use_iterator iter;
use_operand_p use_p;
gimple *use_stmt;
@@ -2711,7 +2674,63 @@ combine_blocks (class loop *loop)
gimple_stmt_iterator gsi = gsi_for_stmt (vphi);
remove_phi_node (&gsi, true);
}
+ }
+
+ /* Now remove all the edges in the loop, except for those from the exit
+ block and delete the blocks we elided. */
+ for (i = 1; i < orig_loop_num_nodes; i++)
+ {
+ bb = ifc_bbs[i];
+
+ for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
+ {
+ if (e->src == exit_bb)
+ ei_next (&ei);
+ else
+ remove_edge (e);
+ }
+ }
+ for (i = 1; i < orig_loop_num_nodes; i++)
+ {
+ bb = ifc_bbs[i];
+
+ if (bb == exit_bb || bb == loop->latch)
+ continue;
+
+ delete_basic_block (bb);
+ }
+
+ /* Re-connect the exit block. */
+ if (exit_bb != NULL)
+ {
+ if (exit_bb != loop->header)
+ {
+ /* Connect this node to loop header. */
+ make_single_succ_edge (loop->header, exit_bb, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
+ }
+ /* Redirect non-exit edges to loop->latch. */
+ FOR_EACH_EDGE (e, ei, exit_bb->succs)
+ {
+ if (!loop_exit_edge_p (loop, e))
+ redirect_edge_and_branch (e, loop->latch);
+ }
+ set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
+ }
+ else
+ {
+ /* If the loop does not have an exit, reconnect header and latch. */
+ make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
+ }
+
+ /* If possible, merge loop header to the block with the exit edge.
+ This reduces the number of basic blocks to two, to please the
+ vectorizer that handles only loops with two nodes. */
+ if (exit_bb
+ && exit_bb != loop->header)
+ {
if (can_merge_blocks_p (loop->header, exit_bb))
merge_blocks (loop->header, exit_bb);
}