diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7b9891e3f06..266154bcdc7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +Tue Sep 11 11:37:52 CEST 2001 Jan Hubicka + + * basic-block.h (cached_make_edge, make_single_succ): New. + (make_edge): Remove first parameter. + * bb-reroder.c (fixup_reorder_chain): Use make_single_succ_edge. + * cfg.c (cached_make_edge): Rename from make_edge; return newly + created edge; use obstack allocation. + (make_edge, make_single_succ_edge): New. + (first_removed_edge): New static variable. + (init_flow): Initialize first_removed_edge and n_edges. + (clear_edges): Use remove_edge. + (flow_delete_block): Likewise. + (remove_edge): Add removed edges to the removed edges list. + (split_block, redirect_edge_and_branch_force, split_edge): + Use make_edge. + * cfganal.c (flow_call_edges_add): Updaet make_edge call. + (add_noreturn_fake_exit_edges): Likewise. + (connect_infinite_loops_to_exit): Liekwise. + * cfgbuild.c (make_label_edge, make_edges, find_sub_basic_blocks): + Use cached_make_edge. + * cfgcleanup.c (try_crossjump_to_edge): Use make_single_succ_edge. + * profile.c (branch_prob): Update make_edge call. + * ssa-dce.c (ssa_eliminate_dead_code): Likewise. + 2001-09-11 Richard Henderson * config/alpha/alpha.c: Tidy formatting. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 13241e8ffe6..1a49c5f1a7d 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -305,7 +305,11 @@ extern void connect_infinite_loops_to_exit PARAMS ((void)); extern int flow_call_edges_add PARAMS ((sbitmap)); extern rtx flow_delete_insn PARAMS ((rtx)); extern void flow_delete_insn_chain PARAMS ((rtx, rtx)); -extern void make_edge PARAMS ((sbitmap *, basic_block, +extern edge cached_make_edge PARAMS ((sbitmap *, basic_block, + basic_block, int)); +extern edge make_edge PARAMS ((basic_block, + basic_block, int)); +extern edge make_single_succ_edge PARAMS ((basic_block, basic_block, int)); extern void remove_edge PARAMS ((edge)); extern void redirect_edge_succ PARAMS ((edge, basic_block)); diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 3102132eb3e..c048ac872ab 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -737,10 +737,8 @@ fixup_reorder_chain () RBI (bb)->next = nb; /* Link to new block. */ - make_edge (NULL, nb, e_fall->dest, 0); + make_single_succ_edge (nb, e_fall->dest, 0); redirect_edge_succ (e_fall, nb); - nb->succ->count = e_fall->count; - nb->succ->probability = REG_BR_PROB_BASE; /* Don't process this new block. */ bb = nb; diff --git a/gcc/cfg.c b/gcc/cfg.c index 3f11a55982f..ff7e1bf7a14 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -34,7 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA compute_bb_for_insn, update_bb_for_insn, set_block_for_insn, set_block_for_new_insns - Edge manipulation - make_edge, remove_edge + make_edge, make_single_succ_edge, cached_make_edge, remove_edge - Low level edge redirection (without updating instruction chain) redirect_edge_succ, redirect_edge_succ_nodup, redirect_edge_pred - High level edge redirection (with updating and optimizing instruction @@ -80,6 +80,10 @@ int n_basic_blocks; int n_edges; +/* First edge in the deleted edges chain. */ + +edge first_deleted_edge; + /* The basic block array. */ varray_type basic_block_info; @@ -151,6 +155,9 @@ init_flow () { static int initialized; + first_deleted_edge = 0; + n_edges = 0; + if (!initialized) { gcc_obstack_init (&flow_obstack); @@ -170,32 +177,20 @@ void clear_edges () { int i; - edge n, e; for (i = 0; i < n_basic_blocks; ++i) { basic_block bb = BASIC_BLOCK (i); - for (e = bb->succ; e; e = n) - { - n = e->succ_next; - free (e); - } - - bb->succ = 0; - bb->pred = 0; + while (bb->succ) + remove_edge (bb->succ); } - for (e = ENTRY_BLOCK_PTR->succ; e; e = n) - { - n = e->succ_next; - free (e); - } + while (ENTRY_BLOCK_PTR->succ) + remove_edge (ENTRY_BLOCK_PTR->succ); - ENTRY_BLOCK_PTR->succ = 0; - EXIT_BLOCK_PTR->pred = 0; - - n_edges = 0; + if (n_edges) + abort (); } /* Return true if NOTE is not one of the ones that must be kept paired, @@ -458,26 +453,10 @@ flow_delete_block (b) /* Remove the edges into and out of this block. Note that there may indeed be edges in, if we are removing an unreachable loop. */ { - edge e, next, *q; - - for (e = b->pred; e; e = next) - { - for (q = &e->src->succ; *q != e; q = &(*q)->succ_next) - continue; - *q = e->succ_next; - next = e->pred_next; - n_edges--; - free (e); - } - for (e = b->succ; e; e = next) - { - for (q = &e->dest->pred; *q != e; q = &(*q)->pred_next) - continue; - *q = e->pred_next; - next = e->succ_next; - n_edges--; - free (e); - } + while (b->pred != NULL) + remove_edge (b->pred); + while (b->succ != NULL) + remove_edge (b->succ); b->pred = NULL; b->succ = NULL; @@ -589,8 +568,10 @@ set_block_for_new_insns (insn, bb) } } -void -make_edge (edge_cache, src, dst, flags) +/* Create an edge connecting SRC and DST with FLAGS optionally using + edge cache CACHE. Return the new edge, NULL if already exist. */ +edge +cached_make_edge (edge_cache, src, dst, flags) sbitmap *edge_cache; basic_block src, dst; int flags; @@ -614,7 +595,7 @@ make_edge (edge_cache, src, dst, flags) /* The edge exists; early exit if no work to do. */ if (flags == 0) - return; + return NULL; /* FALLTHRU */ case 0: @@ -622,12 +603,21 @@ make_edge (edge_cache, src, dst, flags) if (e->dest == dst) { e->flags |= flags; - return; + return NULL; } break; } - e = (edge) xcalloc (1, sizeof (*e)); + if (first_deleted_edge) + { + e = first_deleted_edge; + first_deleted_edge = e->succ_next; + } + else + { + e = (edge) obstack_alloc (&flow_obstack, sizeof (*e)); + memset (e, 0, sizeof (*e)); + } n_edges++; e->succ_next = src->succ; @@ -641,6 +631,34 @@ make_edge (edge_cache, src, dst, flags) if (use_edge_cache) SET_BIT (edge_cache[src->index], dst->index); + + return e; +} + +/* Create an edge connecting SRC and DEST with flags FLAGS. Return newly + created edge or NULL if already exist. */ + +edge +make_edge (src, dest, flags) + basic_block src, dest; + int flags; +{ + return cached_make_edge (NULL, src, dest, flags); +} + +/* Create an edge connecting SRC to DEST and set probability by knowling + that it is the single edge leaving SRC. */ + +edge +make_single_succ_edge (src, dest, flags) + basic_block src, dest; + int flags; +{ + edge e = make_edge (src, dest, flags); + + e->probability = REG_BR_PROB_BASE; + e->count = src->count; + return e; } /* This function will remove an edge from the flow graph. */ @@ -676,7 +694,9 @@ remove_edge (e) dest->pred = e->pred_next; n_edges--; - free (e); + memset (e, 0, sizeof (*e)); + e->succ_next = first_deleted_edge; + first_deleted_edge = e; } /* Redirect an edge's successor from one block to another. */ @@ -766,8 +786,6 @@ split_block (bb, insn) /* Create the new structures. */ new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb)); - new_edge = (edge) xcalloc (1, sizeof (*new_edge)); - n_edges++; memset (new_bb, 0, sizeof (*new_bb)); @@ -776,22 +794,18 @@ split_block (bb, insn) bb->end = insn; new_bb->succ = bb->succ; - bb->succ = new_edge; - new_bb->pred = new_edge; + bb->succ = NULL; + new_bb->pred = NULL; new_bb->count = bb->count; new_bb->frequency = bb->frequency; new_bb->loop_depth = bb->loop_depth; - new_edge->src = bb; - new_edge->dest = new_bb; - new_edge->flags = EDGE_FALLTHRU; - new_edge->probability = REG_BR_PROB_BASE; - new_edge->count = bb->count; - /* Redirect the src of the successor edges of bb to point to new_bb. */ for (e = new_bb->succ; e; e = e->succ_next) e->src = new_bb; + new_edge = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU); + /* Place the new block just after the block being split. */ VARRAY_GROW (basic_block_info, ++n_basic_blocks); @@ -1262,22 +1276,16 @@ redirect_edge_and_branch_force (e, target) /* Create the new structures. */ new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb)); - new_edge = (edge) xcalloc (1, sizeof (*new_edge)); - n_edges++; memset (new_bb, 0, sizeof (*new_bb)); new_bb->end = new_bb->head = last_loop_beg_note (e->src->end); new_bb->succ = NULL; - new_bb->pred = new_edge; + new_bb->pred = NULL; new_bb->count = e->count; new_bb->frequency = EDGE_FREQUENCY (e); new_bb->loop_depth = e->dest->loop_depth; - new_edge->flags = EDGE_FALLTHRU; - new_edge->probability = e->probability; - new_edge->count = e->count; - if (target->global_live_at_start) { new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack); @@ -1288,11 +1296,9 @@ redirect_edge_and_branch_force (e, target) } /* Wire edge in. */ - new_edge->src = e->src; - new_edge->dest = new_bb; - new_edge->succ_next = e->src->succ; - e->src->succ = new_edge; - new_edge->pred_next = NULL; + new_edge = make_edge (e->src, new_bb, EDGE_FALLTHRU); + new_edge->probability = e->probability; + new_edge->count = e->count; /* Redirect old edge. */ redirect_edge_succ (e, target); @@ -1487,8 +1493,6 @@ split_edge (edge_in) /* Create the new structures. */ bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb)); - edge_out = (edge) xcalloc (1, sizeof (*edge_out)); - n_edges++; memset (bb, 0, sizeof (*bb)); @@ -1502,21 +1506,13 @@ split_edge (edge_in) } /* Wire them up. */ - bb->succ = edge_out; + bb->succ = NULL; bb->count = edge_in->count; bb->frequency = EDGE_FREQUENCY (edge_in); edge_in->flags &= ~EDGE_CRITICAL; - edge_out->pred_next = old_succ->pred; - edge_out->succ_next = NULL; - edge_out->src = bb; - edge_out->dest = old_succ; - edge_out->flags = EDGE_FALLTHRU; - edge_out->probability = REG_BR_PROB_BASE; - edge_out->count = edge_in->count; - - old_succ->pred = edge_out; + edge_out = make_single_succ_edge (bb, old_succ, EDGE_FALLTHRU); /* Tricky case -- if there existed a fallthru into the successor (and we're not it) we must add a new unconditional jump around diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 96a20b8f3c3..5711794801f 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -348,7 +348,7 @@ flow_call_edges_add (blocks) if (e) blocks_split++; - make_edge (NULL, bb, EXIT_BLOCK_PTR, EDGE_FAKE); + make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE); } if (insn == bb->head) break; @@ -762,7 +762,7 @@ add_noreturn_fake_exit_edges () for (x = 0; x < n_basic_blocks; x++) if (BASIC_BLOCK (x)->succ == NULL) - make_edge (NULL, BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE); + make_single_succ_edge (BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE); } /* This function adds a fake edge between any infinite loops to the @@ -794,7 +794,7 @@ connect_infinite_loops_to_exit () unvisited_block = flow_dfs_compute_reverse_execute (&dfs_ds); if (!unvisited_block) break; - make_edge (NULL, unvisited_block, EXIT_BLOCK_PTR, EDGE_FAKE); + make_edge (unvisited_block, EXIT_BLOCK_PTR, EDGE_FAKE); flow_dfs_compute_reverse_add_bb (&dfs_ds, unvisited_block); } diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 2f62b067ff5..ea1c7327b34 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -186,7 +186,7 @@ make_label_edge (edge_cache, src, label, flags) if (INSN_UID (label) == 0) return; - make_edge (edge_cache, src, BLOCK_FOR_INSN (label), flags); + cached_make_edge (edge_cache, src, BLOCK_FOR_INSN (label), flags); } /* Create the edges generated by INSN in REGION. */ @@ -246,7 +246,7 @@ make_edges (label_value_list, min, max, update_p) } /* By nature of the way these get numbered, block 0 is always the entry. */ - make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU); + cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU); for (i = min; i <= max; ++i) { @@ -257,7 +257,7 @@ make_edges (label_value_list, min, max, update_p) if (GET_CODE (bb->head) == CODE_LABEL && LABEL_ALTERNATE_NAME (bb->head)) - make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0); + cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0); /* Examine the last instruction of the block, and discover the ways we can leave the block. */ @@ -330,7 +330,7 @@ make_edges (label_value_list, min, max, update_p) /* Returns create an exit out. */ else if (returnjump_p (insn)) - make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0); + cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0); /* Otherwise, we have a plain conditional or unconditional jump. */ else @@ -347,7 +347,7 @@ make_edges (label_value_list, min, max, update_p) wouldn't have created the sibling call in the first place. */ if (code == CALL_INSN && SIBLING_CALL_P (insn)) - make_edge (edge_cache, bb, EXIT_BLOCK_PTR, + cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); /* If this is a CALL_INSN, then mark it as reaching the active EH @@ -383,14 +383,14 @@ make_edges (label_value_list, min, max, update_p) /* Find out if we can drop through to the next block. */ insn = next_nonnote_insn (insn); if (!insn || (i + 1 == n_basic_blocks && force_fallthru)) - make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU); + cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU); else if (i + 1 < n_basic_blocks) { rtx tmp = BLOCK_HEAD (i + 1); if (GET_CODE (tmp) == NOTE) tmp = next_nonnote_insn (tmp); if (force_fallthru || insn == tmp) - make_edge (edge_cache, bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU); + cached_make_edge (edge_cache, bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU); } } @@ -701,7 +701,7 @@ find_sub_basic_blocks (bb) remove_edge (falltru); jump_insn = 0; if (LABEL_ALTERNATE_NAME (insn)) - make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0); + make_edge (ENTRY_BLOCK_PTR, bb, 0); break; case INSN: case JUMP_INSN: diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 00eb80adc7c..4413c027f17 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -941,9 +941,7 @@ try_crossjump_to_edge (mode, e1, e2) /* Update CFG. */ while (src1->succ) remove_edge (src1->succ); - make_edge (NULL, src1, redirect_to, 0); - src1->succ->probability = REG_BR_PROB_BASE; - src1->succ->count = src1->count; + make_single_succ_edge (src1, redirect_to, 0); return true; } diff --git a/gcc/profile.c b/gcc/profile.c index d011021ce15..81737f98fe0 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -563,7 +563,7 @@ branch_prob () || insn != NEXT_INSN (bb->head)) { e = split_block (bb, PREV_INSN (insn)); - make_edge (NULL, ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE); + make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE); break; } else @@ -572,7 +572,7 @@ branch_prob () be the very first instruction of function. */ if (!i) abort (); - make_edge (NULL, ENTRY_BLOCK_PTR, bb, EDGE_FAKE); + make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE); } } } @@ -599,14 +599,14 @@ branch_prob () if (rtl_dump_file) fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n", bb->index); - make_edge (NULL, bb, EXIT_BLOCK_PTR, EDGE_FAKE); + make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE); } if (need_entry_edge && !have_entry_edge) { if (rtl_dump_file) fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n", bb->index); - make_edge (NULL, ENTRY_BLOCK_PTR, bb, EDGE_FAKE); + make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE); } } diff --git a/gcc/ssa-dce.c b/gcc/ssa-dce.c index de763219aa7..797a01ca68a 100644 --- a/gcc/ssa-dce.c +++ b/gcc/ssa-dce.c @@ -707,7 +707,7 @@ ssa_eliminate_dead_code () /* Create an edge from this block to the post dominator. What about the PHI nodes at the target? */ - make_edge (NULL, bb, pdom_bb, 0); + make_edge (bb, pdom_bb, 0); /* Third, transform this insn into an unconditional jump to the label for the immediate postdominator. */