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.
This commit is contained in:
parent
8c775bf447
commit
4dcc7f03b5
1 changed files with 63 additions and 44 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue