summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/bb-reorder.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/bb-reorder.c')
-rw-r--r--contrib/gcc/bb-reorder.c71
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;
OpenPOWER on IntegriCloud