diff options
author | Zdenek Dvorak <dvorakz@suse.cz> | 2007-04-27 10:20:39 +0200 |
---|---|---|
committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2007-04-27 08:20:39 +0000 |
commit | a9b77cd1f72118dead00c720f1fc3348b7c5127e (patch) | |
tree | 27999109f6865e3cf09cab56d6dcff63b98e5594 | |
parent | f5c3dc96c341e300248c37f76067b5a02d61bffb (diff) | |
download | gcc-a9b77cd1f72118dead00c720f1fc3348b7c5127e.tar.gz |
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
-rw-r--r-- | gcc/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/cfgexpand.c | 98 | ||||
-rw-r--r-- | gcc/lambda-code.c | 6 | ||||
-rw-r--r-- | gcc/omp-low.c | 54 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 157 | ||||
-rw-r--r-- | gcc/tree-complex.c | 16 | ||||
-rw-r--r-- | gcc/tree-flow.h | 1 | ||||
-rw-r--r-- | gcc/tree-iterator.c | 2 | ||||
-rw-r--r-- | gcc/tree-mudflap.c | 5 | ||||
-rw-r--r-- | gcc/tree-optimize.c | 8 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 23 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-im.c | 49 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-manip.c | 17 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 26 | ||||
-rw-r--r-- | gcc/tree.c | 11 | ||||
-rw-r--r-- | gcc/value-prof.c | 19 |
16 files changed, 242 insertions, 290 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 526c390d4c1..447dc85588b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index ab2b9d36af2..643ff207108 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -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 diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c index 487c6468de7..ca07bdc2f04 100644 --- a/gcc/lambda-code.c +++ b/gcc/lambda-code.c @@ -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); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ef29e96c271..234c860418f 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 878ba6fa808..59e1cc3b7ab 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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); diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 3f479edad03..71ebeacc408 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -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); diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index b7f6585b907..d308299897f 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -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); diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c index 77e2345e4c2..ac033ae5c39 100644 --- a/gcc/tree-iterator.c +++ b/gcc/tree-iterator.c @@ -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; } diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c index 698114e5dce..72e53e6bdaa 100644 --- a/gcc/tree-mudflap.c +++ b/gcc/tree-mudflap.c @@ -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); } diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index e122f48e540..c9f24cb336d 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -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 (); diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 32f8ac00d37..09d203fa29b 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 1e36fae96bd..c5578cfc9e3 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -731,29 +731,32 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED, 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; diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index 30f853469fc..7611a6f2a5d 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -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); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 3c41c5c4ee4..d235a4917ba 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -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); diff --git a/gcc/tree.c b/gcc/tree.c index 0ea18b2f700..1f2e91919e8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 24a21717278..e015855e8ac 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -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); |