diff options
author | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-06-14 12:09:08 +0000 |
---|---|---|
committer | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-06-14 12:09:08 +0000 |
commit | 9bb8a4af63c2dc43b16aad632a9c8c723235d554 (patch) | |
tree | a37b5ac1c93cff4befd42e4070615ba42213a250 /gcc/cfglayout.c | |
parent | 41d51689c2f60e3a0489e31d6ecb5f2a784fc357 (diff) | |
download | gcc-9bb8a4af63c2dc43b16aad632a9c8c723235d554.tar.gz |
* basic-block.h (could_fall_through): Declare.
* cfganal.c (can_fallthru): Succeed if the target is EXIT_BLOCK_PTR.
Fail if the source already has a fallthrough edge to the exit
block pointer.
(could_fall_through): New function.
* cfgbuild.c (make_edges): Check if we already have a fallthrough
edge to the exit block pointer.
* cfglayout.c (fixup_fallthru_exit_predecessor): Check that it is
not called before reload has completed.
Handle special case of first block having a fall-through exit edge.
(cfg_layout_finalize): Don't call it before reload or if we have
rtl epilogues.
(fixup_reorder_chain): A fall through to the exit block does not
require the block to come last. Add sanity checks.
* cfgrtl.c (rtl_split_edge): Add special handling of fall through
edges to the exit block.
* function.c (cfglayout.h): #include.
(thread_prologue_and_epilogue_insns): If we have neither return nor
epilogue, but a fall through to the exit block from mid-function,
force a non-fall-through exit.
* Makefile.in (function.o): Depend on CFGLAYOUT_H.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83089 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfglayout.c')
-rw-r--r-- | gcc/cfglayout.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 899aa1a5665..66742686e16 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -714,6 +714,10 @@ fixup_reorder_chain (void) && invert_jump (bb_end_insn, label_for_bb (e_fall->dest), 0)) { +#ifdef ENABLE_CHECKING + if (!could_fall_through (e_taken->src, e_taken->dest)) + abort (); +#endif e_fall->flags &= ~EDGE_FALLTHRU; e_taken->flags |= EDGE_FALLTHRU; update_br_prob_note (bb); @@ -731,6 +735,10 @@ fixup_reorder_chain (void) else if (invert_jump (bb_end_insn, label_for_bb (e_fall->dest), 0)) { +#ifdef ENABLE_CHECKING + if (!could_fall_through (e_taken->src, e_taken->dest)) + abort (); +#endif e_fall->flags &= ~EDGE_FALLTHRU; e_taken->flags |= EDGE_FALLTHRU; update_br_prob_note (bb); @@ -770,7 +778,7 @@ fixup_reorder_chain (void) continue; /* A fallthru to exit block. */ - if (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR) + if (e_fall->dest == EXIT_BLOCK_PTR) continue; } @@ -910,14 +918,20 @@ verify_insn_chain (void) abort (); } -/* The block falling through to exit must be the last one in the - reordered chain. Ensure that this condition is met. */ +/* If we have assembler epilogues, the block falling through to exit must + be the last one in the reordered chain when we reach final. Ensure + that this condition is met. */ static void fixup_fallthru_exit_predecessor (void) { edge e; basic_block bb = NULL; + /* This transformation is not valid before reload, because we might separate + a call from the instruction that copies the return value. */ + if (! reload_completed) + abort (); + for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) if (e->flags & EDGE_FALLTHRU) bb = e->src; @@ -926,6 +940,18 @@ fixup_fallthru_exit_predecessor (void) { basic_block c = ENTRY_BLOCK_PTR->next_bb; + /* If the very first block is the one with the fall-through exit + edge, we have to split that block. */ + if (c == bb) + { + bb = split_block (bb, NULL)->dest; + initialize_bb_rbi (bb); + bb->rbi->next = c->rbi->next; + c->rbi->next = bb; + bb->rbi->footer = c->rbi->footer; + c->rbi->footer = NULL; + } + while (c->rbi->next != bb) c = c->rbi->next; @@ -1176,7 +1202,12 @@ cfg_layout_finalize (void) verify_flow_info (); #endif rtl_register_cfg_hooks (); - fixup_fallthru_exit_predecessor (); + if (reload_completed +#ifdef HAVE_epilogue + && !HAVE_epilogue +#endif + ) + fixup_fallthru_exit_predecessor (); fixup_reorder_chain (); #ifdef ENABLE_CHECKING |