This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
BB creation cleanup
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com, patches at x86-64 dot org
- Subject: BB creation cleanup
- From: Jan Hubicka <jh at suse dot cz>
- Date: Tue, 11 Sep 2001 14:50:48 +0200
Hi,
This is another cleanup patch, now for BB creation, I was thinking about for a while.
Now all BBs are created via create_basic_block call (so we can use similar allocation
scheme as we do now for edges) and I've added new function "force_nonfallthru" that
breaks fallthru edge by creating jump (possibly in new basic block).
I've made create_basic_block to handle renumbering of basic blocks and thus CFG
building code now uses create_basic_block_structure that avoids this
functionality.
This functionality is common to redirect_edge_and_branch_force, split_edge and
fixup_reorder_chain. merge_blocks can be made cleaner using it avoiding
the dirty trick with cralling redirect_edge_and_branch_force.
Especially the split_edge and merge_blocks looks IMO much more readable now.
Bootstrapped/regtested i586.
Honza
Tue Sep 11 14:40:52 CEST 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (create_basic_block_structure): New.
(create_basic_block): Update prototype.
(force_nonfallthru): New.
* bb-reorder.c (fixup_reorder_chain): Fixup use force_nonfallthru.
* cfg.c (create_basic_block_structure): Rename from create_basic_block;
handle updating of block_for_insn, creating of empty BBs and BBs at
the end of INSN chain.
(create_basic_block): New function.
(split_block): Use create_basic_block.
(force_nonfallthru_and_redirect): Break out from ...; cleanup
(redirect_edge_and_branch_force): ... here.
(force_nonfallthru): New.
(split_edge): Rewrite to use force_nonfallthru and create_block.
* cfgbuild.c (find_basic_blocks_1): Use create_basic_block_structure.
(find_basic_blocks): Free basic_block_for_insn.
* cfgcleanup.c (merge_blocks): Use force_nonfallthru.
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/basic-block.h,v
retrieving revision 1.117
diff -c -3 -p -r1.117 basic-block.h
*** basic-block.h 2001/09/11 09:39:10 1.117
--- basic-block.h 2001/09/11 12:33:49
*************** extern void remove_edge PARAMS ((edge)
*** 315,321 ****
extern void redirect_edge_succ PARAMS ((edge, basic_block));
extern edge 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));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
--- 315,322 ----
extern void redirect_edge_succ PARAMS ((edge, basic_block));
extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block));
extern void redirect_edge_pred PARAMS ((edge, basic_block));
! extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
! extern basic_block create_basic_block PARAMS ((int, rtx, rtx));
extern int flow_delete_block PARAMS ((basic_block));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
*************** extern void allocate_bb_life_data PARAMS
*** 629,634 ****
--- 630,636 ----
extern void find_unreachable_blocks PARAMS ((void));
extern void delete_noop_moves PARAMS ((rtx));
extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
+ extern basic_block force_nonfallthru PARAMS ((edge));
extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
extern rtx block_label PARAMS ((basic_block));
extern bool forwarder_block_p PARAMS ((basic_block));
Index: bb-reorder.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/bb-reorder.c,v
retrieving revision 1.36
diff -c -3 -p -r1.36 bb-reorder.c
*** bb-reorder.c 2001/09/11 09:39:11 1.36
--- bb-reorder.c 2001/09/11 12:33:50
*************** fixup_reorder_chain ()
*** 610,616 ****
for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
{
edge e_fall, e_taken, e;
! rtx jump_insn, barrier_insn, bb_end_insn;
basic_block nb;
if (bb->succ == NULL)
--- 610,616 ----
for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
{
edge e_fall, e_taken, e;
! rtx bb_end_insn;
basic_block nb;
if (bb->succ == NULL)
*************** fixup_reorder_chain ()
*** 694,747 ****
/* If the fallthru block is still next, nothing to do. */
if (RBI (bb)->next == e_fall->dest)
continue;
-
- /* We need a new jump insn. If the block has only one outgoing
- edge, then we can stuff the new jump insn in directly. */
- if (bb->succ->succ_next == NULL)
- {
- e_fall->flags &= ~EDGE_FALLTHRU;
-
- jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
- bb->end = jump_insn;
- barrier_insn = emit_barrier_after (jump_insn);
- RBI (bb)->eff_end = barrier_insn;
- continue;
- }
}
! /* We got here if we need to add a new jump insn in a new block
! across the edge e_fall. */
! jump_insn = emit_jump_to_block_after (e_fall->dest, bb_end_insn);
! barrier_insn = emit_barrier_after (jump_insn);
! VARRAY_GROW (basic_block_info, ++n_basic_blocks);
! create_basic_block (n_basic_blocks - 1, jump_insn, jump_insn, NULL);
!
! nb = BASIC_BLOCK (n_basic_blocks - 1);
! nb->local_set = 0;
! nb->count = e_fall->count;
! nb->frequency = EDGE_FREQUENCY (e_fall);
!
! nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
! nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
! COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
! COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
!
! nb->aux = xmalloc (sizeof (struct reorder_block_def));
! RBI (nb)->eff_head = nb->head;
! RBI (nb)->eff_end = barrier_insn;
! RBI (nb)->scope = RBI (bb)->scope;
! RBI (nb)->visited = 1;
! RBI (nb)->next = RBI (bb)->next;
! RBI (bb)->next = nb;
!
! /* Link to new block. */
! make_single_succ_edge (nb, e_fall->dest, 0);
! redirect_edge_succ (e_fall, nb);
!
! /* Don't process this new block. */
! bb = nb;
}
/* Put basic_block_info in the new order. */
--- 694,717 ----
/* If the fallthru block is still next, nothing to do. */
if (RBI (bb)->next == e_fall->dest)
continue;
}
! /* We got here if we need to add a new jump insn. */
! nb = force_nonfallthru (e_fall);
! if (nb)
! {
! nb->aux = xmalloc (sizeof (struct reorder_block_def));
! RBI (nb)->eff_head = nb->head;
! RBI (nb)->eff_end = NEXT_INSN (nb->end);
! RBI (nb)->scope = RBI (bb)->scope;
! RBI (nb)->visited = 1;
! RBI (nb)->next = RBI (bb)->next;
! RBI (bb)->next = nb;
! /* Don't process this new block. */
! bb = nb;
! }
}
/* Put basic_block_info in the new order. */
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfg.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfg.c
*** cfg.c 2001/09/11 09:39:11 1.2
--- cfg.c 2001/09/11 12:33:50
*************** Software Foundation, 59 Temple Place - S
*** 40,46 ****
- High level edge redirection (with updating and optimizing instruction
chain)
block_label, redirect_edge_and_branch,
! redirect_edge_and_branch_force, tidy_fallthru_edge
- Edge splitting and commiting to edges
split_edge, insert_insn_on_edge, commit_edge_insertions
- Dumpipng and debugging
--- 40,46 ----
- High level edge redirection (with updating and optimizing instruction
chain)
block_label, redirect_edge_and_branch,
! redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
- Edge splitting and commiting to edges
split_edge, insert_insn_on_edge, commit_edge_insertions
- Dumpipng and debugging
*************** static bool try_redirect_by_replacing_ju
*** 147,152 ****
--- 147,153 ----
static void expunge_block PARAMS ((basic_block));
static rtx last_loop_beg_note PARAMS ((rtx));
static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
+ static basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
/* Called once at intialization time. */
*************** flow_delete_insn_chain (start, finish)
*** 320,330 ****
}
/* Create a new basic block consisting of the instructions between
! HEAD and END inclusive. Reuses the note and basic block struct
! in BB_NOTE, if any. */
! void
! create_basic_block (index, head, end, bb_note)
int index;
rtx head, end, bb_note;
{
--- 321,336 ----
}
/* Create a new basic block consisting of the instructions between
! HEAD and END inclusive. This function is designed to allow fast
! BB construction - reuses the note and basic block struct
! in BB_NOTE, if any and do not grow BASIC_BLOCK chain and should
! be used directly only by CFG construction code.
! END can be NULL in to create new empty basic block before HEAD.
! Both END and HEAD can be NULL to create basic block at the end of
! INSN chain. */
! basic_block
! create_basic_block_structure (index, head, end, bb_note)
int index;
rtx head, end, bb_note;
{
*************** create_basic_block (index, head, end, bb
*** 360,371 ****
bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
memset (bb, 0, sizeof (*bb));
! if (GET_CODE (head) == CODE_LABEL)
! bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
else
{
bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
head = bb_note;
}
NOTE_BASIC_BLOCK (bb_note) = bb;
}
--- 366,388 ----
bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
memset (bb, 0, sizeof (*bb));
! if (!head && !end)
! {
! head = end = bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK,
! get_last_insn ());
! }
! else if (GET_CODE (head) == CODE_LABEL && end)
! {
! bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
! if (head == end)
! end = bb_note;
! }
else
{
bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, head);
head = bb_note;
+ if (!end)
+ end = head;
}
NOTE_BASIC_BLOCK (bb_note) = bb;
}
*************** create_basic_block (index, head, end, bb
*** 378,387 ****
--- 395,440 ----
bb->end = end;
bb->index = index;
BASIC_BLOCK (index) = bb;
+ if (basic_block_for_insn)
+ update_bb_for_insn (bb);
/* Tag the block so that we know it has been used when considering
other basic block notes. */
bb->aux = bb;
+
+ return bb;
+ }
+
+ /* Create new basic block consisting of instructions in between HEAD and
+ END and place it to the BB chain at possition INDEX.
+ END can be NULL in to create new empty basic block before HEAD.
+ Both END and HEAD can be NULL to create basic block at the end of
+ INSN chain. */
+
+ basic_block
+ create_basic_block (index, head, end)
+ int index;
+ rtx head, end;
+ {
+ basic_block bb;
+ int i;
+
+ /* 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.. */
+ for (i = n_basic_blocks - 1; i > index; --i)
+ {
+ basic_block tmp = BASIC_BLOCK (i - 1);
+ BASIC_BLOCK (i) = tmp;
+ tmp->index = i;
+ }
+
+ bb = create_basic_block_structure (index, head, end, NULL);
+ bb->aux = NULL;
+ return bb;
}
/* Remove block B from the basic block array and compact behind it. */
*************** split_block (bb, insn)
*** 777,851 ****
basic_block new_bb;
edge new_edge;
edge e;
- rtx bb_note;
- int i, j;
/* 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 (&flow_obstack, sizeof (*new_bb));
-
- 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 = NULL;
! new_bb->pred = NULL;
new_bb->count = bb->count;
new_bb->frequency = bb->frequency;
new_bb->loop_depth = bb->loop_depth;
! /* 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);
-
- /* 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;
-
- if (GET_CODE (new_bb->head) == CODE_LABEL)
- {
- /* Create the basic block note. */
- bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK,
- new_bb->head);
- NOTE_BASIC_BLOCK (bb_note) = new_bb;
-
- /* If the only thing in this new block was the label, make sure
- the block note gets included. */
- if (new_bb->head == new_bb->end)
- new_bb->end = bb_note;
- }
- else
- {
- /* 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 (&flow_obstack);
--- 831,856 ----
basic_block new_bb;
edge new_edge;
edge e;
/* There is no point splitting the block after its end. */
if (bb->end == insn)
return 0;
! /* Create the new basic block. */
! new_bb = create_basic_block (bb->index + 1, NEXT_INSN (insn), bb->end);
new_bb->count = bb->count;
new_bb->frequency = bb->frequency;
new_bb->loop_depth = bb->loop_depth;
+ bb->end = insn;
! /* Redirect the outgoing edges. */
! new_bb->succ = bb->succ;
! bb->succ = NULL;
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);
if (bb->global_live_at_start)
{
new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
*************** last_loop_beg_note (insn)
*** 1110,1116 ****
{
rtx last = insn;
insn = NEXT_INSN (insn);
! while (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
--- 1115,1121 ----
{
rtx last = insn;
insn = NEXT_INSN (insn);
! while (insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
*************** redirect_edge_and_branch (e, target)
*** 1222,1338 ****
return true;
}
! /* Redirect edge even at the expense of creating new jump insn or
! basic block. Return new basic block if created, NULL otherwise.
! Abort if converison is impossible. */
! basic_block
! redirect_edge_and_branch_force (e, target)
edge e;
basic_block target;
{
! basic_block new_bb;
edge new_edge;
rtx label;
- rtx bb_note;
- int i, j;
- if (redirect_edge_and_branch (e, target))
- return NULL;
- if (e->dest == target)
- return NULL;
if (e->flags & EDGE_ABNORMAL)
abort ();
if (!(e->flags & EDGE_FALLTHRU))
abort ();
!
! e->flags &= ~EDGE_FALLTHRU;
! label = block_label (target);
! /* Case of the fallthru block. */
! if (!e->src->succ->succ_next)
{
! e->src->end = emit_jump_insn_after (gen_jump (label),
! last_loop_beg_note (e->src->end));
! JUMP_LABEL (e->src->end) = label;
! LABEL_NUSES (label)++;
! if (basic_block_for_insn)
! set_block_for_new_insns (e->src->end, e->src);
! emit_barrier_after (e->src->end);
! if (rtl_dump_file)
! fprintf (rtl_dump_file,
! "Emitting jump insn %i to redirect edge %i->%i to %i\n",
! INSN_UID (e->src->end), e->src->index, e->dest->index,
! target->index);
! redirect_edge_succ (e, target);
! return NULL;
! }
! /* Redirecting fallthru edge of the conditional needs extra work. */
!
! if (rtl_dump_file)
! fprintf (rtl_dump_file,
! "Emitting jump insn %i in new BB to redirect edge %i->%i to %i\n",
! INSN_UID (e->src->end), e->src->index, e->dest->index,
! target->index);
!
! /* Create the new structures. */
! new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb));
!
! 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 = NULL;
! new_bb->count = e->count;
! new_bb->frequency = EDGE_FREQUENCY (e);
! new_bb->loop_depth = e->dest->loop_depth;
! if (target->global_live_at_start)
! {
! new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
! new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
! COPY_REG_SET (new_bb->global_live_at_start,
! target->global_live_at_start);
! COPY_REG_SET (new_bb->global_live_at_end, new_bb->global_live_at_start);
}
! /* Wire edge in. */
! 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);
! redirect_edge_pred (e, new_bb);
! e->probability = REG_BR_PROB_BASE;
! /* 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 = new_edge->src->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_after (NOTE_INSN_BASIC_BLOCK, new_bb->head);
! NOTE_BASIC_BLOCK (bb_note) = new_bb;
! new_bb->head = bb_note;
! new_bb->end = emit_jump_insn_after (gen_jump (label), new_bb->head);
! JUMP_LABEL (new_bb->end) = label;
! LABEL_NUSES (label)++;
! if (basic_block_for_insn)
! set_block_for_new_insns (new_bb->end, new_bb);
! emit_barrier_after (new_bb->end);
return new_bb;
}
--- 1227,1325 ----
return true;
}
! /* Like force_nonfallthru bellow, but additionally performs redirection
! Used by redirect_edge_and_branch_force. */
! static basic_block
! force_nonfallthru_and_redirect (e, target)
edge e;
basic_block target;
{
! basic_block jump_block, new_bb = NULL;
! rtx note;
edge new_edge;
rtx label;
if (e->flags & EDGE_ABNORMAL)
abort ();
if (!(e->flags & EDGE_FALLTHRU))
abort ();
! if (e->src->succ->succ_next)
{
! /* Create the new structures. */
! note = last_loop_beg_note (e->src->end);
! jump_block = create_basic_block (e->src->index + 1, NEXT_INSN (note), NULL);
! jump_block->count = e->count;
! jump_block->frequency = EDGE_FREQUENCY (e);
! jump_block->loop_depth = target->loop_depth;
!
! if (target->global_live_at_start)
! {
! jump_block->global_live_at_start =
! OBSTACK_ALLOC_REG_SET (&flow_obstack);
! jump_block->global_live_at_end =
! OBSTACK_ALLOC_REG_SET (&flow_obstack);
! COPY_REG_SET (jump_block->global_live_at_start,
! target->global_live_at_start);
! COPY_REG_SET (jump_block->global_live_at_end,
! target->global_live_at_start);
! }
!
! /* Wire edge in. */
! new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
! new_edge->probability = e->probability;
! new_edge->count = e->count;
!
! /* Redirect old edge. */
! redirect_edge_pred (e, jump_block);
! e->probability = REG_BR_PROB_BASE;
! new_bb = jump_block;
}
+ else
+ jump_block = e->src;
+ e->flags &= ~(EDGE_FALLTHRU | EDGE_CRITICAL);
+ label = block_label (target);
+ jump_block->end = emit_jump_insn_after (gen_jump (label), jump_block->end);
+ JUMP_LABEL (jump_block->end) = label;
+ LABEL_NUSES (label)++;
+ if (basic_block_for_insn)
+ set_block_for_new_insns (jump_block->end, jump_block);
+ emit_barrier_after (jump_block->end);
+ redirect_edge_succ_nodup (e, target);
! return new_bb;
! }
! /* Edge E is assumed to be fallthru edge. Emit needed jump instruction
! (and possibly create new basic block) to make edge non-fallthru.
! Return newly created BB or NULL if none. */
! basic_block
! force_nonfallthru (e)
! edge e;
! {
! return force_nonfallthru_and_redirect (e, e->dest);
! }
! /* Redirect edge even at the expense of creating new jump insn or
! basic block. Return new basic block if created, NULL otherwise.
! Abort if converison is impossible. */
! basic_block
! redirect_edge_and_branch_force (e, target)
! edge e;
! basic_block target;
! {
! basic_block new_bb;
! if (redirect_edge_and_branch (e, target))
! return NULL;
! if (e->dest == target)
! return NULL;
! /* In case the edge redirection failed, try to force it to be non-fallthru
! and redirect newly created simplejump. */
! new_bb = force_nonfallthru_and_redirect (e, target);
return new_bb;
}
*************** basic_block
*** 1479,1527 ****
split_edge (edge_in)
edge edge_in;
{
! basic_block old_pred, bb, old_succ;
edge edge_out;
! rtx bb_note;
! int i, j;
/* Abnormal edges cannot be split. */
if ((edge_in->flags & EDGE_ABNORMAL) != 0)
abort ();
-
- old_pred = edge_in->src;
- old_succ = edge_in->dest;
-
- /* Create the new structures. */
- bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*bb));
-
- memset (bb, 0, sizeof (*bb));
-
- /* ??? This info is likely going to be out of date very soon. */
- if (old_succ->global_live_at_start)
- {
- bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
- bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
- COPY_REG_SET (bb->global_live_at_start, old_succ->global_live_at_start);
- COPY_REG_SET (bb->global_live_at_end, old_succ->global_live_at_start);
- }
! /* Wire them up. */
! bb->succ = NULL;
! bb->count = edge_in->count;
! bb->frequency = EDGE_FREQUENCY (edge_in);
!
! edge_in->flags &= ~EDGE_CRITICAL;
!
! 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
! the new block we're actually interested in.
!
! Further, if that edge is critical, this means a second new basic
! block must be created to hold it. In order to simplify correct
! insn placement, do this before we touch the existing basic block
! ordering for the block we were really wanting. */
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{
edge e;
--- 1466,1481 ----
split_edge (edge_in)
edge edge_in;
{
! basic_block bb;
edge edge_out;
! rtx before;
/* Abnormal edges cannot be split. */
if ((edge_in->flags & EDGE_ABNORMAL) != 0)
abort ();
! /* We are going to place the new block in front of edge destination.
! Avoid existence of fallthru predecesors. */
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{
edge e;
*************** split_edge (edge_in)
*** 1530,1589 ****
break;
if (e)
! {
! basic_block jump_block;
! rtx pos;
!
! if ((e->flags & EDGE_CRITICAL) == 0
! && e->src != ENTRY_BLOCK_PTR)
! {
! /* Non critical -- we can simply add a jump to the end
! of the existing predecessor. */
! jump_block = e->src;
! }
! else
! {
! /* We need a new block to hold the jump. The simplest
! way to do the bulk of the work here is to recursively
! call ourselves. */
! jump_block = split_edge (e);
! e = jump_block->succ;
! }
!
! /* Now add the jump insn ... */
! pos = emit_jump_insn_after (gen_jump (old_succ->head),
! last_loop_beg_note (jump_block->end));
! jump_block->end = pos;
! if (basic_block_for_insn)
! set_block_for_new_insns (pos, jump_block);
! emit_barrier_after (pos);
!
! /* ... let jump know that label is in use, ... */
! JUMP_LABEL (pos) = old_succ->head;
! ++LABEL_NUSES (old_succ->head);
!
! /* ... and clear fallthru on the outgoing edge. */
! e->flags &= ~EDGE_FALLTHRU;
!
! /* Continue splitting the interesting edge. */
! }
}
- /* Place the new block just in front of the successor. */
- VARRAY_GROW (basic_block_info, ++n_basic_blocks);
- if (old_succ == EXIT_BLOCK_PTR)
- j = n_basic_blocks - 1;
- else
- j = old_succ->index;
- for (i = n_basic_blocks - 1; i > j; --i)
- {
- basic_block tmp = BASIC_BLOCK (i - 1);
- BASIC_BLOCK (i) = tmp;
- tmp->index = i;
- }
- BASIC_BLOCK (i) = bb;
- bb->index = i;
-
/* Create the basic block note.
Where we place the note can have a noticable impact on the generated
--- 1484,1492 ----
break;
if (e)
! force_nonfallthru (e);
}
/* Create the basic block note.
Where we place the note can have a noticable impact on the generated
*************** split_edge (edge_in)
*** 1601,1620 ****
we want to ensure the instructions we insert are outside of any
loop notes that physically sit between block 0 and block 1. Otherwise
we confuse the loop optimizer into thinking the loop is a phony. */
! if (old_succ != EXIT_BLOCK_PTR
! && PREV_INSN (old_succ->head)
! && GET_CODE (PREV_INSN (old_succ->head)) == NOTE
! && NOTE_LINE_NUMBER (PREV_INSN (old_succ->head)) == NOTE_INSN_LOOP_BEG
! && !back_edge_of_syntactic_loop_p (old_succ, old_pred))
! bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK,
! PREV_INSN (old_succ->head));
! else if (old_succ != EXIT_BLOCK_PTR)
! bb_note = emit_note_before (NOTE_INSN_BASIC_BLOCK, old_succ->head);
else
! bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
! NOTE_BASIC_BLOCK (bb_note) = bb;
! bb->head = bb->end = bb_note;
/* For non-fallthry edges, we must adjust the predecessor's
jump instruction to target our new block. */
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
--- 1504,1538 ----
we want to ensure the instructions we insert are outside of any
loop notes that physically sit between block 0 and block 1. Otherwise
we confuse the loop optimizer into thinking the loop is a phony. */
!
! if (edge_in->dest != EXIT_BLOCK_PTR
! && PREV_INSN (edge_in->dest->head)
! && GET_CODE (PREV_INSN (edge_in->dest->head)) == NOTE
! && NOTE_LINE_NUMBER (PREV_INSN (edge_in->dest->head)) == NOTE_INSN_LOOP_BEG
! && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
! before = PREV_INSN (edge_in->dest->head);
! else if (edge_in->dest != EXIT_BLOCK_PTR)
! before = edge_in->dest->head;
else
! before = NULL_RTX;
+ bb = create_basic_block (edge_in->dest == EXIT_BLOCK_PTR ? n_basic_blocks
+ : edge_in->dest->index, before, NULL);
+ bb->count = edge_in->count;
+ bb->frequency = EDGE_FREQUENCY (edge_in);
+
+ /* ??? This info is likely going to be out of date very soon. */
+ if (edge_in->dest->global_live_at_start)
+ {
+ bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+ bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+ COPY_REG_SET (bb->global_live_at_start, edge_in->dest->global_live_at_start);
+ COPY_REG_SET (bb->global_live_at_end, edge_in->dest->global_live_at_start);
+ }
+
+ edge_in->flags &= ~EDGE_CRITICAL;
+ edge_out = make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
+
/* For non-fallthry edges, we must adjust the predecessor's
jump instruction to target our new block. */
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
Index: cfgbuild.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfgbuild.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfgbuild.c
*** cfgbuild.c 2001/09/11 09:39:11 1.2
--- cfgbuild.c 2001/09/11 12:33:50
*************** find_basic_blocks_1 (f)
*** 452,458 ****
to a barrier or some such, no need to do it again. */
if (head != NULL_RTX)
{
! create_basic_block (i++, head, end, bb_note);
bb_note = NULL_RTX;
}
--- 452,458 ----
to a barrier or some such, no need to do it again. */
if (head != NULL_RTX)
{
! create_basic_block_structure (i++, head, end, bb_note);
bb_note = NULL_RTX;
}
*************** find_basic_blocks_1 (f)
*** 523,529 ****
end = insn;
new_bb_exclusive:
! create_basic_block (i++, head, end, bb_note);
head = end = NULL_RTX;
bb_note = NULL_RTX;
break;
--- 523,529 ----
end = insn;
new_bb_exclusive:
! create_basic_block_structure (i++, head, end, bb_note);
head = end = NULL_RTX;
bb_note = NULL_RTX;
break;
*************** find_basic_blocks_1 (f)
*** 579,585 ****
}
if (head != NULL_RTX)
! create_basic_block (i++, head, end, bb_note);
else if (bb_note)
flow_delete_insn (bb_note);
--- 579,585 ----
}
if (head != NULL_RTX)
! create_basic_block_structure (i++, head, end, bb_note);
else if (bb_note)
flow_delete_insn (bb_note);
*************** find_basic_blocks (f, nregs, file)
*** 603,608 ****
--- 603,612 ----
{
int max_uid;
timevar_push (TV_CFG);
+
+ if (basic_block_for_insn)
+ VARRAY_FREE (basic_block_for_insn);
+ basic_block_for_insn = 0;
/* Flush out existing data. */
if (basic_block_info != NULL)
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfgcleanup.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 cfgcleanup.c
*** cfgcleanup.c 2001/09/11 09:39:11 1.2
--- cfgcleanup.c 2001/09/11 12:33:50
*************** merge_blocks (e, b, c, mode)
*** 376,384 ****
edge recorded from the call_placeholder back to this label, as
that would make optimize_sibling_and_tail_recursive_calls more
complex for no gain. */
! if (GET_CODE (c->head) == CODE_LABEL
&& tail_recursion_label_p (c->head))
! return 0;
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
--- 374,383 ----
edge recorded from the call_placeholder back to this label, as
that would make optimize_sibling_and_tail_recursive_calls more
complex for no gain. */
! if (! (mode & CLEANUP_PRE_SIBCALL)
! && GET_CODE (c->head) == CODE_LABEL
&& tail_recursion_label_p (c->head))
! return false;
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
*************** merge_blocks (e, b, c, mode)
*** 391,412 ****
b->index, c->index);
}
! return 1;
}
/* Otherwise we will need to move code around. Do that only if expensive
transformations are allowed. */
else if (mode & CLEANUP_EXPENSIVE)
{
! edge tmp_edge, c_fallthru_edge;
! int c_has_outgoing_fallthru;
! int b_has_incoming_fallthru;
/* Avoid overactive code motion, as the forwarder blocks should be
eliminated by edge redirection instead. One exception might have
been if B is a forwarder block and C has no fallthru edge, but
that should be cleaned up by bb-reorder instead. */
if (forwarder_block_p (b) || forwarder_block_p (c))
! return 0;
/* We must make sure to not munge nesting of lexical blocks,
and loop notes. This is done by squeezing out all the notes
--- 390,411 ----
b->index, c->index);
}
! return true;
}
/* Otherwise we will need to move code around. Do that only if expensive
transformations are allowed. */
else if (mode & CLEANUP_EXPENSIVE)
{
! edge tmp_edge, b_fallthru_edge;
! bool c_has_outgoing_fallthru;
! bool b_has_incoming_fallthru;
/* Avoid overactive code motion, as the forwarder blocks should be
eliminated by edge redirection instead. One exception might have
been if B is a forwarder block and C has no fallthru edge, but
that should be cleaned up by bb-reorder instead. */
if (forwarder_block_p (b) || forwarder_block_p (c))
! return false;
/* We must make sure to not munge nesting of lexical blocks,
and loop notes. This is done by squeezing out all the notes
*************** merge_blocks (e, b, c, mode)
*** 416,474 ****
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
c_has_outgoing_fallthru = (tmp_edge != NULL);
- c_fallthru_edge = tmp_edge;
for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
b_has_incoming_fallthru = (tmp_edge != NULL);
!
! /* If B does not have an incoming fallthru, then it can be moved
! immediately before C without introducing or modifying jumps.
! C cannot be the first block, so we do not have to worry about
! accessing a non-existent block. */
! if (! b_has_incoming_fallthru)
! return merge_blocks_move_predecessor_nojumps (b, c);
/* Otherwise, we're going to try to move C after B. If C does
not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
! return merge_blocks_move_successor_nojumps (b, c);
!
! /* Otherwise, we'll need to insert an extra jump, and possibly
! a new block to contain it. We can't redirect to EXIT_BLOCK_PTR,
! as we don't have explicit return instructions before epilogues
! are generated, so give up on that case. */
!
! if (c_fallthru_edge->dest != EXIT_BLOCK_PTR
! && merge_blocks_move_successor_nojumps (b, c))
! {
! basic_block target = c_fallthru_edge->dest;
! rtx barrier;
! basic_block new;
!
! /* This is a dirty hack to avoid code duplication.
!
! Set edge to point to wrong basic block, so
! redirect_edge_and_branch_force will do the trick
! and rewire edge back to the original location. */
! redirect_edge_succ (c_fallthru_edge, ENTRY_BLOCK_PTR);
! new = redirect_edge_and_branch_force (c_fallthru_edge, target);
!
! /* We've just created barrier, but another barrier is
! already present in the stream. Avoid the duplicate. */
! barrier = next_nonnote_insn (new ? new->end : b->end);
! if (GET_CODE (barrier) != BARRIER)
! abort ();
! flow_delete_insn (barrier);
! return 1;
! }
! return 0;
}
! return 0;
}
/* Look through the insns at the end of BB1 and BB2 and find the longest
--- 415,451 ----
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
c_has_outgoing_fallthru = (tmp_edge != NULL);
for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
b_has_incoming_fallthru = (tmp_edge != NULL);
! b_fallthru_edge = tmp_edge;
/* Otherwise, we're going to try to move C after B. If C does
not have an outgoing fallthru, then it can be moved
immediately after B without introducing or modifying jumps. */
if (! c_has_outgoing_fallthru)
! {
! merge_blocks_move_successor_nojumps (b, c);
! return true;
! }
! /* If B does not have an incoming fallthru, then it can be moved
! immediately before C without introducing or modifying jumps.
! C cannot be the first block, so we do not have to worry about
! accessing a non-existent block. */
! if (b_has_incoming_fallthru)
! {
! if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
! return false;
! force_nonfallthru (b_fallthru_edge);
! }
! merge_blocks_move_predecessor_nojumps (b, c);
! return true;
}
! return false;
}
/* Look through the insns at the end of BB1 and BB2 and find the longest