+2007-04-27 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * tree-ssa-loop-im.c (determine_invariantness_stmt): Attempt to
+ transform only GIMPLE_MODIFY_STMTs.
+ * tree-complex.c (expand_complex_operations_1): Ditto.
+ (expand_complex_div_wide): Do not create gotos in COND_EXPR branches.
+ * tree-ssa-loop-manip.c (build_if_stmt): Removed.
+ (tree_transform_and_unroll_loop): Do not create gotos in COND_EXPR
+ branches.
+ * value-prof.c (tree_divmod_fixed_value, tree_mod_pow2,
+ tree_mod_subtract, tree_ic, tree_stringop_fixed_value): Ditto.
+ * omp-low.c (expand_parallel_call, expand_omp_for_generic,
+ expand_omp_for_static_chunk, expand_omp_for_static_nochunk): Ditto.
+ * tree-vectorizer.c (slpeel_make_loop_iterate_ntimes,
+ slpeel_add_loop_guard): Ditto.
+ * tree-mudflap.c (mf_build_check_statement_for): Ditto.
+ * lambda-code.c (perfect_nestify): Ditto.
+ * tree-iterator.c (tsi_split_statement_list_before): Fix splitting
+ before the first statement.
+ * tree-optimize.c (execute_free_datastructures): Fix comments.
+ (execute_free_cfg_annotations): Do not call disband_implicit_edges.
+ * tree-flow.h (disband_implicit_edges): Declaration removed.
+ * tree-cfg.c (make_cond_expr_edges): Remove gotos from COND_EXPR
+ branches.
+ (cleanup_dead_labels, tree_redirect_edge_and_branch): Handle COND_EXPRs
+ without gotos.
+ (disband_implicit_edges, has_label_p): Removed.
+ (tree_verify_flow_info): Verify that COND_EXPR branches are empty.
+ (tree_lv_add_condition_to_bb): Do not create gotos in COND_EXPR
+ branches.
+ * tree.c (build3_stat): Mark COND_EXPRs used as statements as having
+ side effects.
+ * tree-pretty-print.c (dump_implicit_edges): Dump implicit edges
+ also for COND_EXPRs.
+ * cfgexpand.c (label_rtx_for_bb): New function.
+ (expand_gimple_cond_expr): Do not expect gotos in COND_EXPR branches.
+ Use label_rtx_for_bb to find the labels.
+ (expand_gimple_basic_block): Remove RETURN_EXPR at the end of the
+ last block. Detect fallthru edges.
+
2007-04-26 Ian Lance Taylor <iant@google.com>
PR target/28675
}
}
+/* Returns the label_rtx expression for a label starting basic block BB. */
+
+static rtx
+label_rtx_for_bb (basic_block bb)
+{
+ tree_stmt_iterator tsi;
+ tree lab, lab_stmt;
+
+ if (bb->flags & BB_RTL)
+ return block_label (bb);
+
+ /* We cannot use tree_block_label, as we no longer have stmt annotations.
+ TODO -- avoid creating the new tree labels. */
+ for (tsi = tsi_start (bb_stmt_list (bb)); !tsi_end_p (tsi); tsi_next (&tsi))
+ {
+ lab_stmt = tsi_stmt (tsi);
+ if (TREE_CODE (lab_stmt) != LABEL_EXPR)
+ break;
+
+ lab = LABEL_EXPR_LABEL (lab_stmt);
+ if (DECL_NONLOCAL (lab))
+ break;
+
+ return label_rtx (lab);
+ }
+
+ lab = create_artificial_label ();
+ lab_stmt = build1 (LABEL_EXPR, void_type_node, lab);
+ tsi_link_before (&tsi, lab_stmt, TSI_NEW_STMT);
+ return label_rtx (lab);
+}
+
/* A subroutine of expand_gimple_basic_block. Expand one COND_EXPR.
Returns a new basic block if we've terminated the current basic
block and created a new one. */
edge true_edge;
edge false_edge;
tree pred = COND_EXPR_COND (stmt);
- tree then_exp = COND_EXPR_THEN (stmt);
- tree else_exp = COND_EXPR_ELSE (stmt);
rtx last2, last;
+ gcc_assert (COND_EXPR_THEN (stmt) == NULL_TREE);
+ gcc_assert (COND_EXPR_ELSE (stmt) == NULL_TREE);
last2 = last = get_last_insn ();
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
/* We can either have a pure conditional jump with one fallthru edge or
two-way jump that needs to be decomposed into two basic blocks. */
- if (TREE_CODE (then_exp) == GOTO_EXPR && IS_EMPTY_STMT (else_exp))
+ if (false_edge->dest == bb->next_bb)
{
- jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
+ jumpif (pred, label_rtx_for_bb (true_edge->dest));
add_reg_br_prob_note (last, true_edge->probability);
maybe_dump_rtl_for_tree_stmt (stmt, last);
- if (EXPR_LOCUS (then_exp))
- emit_line_note (*(EXPR_LOCUS (then_exp)));
+ if (true_edge->goto_locus)
+ emit_line_note (*true_edge->goto_locus);
+ false_edge->flags |= EDGE_FALLTHRU;
return NULL;
}
- if (TREE_CODE (else_exp) == GOTO_EXPR && IS_EMPTY_STMT (then_exp))
+ if (true_edge->dest == bb->next_bb)
{
- jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp)));
+ jumpifnot (pred, label_rtx_for_bb (false_edge->dest));
add_reg_br_prob_note (last, false_edge->probability);
maybe_dump_rtl_for_tree_stmt (stmt, last);
- if (EXPR_LOCUS (else_exp))
- emit_line_note (*(EXPR_LOCUS (else_exp)));
+ if (false_edge->goto_locus)
+ emit_line_note (*false_edge->goto_locus);
+ true_edge->flags |= EDGE_FALLTHRU;
return NULL;
}
- gcc_assert (TREE_CODE (then_exp) == GOTO_EXPR
- && TREE_CODE (else_exp) == GOTO_EXPR);
- jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
+ jumpif (pred, label_rtx_for_bb (true_edge->dest));
add_reg_br_prob_note (last, true_edge->probability);
last = get_last_insn ();
- expand_expr (else_exp, const0_rtx, VOIDmode, 0);
+ emit_jump (label_rtx_for_bb (false_edge->dest));
BB_END (bb) = last;
if (BARRIER_P (BB_END (bb)))
maybe_dump_rtl_for_tree_stmt (stmt, last2);
- if (EXPR_LOCUS (else_exp))
- emit_line_note (*(EXPR_LOCUS (else_exp)));
+ if (false_edge->goto_locus)
+ emit_line_note (*false_edge->goto_locus);
return new_bb;
}
init_rtl_bb_info (bb);
bb->flags |= BB_RTL;
+ /* Remove the RETURN_EXPR if we may fall though to the exit
+ instead. */
+ tsi = tsi_last (stmts);
+ if (!tsi_end_p (tsi)
+ && TREE_CODE (tsi_stmt (tsi)) == RETURN_EXPR)
+ {
+ tree ret_stmt = tsi_stmt (tsi);
+
+ gcc_assert (single_succ_p (bb));
+ gcc_assert (single_succ (bb) == EXIT_BLOCK_PTR);
+
+ if (bb->next_bb == EXIT_BLOCK_PTR
+ && !TREE_OPERAND (ret_stmt, 0))
+ {
+ tsi_delink (&tsi);
+ single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
+ }
+ }
+
tsi = tsi_start (stmts);
if (!tsi_end_p (tsi))
stmt = tsi_stmt (tsi);
}
}
+ /* Expand implicit goto. */
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+ }
+
+ if (e && e->dest != bb->next_bb)
+ {
+ emit_jump (label_rtx_for_bb (e->dest));
+ if (e->goto_locus)
+ emit_line_note (*e->goto_locus);
+ e->flags &= ~EDGE_FALLTHRU;
+ }
+
do_pending_stack_adjust ();
/* Find the block tail. The last insn in the block is the insn
{
basic_block *bbs;
tree exit_condition;
- tree then_label, else_label, cond_stmt;
+ tree cond_stmt;
basic_block preheaderbb, headerbb, bodybb, latchbb, olddest;
int i;
block_stmt_iterator bsi, firstbsi;
bodybb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
latchbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
make_edge (headerbb, bodybb, EDGE_FALLTHRU);
- then_label = build1 (GOTO_EXPR, void_type_node, tree_block_label (latchbb));
- else_label = build1 (GOTO_EXPR, void_type_node, tree_block_label (olddest));
cond_stmt = build3 (COND_EXPR, void_type_node,
build2 (NE_EXPR, boolean_type_node,
integer_one_node,
integer_zero_node),
- then_label, else_label);
+ NULL_TREE, NULL_TREE);
bsi = bsi_start (bodybb);
bsi_insert_after (&bsi, cond_stmt, BSI_NEW_STMT);
e = make_edge (bodybb, olddest, EDGE_FALSE_VALUE);
{
basic_block cond_bb, then_bb, else_bb;
edge e;
- tree t, then_lab, else_lab, tmp;
+ tree t, tmp;
tmp = create_tmp_var (TREE_TYPE (val), NULL);
e = split_block (bb, NULL);
then_bb = create_empty_bb (cond_bb);
else_bb = create_empty_bb (then_bb);
- then_lab = create_artificial_label ();
- else_lab = create_artificial_label ();
t = build3 (COND_EXPR, void_type_node,
- cond,
- build_and_jump (&then_lab),
- build_and_jump (&else_lab));
+ cond, NULL_TREE, NULL_TREE);
si = bsi_start (cond_bb);
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
si = bsi_start (then_bb);
- t = build1 (LABEL_EXPR, void_type_node, then_lab);
- bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
t = build_gimple_modify_stmt (tmp, val);
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
si = bsi_start (else_bb);
- t = build1 (LABEL_EXPR, void_type_node, else_lab);
- bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
t = build_gimple_modify_stmt (tmp,
build_int_cst (unsigned_type_node, 1));
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
enum built_in_function start_fn,
enum built_in_function next_fn)
{
- tree l0, l1, l2 = NULL, l3 = NULL;
tree type, istart0, iend0, iend;
tree t, list;
basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
l0_bb = create_empty_bb (entry_bb);
l1_bb = single_succ (entry_bb);
- l0 = tree_block_label (l0_bb);
- l1 = tree_block_label (l1_bb);
-
cont_bb = region->cont;
exit_bb = region->exit;
if (cont_bb)
{
l2_bb = create_empty_bb (cont_bb);
l3_bb = single_succ (cont_bb);
-
- l2 = tree_block_label (l2_bb);
- l3 = tree_block_label (l3_bb);
}
si = bsi_last (entry_bb);
t = get_formal_tmp_var (t, &list);
if (cont_bb)
{
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
- build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
}
bsi_insert_after (&si, list, BSI_SAME_STMT);
t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
- build_and_jump (&l2));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
build_fold_addr_expr (istart0),
build_fold_addr_expr (iend0));
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
- build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_start (l2_bb);
expand_omp_for_static_nochunk (struct omp_region *region,
struct omp_for_data *fd)
{
- tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
+ tree n, q, s0, e0, e, t, nthreads, threadid;
tree type, list;
basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
basic_block fin_bb;
fin_bb = single_succ (cont_bb);
exit_bb = region->exit;
- l0 = tree_block_label (seq_start_bb);
- l1 = tree_block_label (body_bb);
- l2 = tree_block_label (fin_bb);
-
/* Iteration space partitioning goes in ENTRY_BB. */
list = alloc_stmt_list ();
e0 = get_formal_tmp_var (t, &list);
t = build2 (GE_EXPR, boolean_type_node, s0, e0);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
- build_and_jump (&l0));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (entry_bb);
t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
- build_and_jump (&l2));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
static void
expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
{
- tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
+ tree n, s0, e0, e, t;
tree trip, nthreads, threadid;
tree type;
basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
fin_bb = single_succ (cont_bb);
exit_bb = region->exit;
- l0 = tree_block_label (iter_part_bb);
- l1 = tree_block_label (seq_start_bb);
- l2 = tree_block_label (body_bb);
- l3 = tree_block_label (trip_update_bb);
- l4 = tree_block_label (fin_bb);
-
/* Trip and adjustment setup goes in ENTRY_BB. */
list = alloc_stmt_list ();
e0 = get_formal_tmp_var (t, &list);
t = build2 (LT_EXPR, boolean_type_node, s0, n);
- t = build3 (COND_EXPR, void_type_node, t,
- build_and_jump (&l1), build_and_jump (&l4));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_start (iter_part_bb);
t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t,
- build_and_jump (&l2), build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
e->goto_locus = EXPR_LOCUS (COND_EXPR_ELSE (entry));
#endif
}
+
+ /* We do not need the gotos anymore. */
+ COND_EXPR_THEN (entry) = NULL_TREE;
+ COND_EXPR_ELSE (entry) = NULL_TREE;
}
true_branch = COND_EXPR_THEN (stmt);
false_branch = COND_EXPR_ELSE (stmt);
- GOTO_DESTINATION (true_branch)
- = main_block_label (GOTO_DESTINATION (true_branch));
- GOTO_DESTINATION (false_branch)
- = main_block_label (GOTO_DESTINATION (false_branch));
+ if (true_branch)
+ GOTO_DESTINATION (true_branch)
+ = main_block_label (GOTO_DESTINATION (true_branch));
+ if (false_branch)
+ GOTO_DESTINATION (false_branch)
+ = main_block_label (GOTO_DESTINATION (false_branch));
break;
}
return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t);
}
-
-/* Add gotos that used to be represented implicitly in the CFG. */
-
-void
-disband_implicit_edges (void)
-{
- basic_block bb;
- block_stmt_iterator last;
- edge e;
- edge_iterator ei;
- tree stmt, label;
-
- FOR_EACH_BB (bb)
- {
- last = bsi_last (bb);
- stmt = last_stmt (bb);
-
- if (stmt && TREE_CODE (stmt) == COND_EXPR)
- {
- /* Remove superfluous gotos from COND_EXPR branches. Moved
- from cfg_remove_useless_stmts here since it violates the
- invariants for tree--cfg correspondence and thus fits better
- here where we do it anyway. */
- e = find_edge (bb, bb->next_bb);
- if (e)
- {
- if (e->flags & EDGE_TRUE_VALUE)
- COND_EXPR_THEN (stmt) = build_empty_stmt ();
- else if (e->flags & EDGE_FALSE_VALUE)
- COND_EXPR_ELSE (stmt) = build_empty_stmt ();
- else
- gcc_unreachable ();
- e->flags |= EDGE_FALLTHRU;
- }
-
- continue;
- }
-
- if (stmt && TREE_CODE (stmt) == RETURN_EXPR)
- {
- /* Remove the RETURN_EXPR if we may fall though to the exit
- instead. */
- gcc_assert (single_succ_p (bb));
- gcc_assert (single_succ (bb) == EXIT_BLOCK_PTR);
-
- if (bb->next_bb == EXIT_BLOCK_PTR
- && !TREE_OPERAND (stmt, 0))
- {
- bsi_remove (&last, true);
- single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
- }
- continue;
- }
-
- /* There can be no fallthru edge if the last statement is a control
- one. */
- if (stmt && is_ctrl_stmt (stmt))
- continue;
-
- /* Find a fallthru edge and emit the goto if necessary. */
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (e->flags & EDGE_FALLTHRU)
- break;
-
- if (!e || e->dest == bb->next_bb)
- continue;
-
- gcc_assert (e->dest != EXIT_BLOCK_PTR);
- label = tree_block_label (e->dest);
-
- stmt = build1 (GOTO_EXPR, void_type_node, label);
-#ifdef USE_MAPPED_LOCATION
- SET_EXPR_LOCATION (stmt, e->goto_locus);
-#else
- SET_EXPR_LOCUS (stmt, e->goto_locus);
-#endif
- bsi_insert_after (&last, stmt, BSI_NEW_STMT);
- e->flags &= ~EDGE_FALLTHRU;
- }
-}
-
/* Remove block annotations and other datastructures. */
void
return new_bb;
}
-
-/* Return true when BB has label LABEL in it. */
-
-static bool
-has_label_p (basic_block bb, tree label)
-{
- block_stmt_iterator bsi;
-
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- tree stmt = bsi_stmt (bsi);
-
- if (TREE_CODE (stmt) != LABEL_EXPR)
- return false;
- if (LABEL_EXPR_LABEL (stmt) == label)
- return true;
- }
- return false;
-}
-
-
/* Callback for walk_tree, check that all elements with address taken are
properly noticed as such. The DATA is an int* that is 1 if TP was seen
inside a PHI node. */
{
edge true_edge;
edge false_edge;
- if (TREE_CODE (COND_EXPR_THEN (stmt)) != GOTO_EXPR
- || TREE_CODE (COND_EXPR_ELSE (stmt)) != GOTO_EXPR)
+
+ if (COND_EXPR_THEN (stmt) != NULL_TREE
+ || COND_EXPR_ELSE (stmt) != NULL_TREE)
{
- error ("structured COND_EXPR at the end of bb %d", bb->index);
+ error ("COND_EXPR with code in branches at the end of bb %d",
+ bb->index);
err = 1;
}
bb->index);
err = 1;
}
-
- if (!has_label_p (true_edge->dest,
- GOTO_DESTINATION (COND_EXPR_THEN (stmt))))
- {
- error ("%<then%> label does not match edge at end of bb %d",
- bb->index);
- err = 1;
- }
-
- if (!has_label_p (false_edge->dest,
- GOTO_DESTINATION (COND_EXPR_ELSE (stmt))))
- {
- error ("%<else%> label does not match edge at end of bb %d",
- bb->index);
- err = 1;
- }
}
break;
switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
{
case COND_EXPR:
- stmt = (e->flags & EDGE_TRUE_VALUE
- ? COND_EXPR_THEN (stmt)
- : COND_EXPR_ELSE (stmt));
- GOTO_DESTINATION (stmt) = label;
+ /* For COND_EXPR, we only need to redirect the edge. */
break;
case GOTO_EXPR:
SECOND_HEAD is the destination of the THEN and FIRST_HEAD is
the destination of the ELSE part. */
static void
-tree_lv_add_condition_to_bb (basic_block first_head, basic_block second_head,
- basic_block cond_bb, void *cond_e)
+tree_lv_add_condition_to_bb (basic_block first_head ATTRIBUTE_UNUSED,
+ basic_block second_head ATTRIBUTE_UNUSED,
+ basic_block cond_bb, void *cond_e)
{
block_stmt_iterator bsi;
- tree goto1 = NULL_TREE;
- tree goto2 = NULL_TREE;
tree new_cond_expr = NULL_TREE;
tree cond_expr = (tree) cond_e;
edge e0;
/* Build new conditional expr */
- goto1 = build1 (GOTO_EXPR, void_type_node, tree_block_label (first_head));
- goto2 = build1 (GOTO_EXPR, void_type_node, tree_block_label (second_head));
- new_cond_expr = build3 (COND_EXPR, void_type_node, cond_expr, goto1, goto2);
+ new_cond_expr = build3 (COND_EXPR, void_type_node, cond_expr,
+ NULL_TREE, NULL_TREE);
/* Add new cond in cond_bb. */
bsi = bsi_start (cond_bb);
bb_true = create_empty_bb (bb_cond);
bb_false = create_empty_bb (bb_true);
- t1 = build1 (GOTO_EXPR, void_type_node, tree_block_label (bb_true));
- t2 = build1 (GOTO_EXPR, void_type_node, tree_block_label (bb_false));
- COND_EXPR_THEN (cond) = t1;
- COND_EXPR_ELSE (cond) = t2;
-
/* Wire the blocks together. */
e->flags = EDGE_TRUE_VALUE;
redirect_edge_succ (e, bb_true);
default:
{
- tree lhs = GENERIC_TREE_OPERAND (stmt, 0);
- tree rhs = GENERIC_TREE_OPERAND (stmt, 1);
+ tree lhs, rhs;
+
+ /* COND_EXPR may also fallthru here, but we do not need to do anything
+ with it. */
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+ return;
+
+ lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
if (TREE_CODE (type) == COMPLEX_TYPE)
expand_complex_move (bsi, stmt, type, lhs, rhs);
#define PENDING_STMT(e) ((e)->insns.t)
extern void delete_tree_cfg_annotations (void);
-extern void disband_implicit_edges (void);
extern bool stmt_ends_bb_p (tree);
extern bool is_ctrl_stmt (tree);
extern bool is_ctrl_altering_stmt (tree);
cur->prev = NULL;
if (prev)
prev->next = NULL;
+ else
+ STATEMENT_LIST_HEAD (old_sl) = NULL;
return new_sl;
}
/* Build the conditional jump. 'cond' is just a temporary so we can
simply build a void COND_EXPR. We do need labels in both arms though. */
- t = build3 (COND_EXPR, void_type_node, cond,
- build1 (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
- build1 (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
+ t = build3 (COND_EXPR, void_type_node, cond, NULL_TREE, NULL_TREE);
SET_EXPR_LOCUS (t, locus);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
*instr_bsi = bsi_start (join_bb);
- bsi_next (instr_bsi);
}
static unsigned int
execute_free_datastructures (void)
{
- /* ??? This isn't the right place for this. Worse, it got computed
- more or less at random in various passes. */
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
- /* Remove the ssa structures. Do it here since this includes statement
- annotations that need to be intact during disband_implicit_edges. */
+ /* Remove the ssa structures. */
if (cfun->gimple_df)
delete_tree_ssa ();
return 0;
static unsigned int
execute_free_cfg_annotations (void)
{
- /* Emit gotos for implicit jumps. */
- disband_implicit_edges ();
-
/* And get rid of annotations we no longer need. */
delete_tree_cfg_annotations ();
{
edge e;
edge_iterator ei;
+ tree stmt;
+
+ stmt = last_stmt (bb);
+ if (stmt && TREE_CODE (stmt) == COND_EXPR)
+ {
+ edge true_edge, false_edge;
+
+ /* When we are emitting the code or changing CFG, it is possible that
+ the edges are not yet created. When we are using debug_bb in such
+ a situation, we do not want it to crash. */
+ if (EDGE_COUNT (bb->succs) != 2)
+ return;
+ extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
+
+ INDENT (indent + 2);
+ pp_cfg_jump (buffer, true_edge->dest);
+ newline_and_indent (buffer, indent);
+ pp_string (buffer, "else");
+ newline_and_indent (buffer, indent + 2);
+ pp_cfg_jump (buffer, false_edge->dest);
+ pp_newline (buffer);
+ return;
+ }
/* If there is a fallthru edge, we may need to add an artificial goto to the
dump. */
continue;
}
- rhs = GENERIC_TREE_OPERAND (stmt, 1);
-
- /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal
- to be hoisted out of loop, saving expensive divide. */
- if (pos == MOVE_POSSIBLE
- && TREE_CODE (rhs) == RDIV_EXPR
- && flag_unsafe_math_optimizations
- && !flag_trapping_math
- && outermost_invariant_loop_expr (TREE_OPERAND (rhs, 1),
- loop_containing_stmt (stmt)) != NULL
- && outermost_invariant_loop_expr (rhs,
- loop_containing_stmt (stmt)) == NULL)
- stmt = rewrite_reciprocal (&bsi);
-
- /* If the shift count is invariant, convert (A >> B) & 1 to
- A & (1 << B) allowing the bit mask to be hoisted out of the loop
- saving an expensive shift. */
- if (pos == MOVE_POSSIBLE
- && TREE_CODE (rhs) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (rhs, 1))
- && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
- && has_single_use (TREE_OPERAND (rhs, 0)))
- stmt = rewrite_bittest (&bsi);
+ if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+ {
+ rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+
+ /* If divisor is invariant, convert a/b to a*(1/b), allowing reciprocal
+ to be hoisted out of loop, saving expensive divide. */
+ if (pos == MOVE_POSSIBLE
+ && TREE_CODE (rhs) == RDIV_EXPR
+ && flag_unsafe_math_optimizations
+ && !flag_trapping_math
+ && outermost_invariant_loop_expr (TREE_OPERAND (rhs, 1),
+ loop_containing_stmt (stmt)) != NULL
+ && outermost_invariant_loop_expr (rhs,
+ loop_containing_stmt (stmt)) == NULL)
+ stmt = rewrite_reciprocal (&bsi);
+
+ /* If the shift count is invariant, convert (A >> B) & 1 to
+ A & (1 << B) allowing the bit mask to be hoisted out of the loop
+ saving an expensive shift. */
+ if (pos == MOVE_POSSIBLE
+ && TREE_CODE (rhs) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (rhs, 1))
+ && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
+ && has_single_use (TREE_OPERAND (rhs, 0)))
+ stmt = rewrite_bittest (&bsi);
+ }
stmt_ann (stmt)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
LIM_DATA (stmt)->always_executed_in = outermost;
return true;
}
-/* Build if (COND) goto THEN_LABEL; else goto ELSE_LABEL; */
-
-static tree
-build_if_stmt (tree cond, tree then_label, tree else_label)
-{
- return build3 (COND_EXPR, void_type_node,
- cond,
- build1 (GOTO_EXPR, void_type_node, then_label),
- build1 (GOTO_EXPR, void_type_node, else_label));
-}
-
/* Returns true if we can unroll LOOP FACTOR times. Number
of iterations of the loop is returned in NITER. */
REG_BR_PROB_BASE - exit->probability);
bsi = bsi_last (exit_bb);
- exit_if = build_if_stmt (boolean_true_node,
- tree_block_label (loop->latch),
- tree_block_label (rest));
+ exit_if = build3 (COND_EXPR, void_type_node, boolean_true_node,
+ NULL_TREE, NULL_TREE);
+
bsi_insert_after (&bsi, exit_if, BSI_NEW_STMT);
new_exit = make_edge (exit_bb, rest, EDGE_FALSE_VALUE | irr);
rescan_loop_exit (new_exit, true, false);
block_stmt_iterator loop_cond_bsi;
block_stmt_iterator incr_bsi;
bool insert_after;
- tree begin_label = tree_block_label (loop->latch);
- tree exit_label = tree_block_label (single_exit (loop)->dest);
tree init = build_int_cst (TREE_TYPE (niters), 0);
tree step = build_int_cst (TREE_TYPE (niters), 1);
- tree then_label;
- tree else_label;
LOC loop_loc;
orig_cond = get_loop_exit_condition (loop);
&incr_bsi, insert_after, &indx_before_incr, &indx_after_incr);
if (exit_edge->flags & EDGE_TRUE_VALUE) /* 'then' edge exits the loop. */
- {
- cond = build2 (GE_EXPR, boolean_type_node, indx_after_incr, niters);
- then_label = build1 (GOTO_EXPR, void_type_node, exit_label);
- else_label = build1 (GOTO_EXPR, void_type_node, begin_label);
- }
+ cond = build2 (GE_EXPR, boolean_type_node, indx_after_incr, niters);
else /* 'then' edge loops back. */
- {
- cond = build2 (LT_EXPR, boolean_type_node, indx_after_incr, niters);
- then_label = build1 (GOTO_EXPR, void_type_node, begin_label);
- else_label = build1 (GOTO_EXPR, void_type_node, exit_label);
- }
+ cond = build2 (LT_EXPR, boolean_type_node, indx_after_incr, niters);
cond_stmt = build3 (COND_EXPR, TREE_TYPE (orig_cond), cond,
- then_label, else_label);
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&loop_cond_bsi, cond_stmt, BSI_SAME_STMT);
/* Remove old loop exit test: */
{
block_stmt_iterator bsi;
edge new_e, enter_e;
- tree cond_stmt, then_label, else_label;
+ tree cond_stmt;
enter_e = EDGE_SUCC (guard_bb, 0);
enter_e->flags &= ~EDGE_FALLTHRU;
enter_e->flags |= EDGE_FALSE_VALUE;
bsi = bsi_last (guard_bb);
- then_label = build1 (GOTO_EXPR, void_type_node,
- tree_block_label (exit_bb));
- else_label = build1 (GOTO_EXPR, void_type_node,
- tree_block_label (enter_e->dest));
cond_stmt = build3 (COND_EXPR, void_type_node, cond,
- then_label, else_label);
+ NULL_TREE, NULL_TREE);
bsi_insert_after (&bsi, cond_stmt, BSI_NEW_STMT);
/* Add new edge to connect guard block to the merge/loop-exit block. */
new_e = make_edge (guard_bb, exit_bb, EDGE_TRUE_VALUE);
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
- side_effects = TREE_SIDE_EFFECTS (t);
+ /* As a special exception, if COND_EXPR has NULL branches, we
+ assume that it is a gimple statement and always consider
+ it to have side effects. */
+ if (code == COND_EXPR
+ && tt == void_type_node
+ && arg1 == NULL_TREE
+ && arg2 == NULL_TREE)
+ side_effects = true;
+ else
+ side_effects = TREE_SIDE_EFFECTS (t);
PROCESS_ARG(0);
PROCESS_ARG(1);
stmt2 = build_gimple_modify_stmt (tmp1, op2);
stmt3 = build3 (COND_EXPR, void_type_node,
build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
- build1 (GOTO_EXPR, void_type_node, label_decl2),
- build1 (GOTO_EXPR, void_type_node, label_decl1));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
stmt4 = build3 (COND_EXPR, void_type_node,
build2 (NE_EXPR, boolean_type_node,
tmp3, build_int_cst (optype, 0)),
- build1 (GOTO_EXPR, void_type_node, label_decl2),
- build1 (GOTO_EXPR, void_type_node, label_decl1));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
stmt2 = build_gimple_modify_stmt (tmp1, op2);
stmt3 = build3 (COND_EXPR, void_type_node,
build2 (LT_EXPR, boolean_type_node, result, tmp1),
- build1 (GOTO_EXPR, void_type_node, label_decl3),
- build1 (GOTO_EXPR, void_type_node,
- ncounts ? label_decl1 : label_decl2));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
result, tmp1));
stmt2 = build3 (COND_EXPR, void_type_node,
build2 (LT_EXPR, boolean_type_node, result, tmp1),
- build1 (GOTO_EXPR, void_type_node, label_decl3),
- build1 (GOTO_EXPR, void_type_node, label_decl2));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
stmt2 = build_gimple_modify_stmt (tmp1, tmp);
stmt3 = build3 (COND_EXPR, void_type_node,
build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
- build1 (GOTO_EXPR, void_type_node, label_decl2),
- build1 (GOTO_EXPR, void_type_node, label_decl1));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
stmt2 = build_gimple_modify_stmt (tmp1, blck_size);
stmt3 = build3 (COND_EXPR, void_type_node,
build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
- build1 (GOTO_EXPR, void_type_node, label_decl2),
- build1 (GOTO_EXPR, void_type_node, label_decl1));
+ NULL_TREE, NULL_TREE);
bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);