tree-ssa-loop-im.c (determine_invariantness_stmt): Attempt to transform only GIMPLE_MODIFY_STMTs.

* 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.

From-SVN: r124214
This commit is contained in:
Zdenek Dvorak 2007-04-27 10:20:39 +02:00 committed by Zdenek Dvorak
parent f5c3dc96c3
commit a9b77cd1f7
16 changed files with 240 additions and 288 deletions

View File

@ -1,3 +1,43 @@
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

View File

@ -1244,6 +1244,38 @@ maybe_dump_rtl_for_tree_stmt (tree stmt, rtx since)
}
}
/* 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. */
@ -1256,10 +1288,10 @@ expand_gimple_cond_expr (basic_block bb, tree stmt)
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);
@ -1275,31 +1307,31 @@ expand_gimple_cond_expr (basic_block bb, tree stmt)
/* 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)))
@ -1321,8 +1353,8 @@ expand_gimple_cond_expr (basic_block bb, tree stmt)
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;
}
@ -1457,6 +1489,25 @@ expand_gimple_basic_block (basic_block 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);
@ -1546,6 +1597,21 @@ expand_gimple_basic_block (basic_block bb)
}
}
/* 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

View File

@ -2450,7 +2450,7 @@ perfect_nestify (struct loop *loop,
{
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;
@ -2498,13 +2498,11 @@ perfect_nestify (struct loop *loop,
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);

View File

@ -2203,7 +2203,7 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
{
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);
@ -2213,26 +2213,18 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
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);
@ -2579,7 +2571,6 @@ expand_omp_for_generic (struct omp_region *region,
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;
@ -2601,18 +2592,12 @@ expand_omp_for_generic (struct omp_region *region,
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);
@ -2640,8 +2625,7 @@ expand_omp_for_generic (struct omp_region *region,
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);
@ -2682,8 +2666,7 @@ expand_omp_for_generic (struct omp_region *region,
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);
@ -2698,8 +2681,7 @@ expand_omp_for_generic (struct omp_region *region,
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);
@ -2768,7 +2750,7 @@ static void
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;
@ -2783,10 +2765,6 @@ expand_omp_for_static_nochunk (struct omp_region *region,
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 ();
@ -2837,8 +2815,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
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);
@ -2872,8 +2849,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
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);
@ -2937,7 +2913,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
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;
@ -2956,12 +2932,6 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
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 ();
@ -3021,8 +2991,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
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);
@ -3055,8 +3024,7 @@ expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
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);

View File

@ -615,6 +615,10 @@ make_cond_expr_edges (basic_block 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;
}
@ -928,10 +932,12 @@ cleanup_dead_labels (void)
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;
}
@ -2522,87 +2528,6 @@ stmt_ends_bb_p (tree t)
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
@ -3136,27 +3061,6 @@ tree_split_edge (edge edge_in)
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. */
@ -3789,10 +3693,12 @@ tree_verify_flow_info (void)
{
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;
}
@ -3809,22 +3715,6 @@ tree_verify_flow_info (void)
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;
@ -4103,10 +3993,7 @@ tree_redirect_edge_and_branch (edge e, basic_block dest)
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:
@ -5676,20 +5563,18 @@ tree_lv_adjust_loop_header_phi (basic_block first, basic_block second,
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);

View File

@ -1060,11 +1060,6 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
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);
@ -1377,8 +1372,15 @@ expand_complex_operations_1 (block_stmt_iterator *bsi)
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);

View File

@ -722,7 +722,6 @@ extern void free_omp_regions (void);
#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);

View File

@ -291,6 +291,8 @@ tsi_split_statement_list_before (tree_stmt_iterator *i)
cur->prev = NULL;
if (prev)
prev->next = NULL;
else
STATEMENT_LIST_HEAD (old_sl) = NULL;
return new_sl;
}

View File

@ -630,9 +630,7 @@ mf_build_check_statement_for (tree base, tree limit,
/* 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);
@ -685,7 +683,6 @@ mf_build_check_statement_for (tree base, tree limit,
bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
*instr_bsi = bsi_start (join_bb);
bsi_next (instr_bsi);
}

View File

@ -208,13 +208,10 @@ struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
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;
@ -241,9 +238,6 @@ struct tree_opt_pass pass_free_datastructures =
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 ();

View File

@ -2958,6 +2958,29 @@ dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
{
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. */

View File

@ -731,29 +731,32 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
continue;
}
rhs = GENERIC_TREE_OPERAND (stmt, 1);
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 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 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;

View File

@ -604,17 +604,6 @@ tree_duplicate_loop_to_header_edge (struct loop *loop, edge e,
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. */
@ -932,9 +921,9 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
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);

View File

@ -767,12 +767,8 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
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);
@ -784,20 +780,12 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
&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: */
@ -935,19 +923,15 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb,
{
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);

View File

@ -3128,7 +3128,16 @@ build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
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);

View File

@ -527,8 +527,7 @@ tree_divmod_fixed_value (tree stmt, tree operation,
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);
@ -689,8 +688,7 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
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);
@ -845,9 +843,7 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
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);
@ -861,8 +857,7 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
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);
@ -1084,8 +1079,7 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
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);
@ -1288,8 +1282,7 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
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);