aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgrtl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cfgrtl.c')
-rw-r--r--gcc/cfgrtl.c258
1 files changed, 163 insertions, 95 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 8664f04..bba6881 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -459,6 +459,7 @@ rtl_split_block (basic_block bb, void *insnp)
basic_block new_bb;
rtx insn = insnp;
edge e;
+ edge_iterator ei;
if (!insn)
{
@@ -482,9 +483,9 @@ rtl_split_block (basic_block bb, void *insnp)
BB_END (bb) = insn;
/* Redirect the outgoing edges. */
- new_bb->succ = bb->succ;
- bb->succ = NULL;
- for (e = new_bb->succ; e; e = e->succ_next)
+ new_bb->succs = bb->succs;
+ bb->succs = NULL;
+ FOR_EACH_EDGE (e, ei, new_bb->succs)
e->src = new_bb;
if (bb->global_live_at_start)
@@ -625,10 +626,12 @@ rtl_can_merge_blocks (basic_block a,basic_block b)
return false;
/* There must be exactly one edge in between the blocks. */
- return (a->succ && !a->succ->succ_next && a->succ->dest == b
- && !b->pred->pred_next && a != b
+ return (EDGE_COUNT (a->succs) == 1
+ && EDGE_SUCC (a, 0)->dest == b
+ && EDGE_COUNT (b->preds) == 1
+ && a != b
/* Must be simple edge. */
- && !(a->succ->flags & EDGE_COMPLEX)
+ && !(EDGE_SUCC (a, 0)->flags & EDGE_COMPLEX)
&& a->next_bb == b
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
@@ -668,7 +671,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
edge tmp;
rtx set;
int fallthru = 0;
-
+ edge_iterator ei;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
@@ -686,7 +689,7 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
return NULL;
/* Verify that all targets will be TARGET. */
- for (tmp = src->succ; tmp; tmp = tmp->succ_next)
+ FOR_EACH_EDGE (tmp, ei, src->succs)
if (tmp->dest != target && tmp != e)
break;
@@ -814,9 +817,10 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
}
/* Keep only one edge out and set proper flags. */
- while (src->succ->succ_next)
- remove_edge (src->succ);
- e = src->succ;
+ while (EDGE_COUNT (src->succs) > 1)
+ remove_edge (e);
+
+ e = EDGE_SUCC (src, 0);
if (fallthru)
e->flags = EDGE_FALLTHRU;
else
@@ -1040,28 +1044,37 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
if (e->src == ENTRY_BLOCK_PTR)
{
/* We can't redirect the entry block. Create an empty block
- at the start of the function which we use to add the new
- jump. */
- edge *pe1;
- basic_block bb
- = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR);
-
+ at the start of the function which we use to add the new
+ jump. */
+ edge tmp;
+ edge_iterator ei;
+ bool found = false;
+
+ basic_block bb = create_basic_block (BB_HEAD (e->dest), NULL, ENTRY_BLOCK_PTR);
+
/* Change the existing edge's source to be the new block, and add
a new edge from the entry block to the new block. */
e->src = bb;
- for (pe1 = &ENTRY_BLOCK_PTR->succ; *pe1; pe1 = &(*pe1)->succ_next)
- if (*pe1 == e)
- {
- *pe1 = e->succ_next;
- break;
- }
- e->succ_next = 0;
- bb->succ = e;
+ for (ei = ei_start (ENTRY_BLOCK_PTR->succs); (tmp = ei_safe_edge (ei)); )
+ {
+ if (tmp == e)
+ {
+ VEC_ordered_remove (edge, ENTRY_BLOCK_PTR->succs, ei.index);
+ found = true;
+ break;
+ }
+ else
+ ei_next (&ei);
+ }
+
+ gcc_assert (found);
+
+ VEC_safe_insert (edge, bb->succs, 0, e);
make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
}
}
- if (e->src->succ->succ_next || abnormal_edge_flags)
+ if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags)
{
/* Create the new structures. */
@@ -1113,7 +1126,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
}
if (JUMP_P (BB_END (jump_block))
&& !any_condjump_p (BB_END (jump_block))
- && (jump_block->succ->flags & EDGE_CROSSING))
+ && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING))
REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST
(REG_CROSSING_JUMP, NULL_RTX,
REG_NOTES (BB_END (jump_block)));
@@ -1193,6 +1206,12 @@ rtl_tidy_fallthru_edge (edge e)
{
rtx q;
basic_block b = e->src, c = b->next_bb;
+ edge e2;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e2, ei, b->succs)
+ if (e == e2)
+ break;
/* ??? In a late-running flow pass, other folks may have deleted basic
blocks by nopping out blocks, leaving multiple BARRIERs between here
@@ -1215,7 +1234,7 @@ rtl_tidy_fallthru_edge (edge e)
if (JUMP_P (q)
&& onlyjump_p (q)
&& (any_uncondjump_p (q)
- || (b->succ == e && e->succ_next == NULL)))
+ || (EDGE_SUCC (b, 0) == e && ei.index == EDGE_COUNT (b->succs) - 1)))
{
#ifdef HAVE_cc0
/* If this was a conditional jump, we need to also delete
@@ -1303,8 +1322,9 @@ rtl_split_edge (edge edge_in)
if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{
edge e;
+ edge_iterator ei;
- for (e = edge_in->dest->pred; e; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, edge_in->dest->preds)
if (e->flags & EDGE_FALLTHRU)
break;
@@ -1518,7 +1538,8 @@ commit_one_edge_insertion (edge e, int watch_calls)
/* Special case -- avoid inserting code between call and storing
its return value. */
- if (watch_calls && (e->flags & EDGE_FALLTHRU) && !e->dest->pred->pred_next
+ if (watch_calls && (e->flags & EDGE_FALLTHRU)
+ && EDGE_COUNT (e->dest->preds) == 1
&& e->src != ENTRY_BLOCK_PTR
&& CALL_P (BB_END (e->src)))
{
@@ -1538,7 +1559,7 @@ commit_one_edge_insertion (edge e, int watch_calls)
{
/* Figure out where to put these things. If the destination has
one predecessor, insert there. Except for the exit block. */
- if (e->dest->pred->pred_next == NULL && e->dest != EXIT_BLOCK_PTR)
+ if (EDGE_COUNT (e->dest->preds) == 1 && e->dest != EXIT_BLOCK_PTR)
{
bb = e->dest;
@@ -1564,7 +1585,7 @@ commit_one_edge_insertion (edge e, int watch_calls)
/* If the source has one successor and the edge is not abnormal,
insert there. Except for the entry block. */
else if ((e->flags & EDGE_ABNORMAL) == 0
- && e->src->succ->succ_next == NULL
+ && EDGE_COUNT (e->src->succs) == 1
&& e->src != ENTRY_BLOCK_PTR)
{
bb = e->src;
@@ -1619,7 +1640,7 @@ commit_one_edge_insertion (edge e, int watch_calls)
NOTE_BASIC_BLOCK (new_note) = bb;
if (JUMP_P (BB_END (bb))
&& !any_condjump_p (BB_END (bb))
- && (bb->succ->flags & EDGE_CROSSING))
+ && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST
(REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb)));
if (after == bb_note)
@@ -1645,9 +1666,9 @@ commit_one_edge_insertion (edge e, int watch_calls)
for the (single) epilogue, which already has a fallthru edge
to EXIT. */
- e = bb->succ;
+ e = EDGE_SUCC (bb, 0);
gcc_assert (e->dest == EXIT_BLOCK_PTR
- && !e->succ_next && (e->flags & EDGE_FALLTHRU));
+ && EDGE_COUNT (bb->succs) == 1 && (e->flags & EDGE_FALLTHRU));
e->flags &= ~EDGE_FALLTHRU;
emit_barrier_after (last);
@@ -1677,17 +1698,15 @@ commit_edge_insertions (void)
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- edge e, next;
+ edge e;
+ edge_iterator ei;
- for (e = bb->succ; e; e = next)
- {
- next = e->succ_next;
- if (e->insns.r)
- {
- changed = true;
- commit_one_edge_insertion (e, false);
- }
- }
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->insns.r)
+ {
+ changed = true;
+ commit_one_edge_insertion (e, false);
+ }
}
if (!changed)
@@ -1724,17 +1743,15 @@ commit_edge_insertions_watch_calls (void)
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- edge e, next;
+ edge e;
+ edge_iterator ei;
- for (e = bb->succ; e; e = next)
- {
- next = e->succ_next;
- if (e->insns.r)
- {
- changed = true;
- commit_one_edge_insertion (e, true);
- }
- }
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->insns.r)
+ {
+ changed = true;
+ commit_one_edge_insertion (e, true);
+ }
}
if (!changed)
@@ -1963,10 +1980,11 @@ rtl_verify_flow_info_1 (void)
int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0;
edge e, fallthru = NULL;
rtx note;
+ edge_iterator ei;
if (INSN_P (BB_END (bb))
&& (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX))
- && bb->succ && bb->succ->succ_next
+ && EDGE_COUNT (bb->succs) >= 2
&& any_condjump_p (BB_END (bb)))
{
if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability
@@ -1977,7 +1995,7 @@ rtl_verify_flow_info_1 (void)
err = 1;
}
}
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
if (e->flags & EDGE_FALLTHRU)
{
@@ -2144,7 +2162,9 @@ rtl_verify_flow_info (void)
FOR_EACH_BB_REVERSE (bb)
{
edge e;
- for (e = bb->succ; e; e = e->succ_next)
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_FALLTHRU)
break;
if (!e)
@@ -2258,9 +2278,11 @@ rtl_verify_flow_info (void)
bool
purge_dead_edges (basic_block bb)
{
- edge e, next;
+ edge e;
rtx insn = BB_END (bb), note;
bool purged = false;
+ bool found;
+ edge_iterator ei;
/* If this instruction cannot trap, remove REG_EH_REGION notes. */
if (NONJUMP_INSN_P (insn)
@@ -2275,23 +2297,31 @@ purge_dead_edges (basic_block bb)
}
/* Cleanup abnormal edges caused by exceptions or non-local gotos. */
- for (e = bb->succ; e; e = next)
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
- next = e->succ_next;
if (e->flags & EDGE_EH)
{
if (can_throw_internal (BB_END (bb)))
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
}
else if (e->flags & EDGE_ABNORMAL_CALL)
{
if (CALL_P (BB_END (bb))
&& (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
|| INTVAL (XEXP (note, 0)) >= 0))
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
}
else
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
remove_edge (e);
bb->flags |= BB_DIRTY;
@@ -2302,6 +2332,7 @@ purge_dead_edges (basic_block bb)
{
rtx note;
edge b,f;
+ edge_iterator ei;
/* We do care only about conditional jumps and simplejumps. */
if (!any_condjump_p (insn)
@@ -2320,10 +2351,8 @@ purge_dead_edges (basic_block bb)
remove_note (insn, note);
}
- for (e = bb->succ; e; e = next)
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
- next = e->succ_next;
-
/* Avoid abnormal flags to leak from computed jumps turned
into simplejumps. */
@@ -2333,22 +2362,32 @@ purge_dead_edges (basic_block bb)
if ((e->flags & EDGE_FALLTHRU) && any_condjump_p (insn))
/* A conditional jump can fall through into the next
block, so we should keep the edge. */
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
else if (e->dest != EXIT_BLOCK_PTR
&& BB_HEAD (e->dest) == JUMP_LABEL (insn))
/* If the destination block is the target of the jump,
keep the edge. */
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
else if (e->dest == EXIT_BLOCK_PTR && returnjump_p (insn))
/* If the destination block is the exit block, and this
instruction is a return, then keep the edge. */
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
/* Keep the edges that correspond to exceptions thrown by
this instruction and rematerialize the EDGE_ABNORMAL
flag we just cleared above. */
{
e->flags |= EDGE_ABNORMAL;
+ ei_next (&ei);
continue;
}
@@ -2358,7 +2397,7 @@ purge_dead_edges (basic_block bb)
remove_edge (e);
}
- if (!bb->succ || !purged)
+ if (EDGE_COUNT (bb->succs) == 0 || !purged)
return purged;
if (dump_file)
@@ -2368,10 +2407,10 @@ purge_dead_edges (basic_block bb)
return purged;
/* Redistribute probabilities. */
- if (!bb->succ->succ_next)
+ if (EDGE_COUNT (bb->succs) == 1)
{
- bb->succ->probability = REG_BR_PROB_BASE;
- bb->succ->count = bb->count;
+ EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (bb, 0)->count = bb->count;
}
else
{
@@ -2395,8 +2434,8 @@ purge_dead_edges (basic_block bb)
from non-local gotos and the like. If there were, we shouldn't
have created the sibcall in the first place. Second, there
should of course never have been a fallthru edge. */
- gcc_assert (bb->succ && !bb->succ->succ_next);
- gcc_assert (bb->succ->flags == (EDGE_SIBCALL | EDGE_ABNORMAL));
+ gcc_assert (EDGE_COUNT (bb->succs) == 1);
+ gcc_assert (EDGE_SUCC (bb, 0)->flags == (EDGE_SIBCALL | EDGE_ABNORMAL));
return 0;
}
@@ -2406,28 +2445,33 @@ purge_dead_edges (basic_block bb)
as these are only created by conditional branches. If we find such an
edge we know that there used to be a jump here and can then safely
remove all non-fallthru edges. */
- for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU));
- e = e->succ_next)
- ;
+ found = false;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (! (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU)))
+ {
+ found = true;
+ break;
+ }
- if (!e)
+ if (!found)
return purged;
- for (e = bb->succ; e; e = next)
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
- next = e->succ_next;
if (!(e->flags & EDGE_FALLTHRU))
{
bb->flags |= BB_DIRTY;
remove_edge (e);
purged = true;
}
+ else
+ ei_next (&ei);
}
- gcc_assert (bb->succ && !bb->succ->succ_next);
+ gcc_assert (EDGE_COUNT (bb->succs) == 1);
- bb->succ->probability = REG_BR_PROB_BASE;
- bb->succ->count = bb->count;
+ EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (bb, 0)->count = bb->count;
if (dump_file)
fprintf (dump_file, "Purged non-fallthru edges from bb %i\n",
@@ -2543,10 +2587,28 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
}
/* In case we are redirecting fallthru edge to the branch edge
of conditional jump, remove it. */
- if (src->succ->succ_next
- && !src->succ->succ_next->succ_next)
+ if (EDGE_COUNT (src->succs) == 2)
{
- edge s = e->succ_next ? e->succ_next : src->succ;
+ bool found = false;
+ unsigned ix = 0;
+ edge tmp, s;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (tmp, ei, src->succs)
+ if (e == tmp)
+ {
+ found = true;
+ ix = ei.index;
+ break;
+ }
+
+ gcc_assert (found);
+
+ if (EDGE_COUNT (src->succs) > (ix + 1))
+ s = EDGE_SUCC (src, ix + 1);
+ else
+ s = EDGE_SUCC (src, 0);
+
if (s->dest == dest
&& any_condjump_p (BB_END (src))
&& onlyjump_p (BB_END (src)))
@@ -2680,10 +2742,12 @@ cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
return false;
/* There must be exactly one edge in between the blocks. */
- return (a->succ && !a->succ->succ_next && a->succ->dest == b
- && !b->pred->pred_next && a != b
+ return (EDGE_COUNT (a->succs) == 1
+ && EDGE_SUCC (a, 0)->dest == b
+ && EDGE_COUNT (b->preds) == 1
+ && a != b
/* Must be simple edge. */
- && !(a->succ->flags & EDGE_COMPLEX)
+ && !(EDGE_SUCC (a, 0)->flags & EDGE_COMPLEX)
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
we can't kill the edge. */
@@ -2707,7 +2771,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
/* We should have fallthru edge in a, or we can do dummy redirection to get
it cleaned up. */
if (JUMP_P (BB_END (a)))
- try_redirect_by_replacing_jump (a->succ, b, true);
+ try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
gcc_assert (!JUMP_P (BB_END (a)));
/* Possible line number notes should appear in between. */
@@ -2906,8 +2970,9 @@ rtl_flow_call_edges_add (sbitmap blocks)
if (need_fake_edge_p (insn))
{
edge e;
+ edge_iterator ei;
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest == EXIT_BLOCK_PTR)
{
insert_insn_on_edge (gen_rtx_USE (VOIDmode, const0_rtx), e);
@@ -2955,8 +3020,11 @@ rtl_flow_call_edges_add (sbitmap blocks)
#ifdef ENABLE_CHECKING
if (split_at_insn == BB_END (bb))
- for (e = bb->succ; e; e = e->succ_next)
- gcc_assert (e->dest != EXIT_BLOCK_PTR);
+ {
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ gcc_assert (e->dest != EXIT_BLOCK_PTR);
+ }
#endif
/* Note that the following may create a new basic block