static void commit_one_edge_insertion (edge, int);
static rtx last_loop_beg_note (rtx);
static bool back_edge_of_syntactic_loop_p (basic_block, basic_block);
-basic_block force_nonfallthru_and_redirect (edge, basic_block);
static basic_block rtl_split_edge (edge);
static bool rtl_move_block_after (basic_block, basic_block);
static int rtl_verify_flow_info (void);
basic_block new_bb;
rtx insn = insnp;
edge e;
+ edge_iterator ei;
if (!insn)
{
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)
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,
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
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;
rtx target_label = block_label (target);
rtx barrier, label, table;
- emit_jump_insn_after (gen_jump (target_label), insn);
+ emit_jump_insn_after_noloc (gen_jump (target_label), insn);
JUMP_LABEL (BB_END (src)) = target_label;
LABEL_NUSES (target_label)++;
if (dump_file)
}
/* 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
/* Like force_nonfallthru below, but additionally performs redirection
Used by redirect_edge_and_branch_force. */
-basic_block
+static basic_block
force_nonfallthru_and_redirect (edge e, basic_block target)
{
basic_block jump_block, new_bb = NULL, src = e->src;
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_unordered_remove (edge, ENTRY_BLOCK_PTR->succs, ei.index);
+ found = true;
+ break;
+ }
+ else
+ ei_next (&ei);
+ }
+
+ gcc_assert (found);
+
+ VEC_safe_push (edge, bb->succs, 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. */
}
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)));
if (target == EXIT_BLOCK_PTR)
{
#ifdef HAVE_return
- emit_jump_insn_after (gen_return (), BB_END (jump_block));
+ emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
#else
gcc_unreachable ();
#endif
else
{
rtx label = block_label (target);
- emit_jump_insn_after (gen_jump (label), BB_END (jump_block));
+ emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
JUMP_LABEL (BB_END (jump_block)) = label;
LABEL_NUSES (label)++;
}
{
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
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
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;
regset_head killed_head;
regset killed = INITIALIZE_REG_SET (killed_head);
rtx save_regs = NULL_RTX;
- int regno, noccmode;
+ unsigned regno;
+ int noccmode;
enum machine_mode mode;
+ reg_set_iterator rsi;
#ifdef AVOID_CCMODE_COPIES
noccmode = true;
for (x = insn; x; x = NEXT_INSN (x))
if (INSN_P (x))
note_stores (PATTERN (x), mark_killed_regs, killed);
- bitmap_operation (killed, killed, e->dest->global_live_at_start,
- BITMAP_AND);
+ bitmap_and_into (killed, e->dest->global_live_at_start);
- EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno,
+ EXECUTE_IF_SET_IN_REG_SET (killed, 0, regno, rsi)
{
mode = regno < FIRST_PSEUDO_REGISTER
? reg_raw_mode[regno]
gen_reg_rtx (mode),
gen_raw_REG (mode, regno)),
save_regs);
- });
+ }
if (save_regs)
{
/* 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)))
{
{
/* 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;
/* 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;
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)
if (before)
{
- emit_insn_before (insns, before);
+ emit_insn_before_noloc (insns, before);
last = prev_nonnote_insn (before);
}
else
- last = emit_insn_after (insns, after);
+ last = emit_insn_after_noloc (insns, after);
if (returnjump_p (last))
{
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);
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)
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)
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)
+ if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability
+ && profile_status != PROFILE_ABSENT)
{
error ("verify_flow_info: REG_BR_PROB does not match cfg %wi %i",
INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
err = 1;
}
}
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
if (e->flags & EDGE_FALLTHRU)
{
if ((e->flags & ~(EDGE_DFS_BACK
| EDGE_CAN_FALLTHRU
| EDGE_IRREDUCIBLE_LOOP
- | EDGE_LOOP_EXIT)) == 0)
+ | EDGE_LOOP_EXIT
+ | EDGE_CROSSING)) == 0)
n_branch++;
if (e->flags & EDGE_ABNORMAL_CALL)
}
for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
- if (BLOCK_FOR_INSN (x) != bb)
+ /* We may have a barrier inside a basic block before dead code
+ elimination. There is no BLOCK_FOR_INSN field in a barrier. */
+ if (!BARRIER_P (x) && BLOCK_FOR_INSN (x) != bb)
{
debug_rtx (x);
if (! BLOCK_FOR_INSN (x))
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)
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)
}
/* 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;
{
rtx note;
edge b,f;
+ edge_iterator ei;
/* We do care only about conditional jumps and simplejumps. */
if (!any_condjump_p (insn)
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. */
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;
}
remove_edge (e);
}
- if (!bb->succ || !purged)
+ if (EDGE_COUNT (bb->succs) == 0 || !purged)
return purged;
if (dump_file)
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
{
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;
}
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",
}
/* 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)))
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. */
/* 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. */
{
rtx first = BB_END (a), last;
- last = emit_insn_after (b->rbi->header, BB_END (a));
+ last = emit_insn_after_noloc (b->rbi->header, BB_END (a));
delete_insn_chain (NEXT_INSN (first), last);
b->rbi->header = NULL;
}
{
rtx first = unlink_insn_chain (BB_HEAD (b), BB_END (b));
- emit_insn_after (first, BB_END (a));
+ emit_insn_after_noloc (first, BB_END (a));
/* Skip possible DELETED_LABEL insn. */
if (!NOTE_INSN_BASIC_BLOCK_P (first))
first = NEXT_INSN (first);
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);
#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