summaryrefslogtreecommitdiff
path: root/gcc/cfglayout.c
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-14 12:09:08 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-14 12:09:08 +0000
commit9bb8a4af63c2dc43b16aad632a9c8c723235d554 (patch)
treea37b5ac1c93cff4befd42e4070615ba42213a250 /gcc/cfglayout.c
parent41d51689c2f60e3a0489e31d6ecb5f2a784fc357 (diff)
downloadgcc-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.c39
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