This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
cfg_layout mode CFG manipulation functions
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at redhat dot com,rakdver at atrey dot karlin dot mff dot cuni dot cz
- Date: Wed, 18 Jun 2003 00:37:48 +0200
- Subject: cfg_layout mode CFG manipulation functions
Hi,
this patch implements basic RTL manipulation API in the cfglayout mode. I
tested it by turning cfgcleanup and loop discovery into cfglayout mode and it
appears to work well (except the fact that it complettely messes up loop notes
but hopefully these won't be there forever :)
Several things are easier than in the normal mode so I hope it won't
have too many dead ends.
Regtested/bootstrapped on i386, OK?
Tue Jun 17 23:12:11 CEST 2003 Jan Hubicka <jh@suse.cz>
* cfgrtl.c: Update comments.
(try_redirect_by_replacing_jump): New argument.
(redirect_branch_edge): Break out from ...
(rtl_redirect_edge_and_branch): ... this one.
(update_cfg_after_block_merging): Break out from ...
(rtl_merge_blocks): ... this one.
(cfg_layout_split_edge): New.
(cfg_layout_merge_blocks): New.
(cfg_layout_can_merge_blocks_p): New.
(cfg_layout_redirect_edge_and_branch): Reorganize.
(cfg_layout_rtl_cfg_hooks): Fill in.
(cfg_layout_delete_block): Kill barriers.
* cfganal.c (can_fallthru): Deal with exit blocks
* cfglayout.c (cfg_layout_function_header): New function
(record_effective_endpoints): Record function header.
(fixup_reorder_chain): Fixup dead jumptables; place header
*** cfgrtl.c.old3 Tue Jun 17 17:56:51 2003
--- cfgrtl.c Tue Jun 17 23:10:15 2003
*************** Software Foundation, 59 Temple Place - S
*** 23,42 ****
that are aware of the RTL intermediate language.
Available functionality:
- CFG-aware instruction chain manipulation
delete_insn, delete_insn_chain
! - Basic block manipulation
! rtl_create_basic_block, rtl_delete_block,rtl_split_block,
! rtl_merge_block
- Infrastructure to determine quickly basic block for insn
compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
- Edge redirection with updating and optimizing of insn chain
! block_label, rtl_redirect_edge_and_branch,
! rtl_redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
! - Edge splitting and committing to edges
! rtl_split_edge, insert_insn_on_edge, commit_edge_insertions
! - CFG updating after constant propagation
! purge_dead_edges, purge_all_dead_edges */
#include "config.h"
#include "system.h"
--- 23,41 ----
that are aware of the RTL intermediate language.
Available functionality:
+ - Basic CFG/RTL manipulation API documented in cfghooks.h
- CFG-aware instruction chain manipulation
delete_insn, delete_insn_chain
! - Edge splitting and committing to edges
! insert_insn_on_edge, commit_edge_insertions
! - CFG updating after insn simplification
! purge_dead_edges, purge_all_dead_edges
!
! Functions not supposed for generic use:
- Infrastructure to determine quickly basic block for insn
compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
- Edge redirection with updating and optimizing of insn chain
! block_label, tidy_fallthru_edge, force_nonfallthru */
#include "config.h"
#include "system.h"
*************** rtx tail_recursion_label_list;
*** 72,82 ****
static int can_delete_note_p PARAMS ((rtx));
static int can_delete_label_p PARAMS ((rtx));
static void commit_one_edge_insertion PARAMS ((edge, int));
! static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
static rtx last_loop_beg_note PARAMS ((rtx));
static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
static basic_block rtl_split_edge PARAMS ((edge));
static int rtl_verify_flow_info PARAMS ((void));
static edge cfg_layout_split_block PARAMS ((basic_block, void *));
static bool cfg_layout_redirect_edge_and_branch PARAMS ((edge, basic_block));
--- 71,83 ----
static int can_delete_note_p PARAMS ((rtx));
static int can_delete_label_p PARAMS ((rtx));
static void commit_one_edge_insertion PARAMS ((edge, int));
! static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block, int));
! static bool redirect_branch_edge PARAMS ((edge, basic_block));
static rtx last_loop_beg_note PARAMS ((rtx));
static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
static basic_block rtl_split_edge PARAMS ((edge));
+ static basic_block cfg_layout_split_edge PARAMS ((edge));
static int rtl_verify_flow_info PARAMS ((void));
static edge cfg_layout_split_block PARAMS ((basic_block, void *));
static bool cfg_layout_redirect_edge_and_branch PARAMS ((edge, basic_block));
*************** static basic_block rtl_create_basic_bloc
*** 92,97 ****
--- 93,101 ----
static basic_block cfg_layout_create_basic_block PARAMS ((void *, void *, basic_block));
static void rtl_merge_blocks PARAMS ((basic_block, basic_block));
static bool rtl_can_merge_blocks PARAMS ((basic_block, basic_block));
+ static void update_cfg_after_block_merging PARAMS ((basic_block, basic_block));
+ static void cfg_layout_merge_blocks PARAMS ((basic_block, basic_block));
+ static bool cfg_layout_can_merge_blocks_p PARAMS ((basic_block, basic_block));
/* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete it. */
*************** rtl_split_block (bb, insnp)
*** 545,550 ****
--- 549,582 ----
return new_edge;
}
+ /* Assume that the code of basic block B has been merged into A.
+ Do corresponding CFG updates: redirect edges accordingly etc. */
+ static void
+ update_cfg_after_block_merging (a, b)
+ basic_block a, b;
+ {
+ edge e;
+
+ /* Normally there should only be one successor of A and that is B, but
+ partway though the merge of blocks for conditional_execution we'll
+ be merging a TEST block with THEN and ELSE successors. Free the
+ whole lot of them and hope the caller knows what they're doing. */
+ while (a->succ)
+ remove_edge (a->succ);
+
+ /* Adjust the edges out of B for the new owner. */
+ for (e = b->succ; e; e = e->succ_next)
+ e->src = a;
+ a->succ = b->succ;
+ a->flags |= b->flags;
+
+ /* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
+ b->pred = b->succ = NULL;
+ a->global_live_at_end = b->global_live_at_end;
+
+ expunge_block (b);
+ }
+
/* Blocks A and B are to be merged into a single block A. The insns
are already contiguous, hence `nomove'. */
*************** rtl_merge_blocks (a, b)
*** 621,644 ****
else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
del_first = NEXT_INSN (a_end);
! /* Normally there should only be one successor of A and that is B, but
! partway though the merge of blocks for conditional_execution we'll
! be merging a TEST block with THEN and ELSE successors. Free the
! whole lot of them and hope the caller knows what they're doing. */
! while (a->succ)
! remove_edge (a->succ);
!
! /* Adjust the edges out of B for the new owner. */
! for (e = b->succ; e; e = e->succ_next)
! e->src = a;
! a->succ = b->succ;
! a->flags |= b->flags;
!
! /* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
! b->pred = b->succ = NULL;
! a->global_live_at_end = b->global_live_at_end;
!
! expunge_block (b);
/* Delete everything marked above as well as crap that might be
hanging out between the two blocks. */
--- 645,651 ----
else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
del_first = NEXT_INSN (a_end);
! update_cfg_after_block_merging (a, b);
/* Delete everything marked above as well as crap that might be
hanging out between the two blocks. */
*************** block_label (block)
*** 703,711 ****
return values are equivalent to redirect_edge_and_branch. */
static bool
! try_redirect_by_replacing_jump (e, target)
edge e;
basic_block target;
{
basic_block src = e->src;
rtx insn = src->end, kill_from;
--- 710,719 ----
return values are equivalent to redirect_edge_and_branch. */
static bool
! try_redirect_by_replacing_jump (e, target, in_cfglayout)
edge e;
basic_block target;
+ int in_cfglayout;
{
basic_block src = e->src;
rtx insn = src->end, kill_from;
*************** try_redirect_by_replacing_jump (e, targe
*** 737,750 ****
#endif
/* See if we can create the fallthru edge. */
! if (can_fallthru (src, target))
{
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
fallthru = 1;
/* Selectively unlink whole insn chain. */
! delete_insn_chain (kill_from, PREV_INSN (target->head));
}
/* If this already is simplejump, redirect it. */
--- 745,782 ----
#endif
/* See if we can create the fallthru edge. */
! if (in_cfglayout || can_fallthru (src, target))
{
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
fallthru = 1;
/* Selectively unlink whole insn chain. */
! if (in_cfglayout)
! {
! rtx insn = src->rbi->footer;
!
! delete_insn_chain (kill_from, src->end);
!
! /* Remove barriers but keep jumptables. */
! while (insn)
! {
! if (GET_CODE (insn) == BARRIER)
! {
! if (PREV_INSN (insn))
! NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
! else
! src->rbi->footer = NEXT_INSN (insn);
! if (NEXT_INSN (insn))
! PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
! }
! if (GET_CODE (insn) == CODE_LABEL)
! break;
! insn = NEXT_INSN (insn);
! }
! }
! else
! delete_insn_chain (kill_from, PREV_INSN (target->head));
}
/* If this already is simplejump, redirect it. */
*************** last_loop_beg_note (insn)
*** 841,858 ****
return last;
}
! /* Attempt to change code to redirect edge E to TARGET. Don't do that on
! expense of adding new instructions or reordering basic blocks.
!
! Function can be also called with edge destination equivalent to the TARGET.
! Then it should try the simplifications and do nothing if none is possible.
!
! Return true if transformation succeeded. We still return false in case E
! already destinated TARGET and we didn't managed to simplify instruction
! stream. */
!
static bool
! rtl_redirect_edge_and_branch (e, target)
edge e;
basic_block target;
{
--- 873,881 ----
return last;
}
! /* Redirect edge representing branch of (un)conditional jump or tablejump. */
static bool
! redirect_branch_edge (e, target)
edge e;
basic_block target;
{
*************** rtl_redirect_edge_and_branch (e, target)
*** 861,878 ****
basic_block src = e->src;
rtx insn = src->end;
- if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
- return false;
-
- if (try_redirect_by_replacing_jump (e, target))
- return true;
-
- /* Do this fast path late, as we want above code to simplify for cases
- where called on single edge leaving basic block containing nontrivial
- jump insn. */
- else if (e->dest == target)
- return false;
-
/* We can only redirect non-fallthru edges of jump insn. */
if (e->flags & EDGE_FALLTHRU)
return false;
--- 884,889 ----
*************** rtl_redirect_edge_and_branch (e, target)
*** 945,950 ****
--- 956,992 ----
if (e->dest != target)
redirect_edge_succ_nodup (e, target);
+ return true;
+ }
+
+ /* Attempt to change code to redirect edge E to TARGET. Don't do that on
+ expense of adding new instructions or reordering basic blocks.
+
+ Function can be also called with edge destination equivalent to the TARGET.
+ Then it should try the simplifications and do nothing if none is possible.
+
+ Return true if transformation succeeded. We still return false in case E
+ already destinated TARGET and we didn't managed to simplify instruction
+ stream. */
+
+ static bool
+ rtl_redirect_edge_and_branch (e, target)
+ edge e;
+ basic_block target;
+ {
+ if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+ return false;
+
+ if (try_redirect_by_replacing_jump (e, target, false))
+ return true;
+
+ /* Do this fast path late, as we want above code to simplify for cases
+ where called on single edge leaving basic block containing nontrivial
+ jump insn. */
+ else if (e->dest == target)
+ return false;
+ else if (!redirect_branch_edge (e, target))
+ return false;
return true;
}
*************** cfg_layout_redirect_edge_and_branch (e,
*** 2324,2337 ****
basic_block dest;
{
basic_block src = e->src;
- basic_block old_next_bb = src->next_bb;
bool ret;
/* Redirect_edge_and_branch may decide to turn branch into fallthru edge
in the case the basic block appears to be in sequence. Avoid this
transformation. */
- src->next_bb = NULL;
if (e->flags & EDGE_FALLTHRU)
{
/* Redirect any branch edges unified with the fallthru one. */
--- 2366,2398 ----
basic_block dest;
{
basic_block src = e->src;
bool ret;
+ if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+ return false;
+
+ if (e->src != ENTRY_BLOCK_PTR
+ && try_redirect_by_replacing_jump (e, dest, true))
+ return true;
+
+ if (e->dest == dest)
+ return true;
+
+ if (e->src == ENTRY_BLOCK_PTR
+ && (e->flags & EDGE_FALLTHRU) && !(e->flags & EDGE_COMPLEX))
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Redirecting entry edge from bb %i to %i\n",
+ e->src->index, dest->index);
+
+ redirect_edge_succ (e, dest);
+ return true;
+ }
+
/* Redirect_edge_and_branch may decide to turn branch into fallthru edge
in the case the basic block appears to be in sequence. Avoid this
transformation. */
if (e->flags & EDGE_FALLTHRU)
{
/* Redirect any branch edges unified with the fallthru one. */
*************** cfg_layout_redirect_edge_and_branch (e,
*** 2353,2372 ****
delete_insn (src->end);
}
redirect_edge_succ_nodup (e, dest);
ret = true;
}
else
! ret = rtl_redirect_edge_and_branch (e, dest);
/* We don't want simplejumps in the insn stream during cfglayout. */
if (simplejump_p (src->end))
! {
! delete_insn (src->end);
! delete_barrier (NEXT_INSN (src->end));
! src->succ->flags |= EDGE_FALLTHRU;
! }
! src->next_bb = old_next_bb;
return ret;
}
--- 2414,2431 ----
delete_insn (src->end);
}
redirect_edge_succ_nodup (e, dest);
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Fallthru edge %i->%i redirected to %i\n",
+ e->src->index, e->dest->index, dest->index);
ret = true;
}
else
! ret = redirect_branch_edge (e, dest);
/* We don't want simplejumps in the insn stream during cfglayout. */
if (simplejump_p (src->end))
! abort ();
return ret;
}
*************** cfg_layout_delete_block (bb)
*** 2406,2421 ****
next = NEXT_INSN (bb->end);
if (bb->rbi->footer)
{
! insn = bb->end;
! NEXT_INSN (insn) = bb->rbi->footer;
! PREV_INSN (bb->rbi->footer) = insn;
! while (NEXT_INSN (insn))
! insn = NEXT_INSN (insn);
! NEXT_INSN (insn) = next;
! if (next)
! PREV_INSN (next) = insn;
! else
! set_last_insn (insn);
}
if (bb->next_bb != EXIT_BLOCK_PTR)
to = &bb->next_bb->rbi->header;
--- 2465,2499 ----
next = NEXT_INSN (bb->end);
if (bb->rbi->footer)
{
! insn = bb->rbi->footer;
! while (insn)
! {
! if (GET_CODE (insn) == BARRIER)
! {
! if (PREV_INSN (insn))
! NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
! else
! bb->rbi->footer = NEXT_INSN (insn);
! if (NEXT_INSN (insn))
! PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
! }
! if (GET_CODE (insn) == CODE_LABEL)
! break;
! insn = NEXT_INSN (insn);
! }
! if (bb->rbi->footer)
! {
! insn = bb->end;
! NEXT_INSN (insn) = bb->rbi->footer;
! PREV_INSN (bb->rbi->footer) = insn;
! while (NEXT_INSN (insn))
! insn = NEXT_INSN (insn);
! NEXT_INSN (insn) = next;
! if (next)
! PREV_INSN (next) = insn;
! else
! set_last_insn (insn);
! }
}
if (bb->next_bb != EXIT_BLOCK_PTR)
to = &bb->next_bb->rbi->header;
*************** cfg_layout_delete_block (bb)
*** 2445,2450 ****
--- 2504,2638 ----
}
}
+ /* Merge block A and B, abort when it is not possible. */
+ static void
+ cfg_layout_merge_blocks (a, b)
+ basic_block a;
+ basic_block b;
+ {
+ #ifdef ENABLE_CHECKING
+ if (!cfg_layout_can_merge_blocks_p (a, b))
+ abort ();
+ #endif
+
+ /* If there was a CODE_LABEL beginning B, delete it. */
+ if (GET_CODE (b->head) == CODE_LABEL)
+ delete_insn (b->head);
+
+ /* We should have fallthru edge in a, or we can do dummy redirection to get
+ it cleaned up. */
+ if (GET_CODE (a->end) == JUMP_INSN)
+ redirect_edge_and_branch (a->succ, b);
+ if (GET_CODE (a->end) == JUMP_INSN)
+ abort ();
+
+ /* Possible line number notes should appear in between. */
+ if (b->rbi->header)
+ {
+ rtx first = a->end, last;
+
+ last = emit_insn_after (b->rbi->header, a->end);
+ delete_insn_chain (NEXT_INSN (first), last);
+ b->rbi->header = NULL;
+ }
+
+ /* In the case basic blocks are not adjacent, move them around. */
+ if (NEXT_INSN (a->end) != b->head)
+ {
+ rtx first = unlink_insn_chain (b->head, b->end);
+
+ emit_insn_after (first, a->end);
+ /* Skip possible DELETED_LABEL insn. */
+ if (!NOTE_INSN_BASIC_BLOCK_P (first))
+ first = NEXT_INSN (first);
+ if (!NOTE_INSN_BASIC_BLOCK_P (first))
+ abort ();
+ b->head = NULL;
+ delete_insn (first);
+ }
+ /* Otherwise just re-associate the instructions. */
+ else
+ {
+ rtx insn;
+
+ for (insn = b->head; insn != NEXT_INSN (b->end); insn = NEXT_INSN (insn))
+ set_block_for_insn (insn, a);
+ insn = b->head;
+ /* Skip possible DELETED_LABEL insn. */
+ if (!NOTE_INSN_BASIC_BLOCK_P (insn))
+ insn = NEXT_INSN (insn);
+ if (!NOTE_INSN_BASIC_BLOCK_P (insn))
+ abort ();
+ b->head = NULL;
+ a->end = b->end;
+ delete_insn (insn);
+ }
+
+ /* Possible tablejumps and barriers should appear after the block. */
+ if (b->rbi->footer)
+ {
+ if (!a->rbi->footer)
+ a->rbi->footer = b->rbi->footer;
+ else
+ {
+ rtx last = a->rbi->footer;
+
+ while (NEXT_INSN (last))
+ last = NEXT_INSN (last);
+ NEXT_INSN (last) = b->rbi->footer;
+ PREV_INSN (b->rbi->footer) = last;
+ }
+ b->rbi->footer = NULL;
+ }
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Merged blocks %d and %d.\n",
+ a->index, b->index);
+
+ update_cfg_after_block_merging (a, b);
+ }
+
+ /* return true when blocks A and B can be safely merged. */
+ static bool
+ cfg_layout_can_merge_blocks_p (a, b)
+ basic_block a;
+ basic_block b;
+ {
+ /* There must be exactly one edge in between the blocks. */
+ return (a->succ && !a->succ->succ_next && a->succ->dest == b
+ && !b->pred->pred_next && a != b
+ /* Must be simple edge. */
+ && !(a->succ->flags & EDGE_COMPLEX)
+ && a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
+ /* If the jump insn has side effects,
+ we can't kill the edge. */
+ && (GET_CODE (a->end) != JUMP_INSN
+ || (flow2_completed
+ ? simplejump_p (a->end) : onlyjump_p (a->end))));
+ }
+
+ /* Split edge E. */
+ static basic_block
+ cfg_layout_split_edge (e)
+ edge e;
+ {
+ edge new_e;
+ basic_block new_bb =
+ create_basic_block (e->src != ENTRY_BLOCK_PTR
+ ? NEXT_INSN (e->src-> end) : get_insns (),
+ NULL_RTX, e->src);
+
+ new_bb->count = e->count;
+ new_bb->frequency = EDGE_FREQUENCY (e);
+
+ new_e = make_edge (new_bb, e->dest, EDGE_FALLTHRU);
+ new_e->probability = REG_BR_PROB_BASE;
+ new_e->count = e->count;
+ redirect_edge_and_branch_force (e, new_bb);
+
+ return new_bb;
+ }
+
/* Implementation of CFG manipulation for linearized RTL. */
struct cfg_hooks rtl_cfg_hooks = {
rtl_verify_flow_info,
*************** struct cfg_hooks rtl_cfg_hooks = {
*** 2454,2460 ****
rtl_redirect_edge_and_branch_force,
rtl_delete_block,
rtl_split_block,
! rtl_can_merge_blocks, /* can_merge_blocks_p */
rtl_merge_blocks,
rtl_split_edge
};
--- 2642,2648 ----
rtl_redirect_edge_and_branch_force,
rtl_delete_block,
rtl_split_block,
! rtl_can_merge_blocks,
rtl_merge_blocks,
rtl_split_edge
};
*************** struct cfg_hooks rtl_cfg_hooks = {
*** 2464,2477 ****
This representation will hopefully become the default one in future
version of the compiler. */
struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
! rtl_verify_flow_info_1, /* verify_flow_info. */
rtl_dump_bb,
cfg_layout_create_basic_block,
cfg_layout_redirect_edge_and_branch,
cfg_layout_redirect_edge_and_branch_force,
cfg_layout_delete_block,
cfg_layout_split_block,
! NULL, /* can_merge_blocks_p */
! NULL, /* merge_blocks */
! NULL /* split_edge. */
};
--- 2652,2665 ----
This representation will hopefully become the default one in future
version of the compiler. */
struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
! rtl_verify_flow_info_1,
rtl_dump_bb,
cfg_layout_create_basic_block,
cfg_layout_redirect_edge_and_branch,
cfg_layout_redirect_edge_and_branch_force,
cfg_layout_delete_block,
cfg_layout_split_block,
! cfg_layout_can_merge_blocks_p,
! cfg_layout_merge_blocks,
! cfg_layout_split_edge
};
*** cfganal.c.old3 Tue Jun 17 21:35:29 2003
--- cfganal.c Tue Jun 17 21:36:42 2003
*************** can_fallthru (src, target)
*** 110,121 ****
basic_block src, target;
{
rtx insn = src->end;
! rtx insn2 = target->head;
if (src->next_bb != target)
return 0;
! if (!active_insn_p (insn2))
insn2 = next_active_insn (insn2);
/* ??? Later we may add code to move jump tables offline. */
--- 110,121 ----
basic_block src, target;
{
rtx insn = src->end;
! rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : target->head;
if (src->next_bb != target)
return 0;
! if (insn2 && !active_insn_p (insn2))
insn2 = next_active_insn (insn2);
/* ??? Later we may add code to move jump tables offline. */
*** cfglayout.c.old3 Tue Jun 17 18:12:58 2003
--- cfglayout.c Tue Jun 17 23:21:17 2003
*************** fixup_reorder_chain ()
*** 770,775 ****
--- 769,784 ----
}
prev_bb->next_bb = EXIT_BLOCK_PTR;
EXIT_BLOCK_PTR->prev_bb = prev_bb;
+
+ /* Anoying special case - jump around dead jumptables left in the code. */
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+ for (e = bb->succ; e && !(e->flags & EDGE_FALLTHRU); e = e->succ_next)
+ continue;
+ if (e && !can_fallthru (e->src, e->dest))
+ force_nonfallthru (e);
+ }
}
/* Perform sanity checks on the insn chain.
*** cfglayout.c.old3 Tue Jun 17 18:12:58 2003
--- cfglayout.c Wed Jun 18 00:59:21 2003
*************** extern struct obstack flow_obstack;
*** 43,49 ****
alloc_pool cfg_layout_pool;
/* Holds the interesting trailing notes for the function. */
! rtx cfg_layout_function_footer;
static rtx skip_insns_after_block PARAMS ((basic_block));
static void record_effective_endpoints PARAMS ((void));
--- 43,49 ----
alloc_pool cfg_layout_pool;
/* Holds the interesting trailing notes for the function. */
! rtx cfg_layout_function_footer, cfg_layout_function_header;
static rtx skip_insns_after_block PARAMS ((basic_block));
static void record_effective_endpoints PARAMS ((void));
*************** label_for_bb (bb)
*** 196,204 ****
static void
record_effective_endpoints ()
{
! rtx next_insn = get_insns ();
basic_block bb;
FOR_EACH_BB (bb)
{
rtx end;
--- 195,222 ----
static void
record_effective_endpoints ()
{
! rtx next_insn;
basic_block bb;
+ rtx insn;
+
+ for (insn = get_insns ();
+ NEXT_INSN (insn) && GET_CODE (insn) == NOTE;
+ insn = NEXT_INSN (insn))
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+ {
+ insn = NULL;
+ break;
+ }
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+ break;
+ }
+ if (insn)
+ cfg_layout_function_header = unlink_insn_chain (get_insns (), insn);
+ else
+ cfg_layout_function_header = NULL_RTX;
+ next_insn = get_insns ();
FOR_EACH_BB (bb)
{
rtx end;
*************** fixup_reorder_chain ()
*** 544,549 ****
--- 562,575 ----
int index;
rtx insn = NULL;
+ if (cfg_layout_function_header)
+ {
+ set_first_insn (cfg_layout_function_header);
+ insn = cfg_layout_function_header;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
+
/* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */
*************** fixup_reorder_chain ()
*** 770,775 ****
--- 796,811 ----
}
prev_bb->next_bb = EXIT_BLOCK_PTR;
EXIT_BLOCK_PTR->prev_bb = prev_bb;
+
+ /* Anoying special case - jump around dead jumptables left in the code. */
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+ for (e = bb->succ; e && !(e->flags & EDGE_FALLTHRU); e = e->succ_next)
+ continue;
+ if (e && !can_fallthru (e->src, e->dest))
+ force_nonfallthru (e);
+ }
}
/* Perform sanity checks on the insn chain.