static bool if_convertable_bb_p (struct loop *, basic_block, bool);
static bool if_convertable_loop_p (struct loop *, bool);
static void add_to_predicate_list (basic_block, tree);
-static tree add_to_dst_predicate_list (struct loop * loop, tree, tree, tree,
+static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree,
block_stmt_iterator *);
static void clean_predicate_lists (struct loop *loop);
static basic_block find_phi_replacement_condition (basic_block, tree *,
for vectorizer or not. If it is used for vectorizer, additional checks are
used. (Vectorization checks are not yet implemented). */
-bool
+static bool
tree_if_conversion (struct loop *loop, bool for_vectorizer)
{
basic_block bb;
tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
block_stmt_iterator *bsi)
{
- tree then_clause, else_clause, c, new_cond;
+ tree c, c2, new_cond;
+ edge true_edge, false_edge;
new_cond = NULL_TREE;
gcc_assert (TREE_CODE (stmt) == COND_EXPR);
- c = TREE_OPERAND (stmt, 0);
- then_clause = TREE_OPERAND (stmt, 1);
- else_clause = TREE_OPERAND (stmt, 2);
+ c = COND_EXPR_COND (stmt);
/* Create temp. for condition. */
if (!is_gimple_condexpr (c))
c = TREE_OPERAND (new_stmt, 0);
}
+ extract_true_false_edges_from_block (bb_for_stmt (stmt),
+ &true_edge, &false_edge);
+
/* Add new condition into destination's predicate list. */
- if (then_clause)
- /* if 'c' is true then then_clause is reached. */
- new_cond = add_to_dst_predicate_list (loop, then_clause, cond,
- unshare_expr (c), bsi);
- if (else_clause)
- {
- tree c2;
- if (!is_gimple_reg(c) && is_gimple_condexpr (c))
- {
- tree new_stmt;
- new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c));
- bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
- c = TREE_OPERAND (new_stmt, 0);
- }
+ /* If 'c' is true then TRUE_EDGE is taken. */
+ new_cond = add_to_dst_predicate_list (loop, true_edge->dest, cond,
+ unshare_expr (c), bsi);
- /* if 'c' is false then else_clause is reached. */
- c2 = invert_truthvalue (unshare_expr (c));
- add_to_dst_predicate_list (loop, else_clause, cond, c2, bsi);
+ if (!is_gimple_reg(c) && is_gimple_condexpr (c))
+ {
+ tree new_stmt;
+ new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c));
+ bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
+ c = TREE_OPERAND (new_stmt, 0);
}
+ /* If 'c' is false then FALSE_EDGE is taken. */
+ c2 = invert_truthvalue (unshare_expr (c));
+ add_to_dst_predicate_list (loop, false_edge->dest, cond, c2, bsi);
+
/* Now this conditional statement is redundant. Remove it.
But, do not remove exit condition! Update exit condition
using new condition. */
/* ??? Check data dependency for vectorizer. */
/* What about phi nodes ? */
- for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
if (!if_convertable_phi_p (loop, bb, phi))
return false;
bb->aux = cond;
}
-/* Add condition COND into DST's predicate list. PREV_COND is
+/* Add condition COND into BB's predicate list. PREV_COND is
existing condition. */
static tree
-add_to_dst_predicate_list (struct loop * loop, tree dst,
+add_to_dst_predicate_list (struct loop * loop, basic_block bb,
tree prev_cond, tree cond,
block_stmt_iterator *bsi)
{
- basic_block bb;
tree new_cond = NULL_TREE;
- gcc_assert (TREE_CODE (dst) == GOTO_EXPR);
- bb = label_to_block (TREE_OPERAND (dst, 0));
if (!flow_bb_inside_loop_p (loop, bb))
return NULL_TREE;
static void
clean_predicate_lists (struct loop *loop)
{
- unsigned int i;
-
- for (i = 0; i < loop->num_nodes; i++)
- ifc_bbs[i]->aux = NULL;
+#ifdef ENABLE_CHECKING
+ gcc_assert (loop->num_nodes == 2 || loop->num_nodes == 1);
+#endif
+ loop->header->aux = NULL;
+ loop->latch->aux = NULL;
}
/* Basic block BB has two predecessors. Using predecessor's aux field, set
basic_block true_bb = NULL;
bb = ifc_bbs[i];
- if (bb == loop->header || bb == loop->latch)
+ if (bb == loop->header)
continue;
phi = phi_nodes (bb);
while (phi)
{
- tree next = TREE_CHAIN (phi);
+ tree next = PHI_CHAIN (phi);
replace_phi_with_cond_modify_expr (phi, cond, true_bb, &bsi);
release_phi_node (phi);
phi = next;
bb = ifc_bbs[i];
- if (bb == loop->latch)
- continue;
-
if (!exit_bb && bb_with_exit_edge_p (bb))
exit_bb = bb;
continue;
}
+ if (bb == loop->latch && empty_block_p (bb))
+ continue;
+
/* It is time to remove this basic block. First remove edges. */
while (EDGE_COUNT (bb->succs) > 0)
ssa_remove_edge (EDGE_SUCC (bb, 0));
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);
}
/* Now if possible, merge loop header and block with exit edge.
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->latch && empty_block_p (loop->latch))
+ if (exit_bb
+ && loop->header != loop->latch
+ && exit_bb != loop->latch
+ && empty_block_p (loop->latch))
{
if (can_merge_blocks_p (loop->header, exit_bb))
{