diff options
Diffstat (limited to 'contrib/gcc/bb-reorder.c')
-rw-r--r-- | contrib/gcc/bb-reorder.c | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/contrib/gcc/bb-reorder.c b/contrib/gcc/bb-reorder.c index b0cc462..857e0fb 100644 --- a/contrib/gcc/bb-reorder.c +++ b/contrib/gcc/bb-reorder.c @@ -89,11 +89,13 @@ #include "flags.h" #include "output.h" #include "cfglayout.h" +#include "function.h" #include "target.h" /* Local function prototypes. */ static void make_reorder_chain PARAMS ((void)); static basic_block make_reorder_chain_1 PARAMS ((basic_block, basic_block)); +static basic_block maybe_duplicate_computed_goto_succ PARAMS ((basic_block)); /* Compute an ordering for a subgraph beginning with block BB. Record the ordering in RBI()->index and chained through RBI()->next. */ @@ -102,14 +104,11 @@ static void make_reorder_chain () { basic_block prev = NULL; - int nbb_m1 = n_basic_blocks - 1; - basic_block next; + basic_block next, bb; /* Loop until we've placed every block. */ do { - int i; - next = NULL; /* Find the next unplaced block. */ @@ -119,19 +118,59 @@ make_reorder_chain () remove from the list as we place. The head of that list is what we're looking for here. */ - for (i = 0; i <= nbb_m1 && !next; ++i) - { - basic_block bb = BASIC_BLOCK (i); - if (! RBI (bb)->visited) + FOR_EACH_BB (bb) + if (! RBI (bb)->visited) + { next = bb; - } + break; + } + if (next) - prev = make_reorder_chain_1 (next, prev); + prev = make_reorder_chain_1 (next, prev); } while (next); RBI (prev)->next = NULL; } +/* If the successor is our artificial computed_jump block, duplicate it. */ + +static inline basic_block +maybe_duplicate_computed_goto_succ (bb) + basic_block bb; +{ + edge e; + basic_block next; + + /* Note that we can't rely on computed_goto_common_label still being in + the instruction stream -- cfgloop.c likes to munge things about. But + we can still use it's non-null-ness to avoid a fruitless search. */ + if (!cfun->computed_goto_common_label) + return NULL; + + /* Only want to duplicate when coming from a simple branch. */ + e = bb->succ; + if (!e || e->succ_next) + return NULL; + + /* Only duplicate if we've already layed out this block once. */ + next = e->dest; + if (!RBI (next)->visited) + return NULL; + + /* See if the block contains only a computed branch. */ + if ((next->head == next->end + || next_active_insn (next->head) == next->end) + && computed_jump_p (next->end)) + { + if (rtl_dump_file) + fprintf (rtl_dump_file, "Duplicating block %d after %d\n", + next->index, bb->index); + return cfg_layout_duplicate_bb (next, e); + } + + return NULL; +} + /* A helper function for make_reorder_chain. We do not follow EH edges, or non-fallthru edges to noreturn blocks. @@ -158,13 +197,13 @@ make_reorder_chain_1 (bb, prev) restart: RBI (prev)->next = bb; - if (rtl_dump_file && prev->index + 1 != bb->index) + if (rtl_dump_file && prev->next_bb != bb) fprintf (rtl_dump_file, "Reordering block %d after %d\n", bb->index, prev->index); } else { - if (bb->index != 0) + if (bb->prev_bb != ENTRY_BLOCK_PTR) abort (); } RBI (bb)->visited = 1; @@ -205,9 +244,13 @@ make_reorder_chain_1 (bb, prev) e_taken = e; } - next = (taken ? e_taken : e_fall)->dest; + next = ((taken && e_taken) ? e_taken : e_fall)->dest; } + /* If the successor is our artificial computed_jump block, duplicate it. */ + else + next = maybe_duplicate_computed_goto_succ (bb); + /* In the absence of a prediction, disturb things as little as possible by selecting the old "next" block from the list of successors. If there had been a fallthru edge, that will be the one. */ @@ -221,7 +264,7 @@ make_reorder_chain_1 (bb, prev) next = e->dest; break; } - else if (e->dest->index == bb->index + 1) + else if (e->dest == bb->next_bb) { if (! (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))) next = e->dest; |