summaryrefslogtreecommitdiff
path: root/gcc/cfglayout.c
diff options
context:
space:
mode:
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