{
basic_block first_bb = NULL;
basic_block second_bb = NULL;
- tree tmp_cond;
+ tree tmp_cond, new_stmts;
gcc_assert (EDGE_COUNT (bb->preds) == 2);
first_bb = (EDGE_PRED (bb, 0))->src;
value as condition. Various targets use different means to communicate
condition in vector compare operation. Using gimple value allows compiler
to emit vector compare and select RTL without exposing compare's result. */
+ *cond = force_gimple_operand (*cond, &new_stmts, false, NULL_TREE);
+ if (new_stmts)
+ bsi_insert_before (bsi, new_stmts, BSI_SAME_STMT);
if (!is_gimple_reg (*cond) && !is_gimple_condexpr (*cond))
{
tree new_stmt;
basic_block bb, exit_bb, merge_target_bb;
unsigned int orig_loop_num_nodes = loop->num_nodes;
unsigned int i;
- unsigned int n_exits;
- edge *exits;
+ edge e;
+ edge_iterator ei;
- exits = get_loop_exit_edges (loop, &n_exits);
- free (exits);
/* Process phi nodes to prepare blocks for merge. */
process_phi_nodes (loop);
+ /* Merge basic blocks. First remove all the edges in the loop, except
+ for those from the exit block. */
exit_bb = NULL;
+ for (i = 0; i < orig_loop_num_nodes; i++)
+ {
+ bb = ifc_bbs[i];
+ if (bb_with_exit_edge_p (loop, bb))
+ {
+ exit_bb = bb;
+ break;
+ }
+ }
+ gcc_assert (exit_bb != loop->latch);
- /* Merge basic blocks */
- merge_target_bb = loop->header;
for (i = 1; i < orig_loop_num_nodes; i++)
{
- edge e;
- block_stmt_iterator bsi;
- tree_stmt_iterator last;
-
bb = ifc_bbs[i];
- if (!exit_bb && bb_with_exit_edge_p (loop, bb))
- exit_bb = bb;
-
- if (bb == exit_bb)
+ for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
{
- edge_iterator 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 with loop header. */
- make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU);
- set_immediate_dominator (CDI_DOMINATORS, bb, ifc_bbs[0]);
-
- if (exit_bb != loop->latch)
- {
- /* Redirect non-exit edge to loop->latch. */
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- if (!loop_exit_edge_p (loop, e))
- {
- redirect_edge_and_branch (e, loop->latch);
- set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
- }
- }
- }
- continue;
+ make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
}
- if (bb == loop->latch && empty_block_p (bb))
- continue;
+ /* 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 exit then reconnect header and latch. */
+ make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
+ }
- /* It is time to remove this basic block. First remove edges. */
- while (EDGE_COUNT (bb->preds) > 0)
- remove_edge (EDGE_PRED (bb, 0));
+ merge_target_bb = loop->header;
+ for (i = 1; i < orig_loop_num_nodes; i++)
+ {
+ block_stmt_iterator bsi;
+ tree_stmt_iterator last;
- /* This is loop latch and loop does not have exit then do not
- delete this basic block. Just remove its PREDS and reconnect
- loop->header and loop->latch blocks. */
- if (bb == loop->latch && n_exits == 0)
- {
- make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
- set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
- continue;
- }
+ bb = ifc_bbs[i];
- while (EDGE_COUNT (bb->succs) > 0)
- remove_edge (EDGE_SUCC (bb, 0));
+ if (bb == exit_bb || bb == loop->latch)
+ continue;
/* Remove labels and make stmts member of loop->header. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
/* Remove basic block. */
- if (bb == loop->latch)
- loop->latch = merge_target_bb;
remove_bb_from_loops (bb);
expunge_block (bb);
}
This reduces number of basic blocks to 2. Auto vectorizer addresses
loops with two nodes only. FIXME: Use cleanup_tree_cfg(). */
if (exit_bb
- && loop->header != loop->latch
- && exit_bb != loop->latch
- && empty_block_p (loop->latch))
+ && exit_bb != loop->header
+ && can_merge_blocks_p (loop->header, exit_bb))
{
- if (can_merge_blocks_p (loop->header, exit_bb))
- {
- remove_bb_from_loops (exit_bb);
- merge_blocks (loop->header, exit_bb);
- }
+ remove_bb_from_loops (exit_bb);
+ merge_blocks (loop->header, exit_bb);
}
}