From: Michael Hayes Date: Mon, 11 Sep 2000 21:39:33 +0000 (+0000) Subject: basic-block.h (split_block, [...]): New prototypes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c586192c7d0f9f5264179a7af8e48022b1a089de;p=gcc.git basic-block.h (split_block, [...]): New prototypes. * basic-block.h (split_block, update_bb_for_insn): New prototypes. * flow.c (split_block, update_bb_for_insn): New functions. From-SVN: r36332 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1979574aaa7..5b75fc83f9a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2000-09-12 Michael Hayes + + * basic-block.h (split_block, update_bb_for_insn): New prototypes. + * flow.c (split_block, update_bb_for_insn): New functions. + 2000-09-11 Richard Henderson * cse.c (fold_rtx): Honor NO_FUNCTION_CSE. diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 7e11ed5e5ec..79e3c5e97fd 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -235,11 +235,13 @@ extern varray_type basic_block_for_insn; #define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0) extern void compute_bb_for_insn PARAMS ((int)); +extern void update_bb_for_insn PARAMS ((basic_block)); extern void set_block_for_insn PARAMS ((rtx, basic_block)); extern void set_block_num PARAMS ((rtx, int)); extern void free_basic_block_vars PARAMS ((int)); +extern edge split_block PARAMS ((basic_block, rtx)); extern basic_block split_edge PARAMS ((edge)); extern void insert_insn_on_edge PARAMS ((rtx, edge)); extern void commit_edge_insertions PARAMS ((void)); diff --git a/gcc/flow.c b/gcc/flow.c index ca6cac2a0d5..545f248d549 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -1420,6 +1420,102 @@ mark_critical_edges () } } +/* Split a block BB after insn INSN creating a new fallthru edge. + Return the new edge. Note that to keep other parts of the compiler happy, + this function renumbers all the basic blocks so that the new + one has a number one greater than the block split. */ + +edge +split_block (bb, insn) + basic_block bb; + rtx insn; +{ + basic_block new_bb; + edge new_edge; + edge e; + rtx bb_note; + int i, j; + + if (BLOCK_FOR_INSN (insn) != bb) + abort (); + + /* There is no point splitting the block after its end. */ + if (bb->end == insn) + return 0; + + /* Create the new structures. */ + new_bb = (basic_block) obstack_alloc (function_obstack, sizeof (*new_bb)); + new_edge = (edge) xcalloc (1, sizeof (*new_edge)); + n_edges++; + + memset (new_bb, 0, sizeof (*new_bb)); + + new_bb->head = NEXT_INSN (insn); + new_bb->end = bb->end; + bb->end = insn; + + new_bb->succ = bb->succ; + bb->succ = new_edge; + new_bb->pred = new_edge; + new_bb->count = bb->count; + 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; + + /* Place the new block just after the block being split. */ + VARRAY_GROW (basic_block_info, ++n_basic_blocks); + + /* Some parts of the compiler expect blocks to be number in + sequential order so insert the new block immediately after the + block being split.. */ + j = bb->index; + for (i = n_basic_blocks - 1; i > j + 1; --i) + { + basic_block tmp = BASIC_BLOCK (i - 1); + BASIC_BLOCK (i) = tmp; + tmp->index = i; + } + + BASIC_BLOCK (i) = new_bb; + new_bb->index = i; + + /* Create the basic block note. */ + bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, + new_bb->head); + NOTE_BASIC_BLOCK (bb_note) = new_bb; + new_bb->head = bb_note; + + update_bb_for_insn (new_bb); + + if (bb->global_live_at_start) + { + new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (function_obstack); + new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (function_obstack); + COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end); + + /* We now have to calculate which registers are live at the end + of the split basic block and at the start of the new basic + block. Start with those registers that are known to be live + at the end of the original basic block and get + propagate_block to determine which registers are live. */ + COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_end); + propagate_block (new_bb, new_bb->global_live_at_start, NULL, 0); + COPY_REG_SET (new_bb->global_live_at_end, + new_bb->global_live_at_start); + } + + return new_edge; +} + + /* Split a (typically critical) edge. Return the new block. Abort on abnormal edges. @@ -6425,6 +6521,28 @@ count_or_remove_death_notes (blocks, kill) return count; } + +/* Update insns block within BB. */ + +void +update_bb_for_insn (bb) + basic_block bb; +{ + rtx insn; + + if (! basic_block_for_insn) + return; + + for (insn = bb->head; ; insn = NEXT_INSN (insn)) + { + set_block_for_insn (insn, bb); + + if (insn == bb->end) + break; + } +} + + /* Record INSN's block as BB. */ void