From ca9fef16af6d5678e16a3165f7d54ad3fa26c58b Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 25 Jul 2001 01:42:40 +0200 Subject: [PATCH] flow.c (try_simplify_condjump): Avoid duplicated edges. * flow.c (try_simplify_condjump): Avoid duplicated edges. (verify_flow_info): Check for duplicated edges; clarify error reporting. * flow.c (block_label): Update basic_block_for_insn. (commit_edge_insertions): Call compute_bb_for_insn. * flow.c (purge_dead_edges): Handle conditional jumps and conditional returns too. * flow.c (redirect_edge_and_branch, try_optimize_cfg): Use redirect_edge_succ_nodup (redirect_edge_succ_nodup): New. * basic_block.h (redirect_edge_succ_nodup): Declare. * toplev.c (rest_of_compilation): Rebuild CFG before cfg_cleanup after gcse. From-SVN: r44320 --- gcc/ChangeLog | 20 ++++++++ gcc/basic-block.h | 1 + gcc/flow.c | 124 ++++++++++++++++++++++++++++++++++------------ gcc/toplev.c | 2 + 4 files changed, 114 insertions(+), 33 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 30db51bd0d3..010e14cddef 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Wed Jul 25 01:41:27 CEST 2001 Jan Hubicka + + * flow.c (try_simplify_condjump): Avoid duplicated edges. + (verify_flow_info): Check for duplicated edges; clarify + error reporting. + + * flow.c (block_label): Update basic_block_for_insn. + (commit_edge_insertions): Call compute_bb_for_insn. + + * flow.c (purge_dead_edges): Handle conditional jumps and conditional + returns too. + + * flow.c (redirect_edge_and_branch, + try_optimize_cfg): Use redirect_edge_succ_nodup + (redirect_edge_succ_nodup): New. + * basic_block.h (redirect_edge_succ_nodup): Declare. + + * toplev.c (rest_of_compilation): Rebuild CFG before cfg_cleanup + after gcse. + Wed Jul 25 00:32:49 CEST 2001 Jan Hubicka * flow.c (try_forward_edges): Accept fallthru edge; Update comment. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index b6e8c11a16b..c069ad57edd 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -296,6 +296,7 @@ extern void make_edge PARAMS ((sbitmap *, basic_block, basic_block, int)); extern void remove_edge PARAMS ((edge)); extern void redirect_edge_succ PARAMS ((edge, basic_block)); +extern void redirect_edge_succ_nodup PARAMS ((edge, basic_block)); extern void redirect_edge_pred PARAMS ((edge, basic_block)); extern void create_basic_block PARAMS ((int, rtx, rtx, rtx)); extern int flow_delete_block PARAMS ((basic_block)); diff --git a/gcc/flow.c b/gcc/flow.c index ac1ea5ccee3..733eae047bc 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -1592,7 +1592,11 @@ block_label (block) if (block == EXIT_BLOCK_PTR) return NULL_RTX; if (GET_CODE (block->head) != CODE_LABEL) - block->head = emit_label_before (gen_label_rtx (), block->head); + { + block->head = emit_label_before (gen_label_rtx (), block->head); + if (basic_block_for_insn) + set_block_for_insn (block->head, block); + } return block->head; } @@ -1834,22 +1838,7 @@ redirect_edge_and_branch (e, target) fprintf (rtl_dump_file, "Edge %i->%i redirected to %i\n", e->src->index, e->dest->index, target->index); if (e->dest != target) - { - edge s; - /* Check whether the edge is already present. */ - for (s = src->succ; s; s=s->succ_next) - if (s->dest == target) - break; - if (s) - { - s->flags |= e->flags; - s->probability += e->probability; - s->count += e->count; - remove_edge (e); - } - else - redirect_edge_succ (e, target); - } + redirect_edge_succ_nodup (e, target); return true; } @@ -2293,6 +2282,7 @@ commit_edge_insertions () { int i; basic_block bb; + compute_bb_for_insn (get_max_uid ()); #ifdef ENABLE_CHECKING verify_flow_info (); @@ -3076,8 +3066,8 @@ try_simplify_condjump (cbranch_block) /* Success. Update the CFG to match. Note that after this point the edge variable names appear backwards; the redirection is done this way to preserve edge profile data. */ - redirect_edge_succ (cbranch_jump_edge, cbranch_dest_block); - redirect_edge_succ (cbranch_fallthru_edge, jump_dest_block); + redirect_edge_succ_nodup (cbranch_jump_edge, cbranch_dest_block); + redirect_edge_succ_nodup (cbranch_fallthru_edge, jump_dest_block); cbranch_jump_edge->flags |= EDGE_FALLTHRU; cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU; @@ -3820,7 +3810,7 @@ try_optimize_cfg (mode) fprintf (rtl_dump_file, "Deleting fallthru block %i.\n", b->index); c = BASIC_BLOCK (b->index ? b->index - 1 : 1); - redirect_edge_succ (b->pred, b->succ->dest); + redirect_edge_succ_nodup (b->pred, b->succ->dest); flow_delete_block (b); changed = true; b = c; @@ -7979,11 +7969,13 @@ verify_flow_info () const int max_uid = get_max_uid (); const rtx rtx_first = get_insns (); rtx last_head = get_last_insn (); - basic_block *bb_info; + basic_block *bb_info, *last_visited; rtx x; int i, last_bb_num_seen, num_bb_notes, err = 0; bb_info = (basic_block *) xcalloc (max_uid, sizeof (basic_block)); + last_visited = (basic_block *) xcalloc (n_basic_blocks + 2, + sizeof (basic_block)); for (i = n_basic_blocks - 1; i >= 0; i--) { @@ -8040,6 +8032,14 @@ verify_flow_info () e = bb->succ; while (e) { + if (last_visited [e->dest->index + 2] == bb) + { + error ("verify_flow_info: Duplicate edge %i->%i", + e->src->index, e->dest->index); + err = 1; + } + last_visited [e->dest->index + 2] = bb; + if ((e->flags & EDGE_FALLTHRU) && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR @@ -8166,8 +8166,7 @@ verify_flow_info () basic_block bb = NOTE_BASIC_BLOCK (x); num_bb_notes++; if (bb->index != last_bb_num_seen + 1) - /* Basic blocks not numbered consecutively. */ - abort (); + internal_error ("Basic blocks not numbered consecutively."); last_bb_num_seen = bb->index; } @@ -8213,10 +8212,11 @@ verify_flow_info () num_bb_notes, n_basic_blocks); if (err) - abort (); + internal_error ("verify_flow_info failed."); /* Clean up. */ free (bb_info); + free (last_visited); } /* Functions to access an edge list with a vector representation. @@ -8629,6 +8629,29 @@ redirect_edge_succ (e, new_succ) e->dest = new_succ; } +/* Like previous but avoid possible dupplicate edge. */ + +void +redirect_edge_succ_nodup (e, new_succ) + edge e; + basic_block new_succ; +{ + edge s; + /* Check whether the edge is already present. */ + for (s = e->src->succ; s; s = s->succ_next) + if (s->dest == new_succ && s != e) + break; + if (s) + { + s->flags |= e->flags; + s->probability += e->probability; + s->count += e->count; + remove_edge (e); + } + else + redirect_edge_succ (e, new_succ); +} + /* Redirect an edge's predecessor from one block to another. */ void @@ -9794,21 +9817,56 @@ purge_dead_edges (bb) return; if (GET_CODE (insn) == JUMP_INSN) { + int removed = 0; + rtx note; + edge b,f; + /* We do care only about conditional jumps and simplejumps. */ + if (!any_condjump_p (insn) + && !returnjump_p (insn) + && !simplejump_p (insn)) + return; for (e = bb->succ; e; e = next) { next = e->succ_next; - if (e->dest == EXIT_BLOCK_PTR || e->dest->head != JUMP_LABEL (insn)) - remove_edge (e); - } - if (bb->succ && bb->succ->succ_next) - abort (); - if (!bb->succ) - return; - bb->succ->probability = REG_BR_PROB_BASE; - bb->succ->count = bb->count; + /* Check purposes we can have edge. */ + if ((e->flags & EDGE_FALLTHRU) + && any_condjump_p (insn)) + continue; + if (e->dest != EXIT_BLOCK_PTR + && e->dest->head == JUMP_LABEL (insn)) + continue; + if (e->dest == EXIT_BLOCK_PTR + && returnjump_p (insn)) + continue; + removed = 1; + remove_edge (e); + } + if (!bb->succ || !removed) + return; if (rtl_dump_file) fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index); + if (!optimize) + return; + + /* Redistribute probabilities. */ + if (!bb->succ->succ_next) + { + bb->succ->probability = REG_BR_PROB_BASE; + bb->succ->count = bb->count; + } + else + { + note = find_reg_note (insn, REG_BR_PROB, NULL); + if (!note) + return; + b = BRANCH_EDGE (bb); + f = FALLTHRU_EDGE (bb); + b->probability = INTVAL (XEXP (note, 0)); + f->probability = REG_BR_PROB_BASE - b->probability; + b->count = bb->count * b->probability / REG_BR_PROB_BASE; + f->count = bb->count * f->probability / REG_BR_PROB_BASE; + } return; } /* If we don't see a jump insn, we don't know exactly why the block would diff --git a/gcc/toplev.c b/gcc/toplev.c index a7bd5e36daf..02bb24ab6a7 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3060,6 +3060,8 @@ rest_of_compilation (decl) tem = tem2 = 0; timevar_push (TV_JUMP); rebuild_jump_labels (insns); + delete_trivially_dead_insns (insns, max_reg_num (), 0); + find_basic_blocks (insns, max_reg_num (), rtl_dump_file); cleanup_cfg (CLEANUP_EXPENSIVE); timevar_pop (TV_JUMP);