diff options
Diffstat (limited to 'gcc/cfglayout.c')
-rw-r--r-- | gcc/cfglayout.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 9fc05fea854..d599b36e70a 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -828,10 +828,8 @@ fixup_reorder_chain (void) : label_for_bb (e_fall->dest)), 0)) { e_fall->flags &= ~EDGE_FALLTHRU; -#ifdef ENABLE_CHECKING - gcc_assert (could_fall_through - (e_taken->src, e_taken->dest)); -#endif + gcc_checking_assert (could_fall_through + (e_taken->src, e_taken->dest)); e_taken->flags |= EDGE_FALLTHRU; update_br_prob_note (bb); e = e_fall, e_fall = e_taken, e_taken = e; @@ -852,10 +850,8 @@ fixup_reorder_chain (void) : label_for_bb (e_fall->dest)), 0)) { e_fall->flags &= ~EDGE_FALLTHRU; -#ifdef ENABLE_CHECKING - gcc_assert (could_fall_through - (e_taken->src, e_taken->dest)); -#endif + gcc_checking_assert (could_fall_through + (e_taken->src, e_taken->dest)); e_taken->flags |= EDGE_FALLTHRU; update_br_prob_note (bb); continue; @@ -944,7 +940,9 @@ fixup_reorder_chain (void) FOR_EACH_EDGE (e, ei, bb->succs) if (e->goto_locus && !(e->flags & EDGE_ABNORMAL)) { - basic_block nb; + edge e2; + edge_iterator ei2; + basic_block dest, nb; rtx end; insn = BB_END (e->src); @@ -961,10 +959,17 @@ fixup_reorder_chain (void) INSN_LOCATOR (BB_END (e->src)) = e->goto_locus; continue; } - if (e->dest != EXIT_BLOCK_PTR) + dest = e->dest; + if (dest == EXIT_BLOCK_PTR) { - insn = BB_HEAD (e->dest); - end = NEXT_INSN (BB_END (e->dest)); + /* Non-fallthru edges to the exit block cannot be split. */ + if (!(e->flags & EDGE_FALLTHRU)) + continue; + } + else + { + insn = BB_HEAD (dest); + end = NEXT_INSN (BB_END (dest)); while (insn != end && !NONDEBUG_INSN_P (insn)) insn = NEXT_INSN (insn); if (insn != end && INSN_LOCATOR (insn) @@ -976,6 +981,18 @@ fixup_reorder_chain (void) BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb), nb); INSN_LOCATOR (BB_END (nb)) = e->goto_locus; + + /* If there are other incoming edges to the destination block + with the same goto locus, redirect them to the new block as + well, this can prevent other such blocks from being created + in subsequent iterations of the loop. */ + for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); ) + if (e2->goto_locus + && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU)) + && locator_eq (e->goto_locus, e2->goto_locus)) + redirect_edge_and_branch (e2, nb); + else + ei_next (&ei2); } } } |