@@ -455,8 +455,8 @@ add_to_predicate_list (struct loop *loop, basic_block bb, tree nc)
return;
/* If dominance tells us this basic block is always executed,
- don't record any predicates for it. */
- if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
+ i.e. it postdominates the header, don't record any predicates for it. */
+ if (dominated_by_p (CDI_POST_DOMINATORS, loop->header, bb))
return;
dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
@@ -1025,11 +1025,10 @@ has_pred_critical_p (basic_block bb)
Last restriction is valid if aggressive_if_conv is false.
- EXIT_BB is the basic block containing the exit of the LOOP. BB is
- inside LOOP. */
+ BB is inside LOOP. */
static bool
-if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
+if_convertible_bb_p (struct loop *loop, basic_block bb)
{
edge e;
edge_iterator ei;
@@ -1044,30 +1043,6 @@ if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
&& !aggressive_if_conv)
return false;
- if (exit_bb)
- {
- if (bb != loop->latch)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "basic block after exit bb but before latch\n");
- return false;
- }
- else if (!empty_block_p (bb))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "non empty basic block after exit bb\n");
- return false;
- }
- else if (bb == loop->latch
- && bb != exit_bb
- && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "latch is not dominated by exit_block\n");
- return false;
- }
- }
-
/* Be less adventurous and handle only normal edges. */
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
@@ -1199,15 +1174,6 @@ predicate_bbs (loop_p loop)
tree cond;
gimple stmt;
- /* The loop latch and loop exit block are always executed and
- have no extra conditions to be processed: skip them. */
- if (bb == loop->latch
- || bb_with_exit_edge_p (loop, bb))
- {
- reset_bb_predicate (bb);
- continue;
- }
-
cond = bb_predicate (bb);
stmt = last_stmt (bb);
if (stmt && gimple_code (stmt) == GIMPLE_COND)
@@ -1271,7 +1237,6 @@ if_convertible_loop_p_1 (struct loop *loop,
{
bool res;
unsigned int i;
- basic_block exit_bb = NULL;
/* Don't if-convert the loop when the data dependences cannot be
computed: the loop won't be vectorized in that case. */
@@ -1295,11 +1260,8 @@ if_convertible_loop_p_1 (struct loop *loop,
{
basic_block bb = ifc_bbs[i];
- if (!if_convertible_bb_p (loop, bb, exit_bb))
+ if (!if_convertible_bb_p (loop, bb))
return false;
-
- if (bb_with_exit_edge_p (loop, bb))
- exit_bb = bb;
}
for (i = 0; i < loop->num_nodes; i++)
@@ -1375,14 +1337,11 @@ if_convertible_loop_p_1 (struct loop *loop,
- it is innermost,
- it has two or more basic blocks,
- it has only one exit,
- - loop header is not the exit edge,
- if its basic blocks and phi nodes are if convertible. */
static bool
if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
{
- edge e;
- edge_iterator ei;
bool res = false;
vec<data_reference_p> refs;
vec<ddr_p> ddrs;
@@ -1411,12 +1370,6 @@ if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
return false;
}
- /* If one of the loop header's edge is an exit edge then do not
- apply if-conversion. */
- FOR_EACH_EDGE (e, ei, loop->header->succs)
- if (loop_exit_edge_p (loop, e))
- return false;
-
refs.create (5);
ddrs.create (25);
auto_vec<loop_p, 3> loop_nest;
@@ -2249,7 +2202,6 @@ remove_conditions_and_labels (loop_p loop)
static void
combine_blocks (struct loop *loop, bool any_mask_load_store)
{
- basic_block bb, exit_bb, merge_target_bb;
unsigned int orig_loop_num_nodes = loop->num_nodes;
unsigned int i;
edge e;
@@ -2265,10 +2217,10 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
/* Merge basic blocks: first remove all the edges in the loop,
except for those from the exit block. */
- exit_bb = NULL;
+ basic_block exit_bb = NULL;
for (i = 0; i < orig_loop_num_nodes; i++)
{
- bb = ifc_bbs[i];
+ basic_block bb = ifc_bbs[i];
free_bb_predicate (bb);
if (bb_with_exit_edge_p (loop, bb))
{
@@ -2280,7 +2232,7 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
for (i = 1; i < orig_loop_num_nodes; i++)
{
- bb = ifc_bbs[i];
+ basic_block bb = ifc_bbs[i];
for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
{
@@ -2315,37 +2267,53 @@ combine_blocks (struct loop *loop, bool any_mask_load_store)
set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
}
- merge_target_bb = loop->header;
+ basic_block merge_target_bb = loop->header;
+ /* Indicates that any further statements must be inserted
+ _before_ the final jump. */
+ bool seen_exit = (loop->header == exit_bb);
for (i = 1; i < orig_loop_num_nodes; i++)
{
- gimple_stmt_iterator gsi;
- gimple_stmt_iterator last;
-
- bb = ifc_bbs[i];
+ basic_block bb = ifc_bbs[i];
- if (bb == exit_bb || bb == loop->latch)
- continue;
+ if (bb == exit_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. */
+ if (can_merge_blocks_p (loop->header, bb))
+ merge_blocks (loop->header, bb);
+ else
+ {
+ /* Must leave stmts in this BB; move following stmts here too. */
+ merge_target_bb = bb;
+ }
+ seen_exit = true;
+ continue;
+ }
/* Make stmts member of loop->header. */
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
gimple_set_bb (gsi_stmt (gsi), merge_target_bb);
/* Update stmt list. */
- last = gsi_last_bb (merge_target_bb);
- gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT);
+ gimple_stmt_iterator last = gsi_last_bb (merge_target_bb);
+
+ if (seen_exit)
+ {
+ gcc_assert (is_ctrl_stmt (gsi_stmt (last)));
+ gsi_insert_seq_before (&last, bb_seq(bb), GSI_SAME_STMT);
+ }
+ else
+ gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT);
+
set_bb_seq (bb, NULL);
- delete_basic_block (bb);
+ if (bb != loop->latch)
+ 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. */
- if (exit_bb
- && exit_bb != loop->header
- && can_merge_blocks_p (loop->header, exit_bb))
- merge_blocks (loop->header, exit_bb);
-
free (ifc_bbs);
ifc_bbs = NULL;
}