/* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
#include "tm.h"
#include "rtl.h"
#include "hard-reg-set.h"
-#include "basic-block.h"
+#include "regs.h"
#include "timevar.h"
#include "output.h"
#include "insn-config.h"
#include "params.h"
#include "tm_p.h"
#include "target.h"
-#include "regs.h"
#include "cfglayout.h"
#include "emit-rtl.h"
rtx cbranch_insn;
/* Verify that there are exactly two successors. */
- if (!cbranch_block->succ
- || !cbranch_block->succ->succ_next
- || cbranch_block->succ->succ_next->succ_next)
+ if (EDGE_COUNT (cbranch_block->succs) != 2)
return false;
/* Verify that we've got a normal conditional branch at the end
be the last block in the function, and must contain just the
unconditional jump. */
jump_block = cbranch_fallthru_edge->dest;
- if (jump_block->pred->pred_next
+ if (!single_pred_p (jump_block)
|| jump_block->next_bb == EXIT_BLOCK_PTR
|| !FORWARDER_BLOCK_P (jump_block))
return false;
- jump_dest_block = jump_block->succ->dest;
+ jump_dest_block = single_succ (jump_block);
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
- || (cbranch_jump_edge->flags & EDGE_CROSSING)))
+ if (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block)
+ || (cbranch_jump_edge->flags & EDGE_CROSSING))
return false;
/* The conditional branch must target the block after the
rtx set1, set2, cond1, cond2, insn;
enum rtx_code code1, code2, reversed_code2;
bool reverse1 = false;
- int i;
+ unsigned i;
regset nonequal;
bool failed = false;
+ reg_set_iterator rsi;
if (BB_FLAGS (b) & BB_NONTHREADABLE_BLOCK)
return NULL;
/* At the moment, we do handle only conditional jumps, but later we may
want to extend this code to tablejumps and others. */
- if (!e->src->succ->succ_next || e->src->succ->succ_next->succ_next)
+ if (EDGE_COUNT (e->src->succs) != 2)
return NULL;
- if (!b->succ || !b->succ->succ_next || b->succ->succ_next->succ_next)
+ if (EDGE_COUNT (b->succs) != 2)
{
BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
return NULL;
cselib_init (false);
/* First process all values computed in the source basic block. */
- for (insn = NEXT_INSN (BB_HEAD (e->src)); insn != NEXT_INSN (BB_END (e->src));
+ for (insn = NEXT_INSN (BB_HEAD (e->src));
+ insn != NEXT_INSN (BB_END (e->src));
insn = NEXT_INSN (insn))
if (INSN_P (insn))
cselib_process_insn (insn);
- nonequal = BITMAP_XMALLOC();
+ nonequal = BITMAP_ALLOC (NULL);
CLEAR_REG_SET (nonequal);
/* Now assume that we've continued by the edge E to B and continue
processing as if it were same basic block.
Our goal is to prove that whole block is an NOOP. */
- for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b)) && !failed;
+ for (insn = NEXT_INSN (BB_HEAD (b));
+ insn != NEXT_INSN (BB_END (b)) && !failed;
insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
if (GET_CODE (pat) == PARALLEL)
{
- for (i = 0; i < XVECLEN (pat, 0); i++)
+ for (i = 0; i < (unsigned)XVECLEN (pat, 0); i++)
failed |= mark_effect (XVECEXP (pat, 0, i), nonequal);
}
else
if (mode & CLEANUP_UPDATE_LIFE)
AND_REG_SET (nonequal, b->global_live_at_end);
- EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, goto failed_exit;);
+ EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi)
+ goto failed_exit;
- BITMAP_XFREE (nonequal);
+ BITMAP_FREE (nonequal);
cselib_finish ();
if ((comparison_dominates_p (code1, code2) != 0)
!= (XEXP (SET_SRC (set2), 1) == pc_rtx))
return FALLTHRU_EDGE (b);
failed_exit:
- BITMAP_XFREE (nonequal);
+ BITMAP_FREE (nonequal);
cselib_finish ();
return NULL;
}
try_forward_edges (int mode, basic_block b)
{
bool changed = false;
- edge e, next, *threaded_edges = NULL;
+ edge_iterator ei;
+ edge e, *threaded_edges = NULL;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
+ if (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
return false;
- for (e = b->succ; e; e = next)
+ for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
{
basic_block target, first;
int counter;
int nthreaded_edges = 0;
bool may_thread = first_pass | (b->flags & BB_DIRTY);
- next = e->succ_next;
-
/* Skip complex edges because we don't know how to update them.
Still handle fallthru edges, as we can succeed to forward fallthru
edge to the same place as the branch edge of conditional branch
and turn conditional branch to an unconditional branch. */
if (e->flags & EDGE_COMPLEX)
- continue;
+ {
+ ei_next (&ei);
+ continue;
+ }
target = first = e->dest;
counter = 0;
bb-reorder.c:partition_hot_cold_basic_blocks for complete
details. */
- if (flag_reorder_blocks_and_partition
- && first != EXIT_BLOCK_PTR
+ if (first != EXIT_BLOCK_PTR
&& find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX))
return false;
may_thread |= target->flags & BB_DIRTY;
if (FORWARDER_BLOCK_P (target)
- && !(target->succ->flags & EDGE_CROSSING)
- && target->succ->dest != EXIT_BLOCK_PTR)
+ && !(single_succ_edge (target)->flags & EDGE_CROSSING)
+ && single_succ (target) != EXIT_BLOCK_PTR)
{
/* Bypass trivial infinite loops. */
- if (target == target->succ->dest)
+ new_target = single_succ (target);
+ if (target == new_target)
counter = n_basic_blocks;
- new_target = target->succ->dest;
}
/* Allow to thread only over one edge at time to simplify updating
if (t->dest == b)
break;
- if (nthreaded_edges >= n_basic_blocks)
- abort ();
+ gcc_assert (nthreaded_edges < n_basic_blocks);
threaded_edges[nthreaded_edges++] = t;
new_target = t->dest;
For fallthru forwarders, the LOOP_BEG note must appear between
the header of block and CODE_LABEL of the loop, for non forwarders
it must appear before the JUMP_INSN. */
- if ((mode & CLEANUP_PRE_LOOP) && optimize)
+ if ((mode & CLEANUP_PRE_LOOP) && optimize && flag_loop_optimize)
{
- rtx insn = (target->succ->flags & EDGE_FALLTHRU
+ rtx insn = (EDGE_SUCC (target, 0)->flags & EDGE_FALLTHRU
? BB_HEAD (target) : prev_nonnote_insn (BB_END (target)));
if (!NOTE_P (insn))
fprintf (dump_file,
"Forwarding edge %i->%i to %i failed.\n",
b->index, e->dest->index, target->index);
+ ei_next (&ei);
continue;
}
{
edge t;
- first->count -= edge_count;
- if (first->count < 0)
- first->count = 0;
- first->frequency -= edge_frequency;
- if (first->frequency < 0)
- first->frequency = 0;
- if (first->succ->succ_next)
+ if (!single_succ_p (first))
{
- edge e;
- int prob;
- if (n >= nthreaded_edges)
- abort ();
+ gcc_assert (n < nthreaded_edges);
t = threaded_edges [n++];
- if (t->src != first)
- abort ();
- if (first->frequency)
- prob = edge_frequency * REG_BR_PROB_BASE / first->frequency;
- else
- prob = 0;
- if (prob > t->probability)
- prob = t->probability;
- t->probability -= prob;
- prob = REG_BR_PROB_BASE - prob;
- if (prob <= 0)
- {
- first->succ->probability = REG_BR_PROB_BASE;
- first->succ->succ_next->probability = 0;
- }
- else
- for (e = first->succ; e; e = e->succ_next)
- e->probability = ((e->probability * REG_BR_PROB_BASE)
- / (double) prob);
+ gcc_assert (t->src == first);
+ update_bb_profile_for_threading (first, edge_frequency,
+ edge_count, t);
update_br_prob_note (first);
}
else
{
+ first->count -= edge_count;
+ if (first->count < 0)
+ first->count = 0;
+ first->frequency -= edge_frequency;
+ if (first->frequency < 0)
+ first->frequency = 0;
/* It is possible that as the result of
threading we've removed edge as it is
threaded to the fallthru edge. Avoid
if (n < nthreaded_edges
&& first == threaded_edges [n]->src)
n++;
- t = first->succ;
+ t = single_succ_edge (first);
}
t->count -= edge_count;
while (first != target);
changed = true;
+ continue;
}
+ ei_next (&ei);
}
if (threaded_edges)
merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b)
{
rtx barrier;
+ bool only_notes;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && (BB_PARTITION (a) != BB_PARTITION (b)
- || find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)))
+ if (BB_PARTITION (a) != BB_PARTITION (b))
return;
barrier = next_nonnote_insn (BB_END (a));
- if (!BARRIER_P (barrier))
- abort ();
+ gcc_assert (BARRIER_P (barrier));
delete_insn (barrier);
/* Move block and loop notes out of the chain so that we do not
and adjust the block trees appropriately. Even better would be to have
a tighter connection between block trees and rtl so that this is not
necessary. */
- if (squeeze_notes (&BB_HEAD (a), &BB_END (a)))
- abort ();
+ only_notes = squeeze_notes (&BB_HEAD (a), &BB_END (a));
+ gcc_assert (!only_notes);
/* Scramble the insn chain. */
if (BB_END (a) != PREV_INSN (BB_HEAD (b)))
{
rtx barrier, real_b_end;
rtx label, table;
+ bool only_notes;
/* If we are partitioning hot/cold basic blocks, we don't want to
mess up unconditional or indirect jumps that cross between hot
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && (find_reg_note (BB_END (a), REG_CROSSING_JUMP, NULL_RTX)
- || BB_PARTITION (a) != BB_PARTITION (b)))
+ if (BB_PARTITION (a) != BB_PARTITION (b))
return;
real_b_end = BB_END (b);
and adjust the block trees appropriately. Even better would be to have
a tighter connection between block trees and rtl so that this is not
necessary. */
- if (squeeze_notes (&BB_HEAD (b), &BB_END (b)))
- abort ();
+ only_notes = squeeze_notes (&BB_HEAD (b), &BB_END (b));
+ gcc_assert (!only_notes);
+
/* Scramble the insn chain. */
reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a));
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
- || find_reg_note (BB_END (c), REG_CROSSING_JUMP, NULL_RTX)
- || BB_PARTITION (b) != BB_PARTITION (c)))
+ if (BB_PARTITION (b) != BB_PARTITION (c))
return NULL;
edge tmp_edge, b_fallthru_edge;
bool c_has_outgoing_fallthru;
bool b_has_incoming_fallthru;
+ edge_iterator ei;
/* Avoid overactive code motion, as the forwarder blocks should be
eliminated by edge redirection instead. One exception might have
and loop notes. This is done by squeezing out all the notes
and leaving them there to lie. Not ideal, but functional. */
- for (tmp_edge = c->succ; tmp_edge; tmp_edge = tmp_edge->succ_next)
+ FOR_EACH_EDGE (tmp_edge, ei, c->succs)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
c_has_outgoing_fallthru = (tmp_edge != NULL);
- for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
+ FOR_EACH_EDGE (tmp_edge, ei, b->preds)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
MEM_ATTRS (x) = 0;
else
{
+ rtx mem_size;
+
if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
{
set_mem_alias_set (x, 0);
set_mem_offset (x, 0);
set_mem_offset (y, 0);
}
-
- set_mem_size (x, GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
- INTVAL (MEM_SIZE (y)))));
- set_mem_size (y, MEM_SIZE (x));
+
+ if (!MEM_SIZE (x))
+ mem_size = NULL_RTX;
+ else if (!MEM_SIZE (y))
+ mem_size = NULL_RTX;
+ else
+ mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)),
+ INTVAL (MEM_SIZE (y))));
+ set_mem_size (x, mem_size);
+ set_mem_size (y, mem_size);
set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y)));
set_mem_align (y, MEM_ALIGN (x));
int nehedges1 = 0, nehedges2 = 0;
edge fallthru1 = 0, fallthru2 = 0;
edge e1, e2;
+ edge_iterator ei;
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
- if (bb1->succ && !bb1->succ->succ_next
- && (bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ if (single_succ_p (bb1)
+ && (single_succ_edge (bb1)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
&& (!JUMP_P (BB_END (bb1)) || simplejump_p (BB_END (bb1))))
- return (bb2->succ && !bb2->succ->succ_next
- && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ return (single_succ_p (bb2)
+ && (single_succ_edge (bb2)->flags
+ & (EDGE_COMPLEX | EDGE_FAKE)) == 0
&& (!JUMP_P (BB_END (bb2)) || simplejump_p (BB_END (bb2))));
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */
- if (bb1->succ
- && bb1->succ->succ_next
- && !bb1->succ->succ_next->succ_next
+ if (EDGE_COUNT (bb1->succs) == 2
&& any_condjump_p (BB_END (bb1))
&& onlyjump_p (BB_END (bb1)))
{
rtx set1, set2, cond1, cond2;
enum rtx_code code1, code2;
- if (!bb2->succ
- || !bb2->succ->succ_next
- || bb2->succ->succ_next->succ_next
+ if (EDGE_COUNT (bb2->succs) != 2
|| !any_condjump_p (BB_END (bb2))
|| !onlyjump_p (BB_END (bb2)))
return false;
/* Get around possible forwarders on fallthru edges. Other cases
should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest))
- f1 = f1->dest->succ;
+ f1 = single_succ_edge (f1->dest);
if (FORWARDER_BLOCK_P (f2->dest))
- f2 = f2->dest->succ;
+ f2 = single_succ_edge (f2->dest);
/* To simplify use of this function, return false if there are
unneeded forwarder blocks. These will get eliminated later
{
if (dump_file)
fprintf (dump_file,
- "Outcomes of branch in bb %i and %i differs to much (%i %i)\n",
+ "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
bb1->index, bb2->index, b1->probability, prob2);
return false;
/* Generic case - we are seeing a computed jump, table jump or trapping
instruction. */
-#ifndef CASE_DROPS_THROUGH
/* Check whether there are tablejumps in the end of BB1 and BB2.
Return true if they are identical. */
{
return false;
}
}
-#endif
/* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper. */
/* Search the outgoing edges, ensure that the counts do match, find possible
fallthru and exception handling edges since these needs more
validation. */
- for (e1 = bb1->succ, e2 = bb2->succ; e1 && e2;
- e1 = e1->succ_next, e2 = e2->succ_next)
+ if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
+ return false;
+
+ FOR_EACH_EDGE (e1, ei, bb1->succs)
{
+ e2 = EDGE_SUCC (bb2, ei.index);
+
if (e1->flags & EDGE_EH)
nehedges1++;
}
/* If number of edges of various types does not match, fail. */
- if (e1 || e2
- || nehedges1 != nehedges2
+ if (nehedges1 != nehedges2
|| (fallthru1 != 0) != (fallthru2 != 0))
return false;
if (fallthru1)
{
basic_block d1 = (forwarder_block_p (fallthru1->dest)
- ? fallthru1->dest->succ->dest: fallthru1->dest);
+ ? single_succ (fallthru1->dest): fallthru1->dest);
basic_block d2 = (forwarder_block_p (fallthru2->dest)
- ? fallthru2->dest->succ->dest: fallthru2->dest);
+ ? single_succ (fallthru2->dest): fallthru2->dest);
if (d1 != d2)
return false;
basic_block redirect_to, redirect_from, to_remove;
rtx newpos1, newpos2;
edge s;
+ edge_iterator ei;
newpos1 = newpos2 = NULL_RTX;
about multiple entry or chained forwarders, as they will be optimized
away. We do this to look past the unconditional jump following a
conditional jump that is required due to the current CFG shape. */
- if (src1->pred
- && !src1->pred->pred_next
+ if (single_pred_p (src1)
&& FORWARDER_BLOCK_P (src1))
- e1 = src1->pred, src1 = e1->src;
+ e1 = single_pred_edge (src1), src1 = e1->src;
- if (src2->pred
- && !src2->pred->pred_next
+ if (single_pred_p (src2)
&& FORWARDER_BLOCK_P (src2))
- e2 = src2->pred, src2 = e2->src;
+ e2 = single_pred_edge (src2), src2 = e2->src;
/* Nothing to do if we reach ENTRY, or a common source block. */
if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR)
/* Seeing more than 1 forwarder blocks would confuse us later... */
if (FORWARDER_BLOCK_P (e1->dest)
- && FORWARDER_BLOCK_P (e1->dest->succ->dest))
+ && FORWARDER_BLOCK_P (single_succ (e1->dest)))
return false;
if (FORWARDER_BLOCK_P (e2->dest)
- && FORWARDER_BLOCK_P (e2->dest->succ->dest))
+ && FORWARDER_BLOCK_P (single_succ (e2->dest)))
return false;
/* Likewise with dead code (possibly newly created by the other optimizations
of cfg_cleanup). */
- if (!src1->pred || !src2->pred)
+ if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0)
return false;
/* Look for the common insn sequence, part the first ... */
&& (newpos1 != BB_HEAD (src1)))
return false;
-#ifndef CASE_DROPS_THROUGH
/* Here we know that the insns in the end of SRC1 which are common with SRC2
will be deleted.
If we have tablejumps in the end of SRC1 and SRC2
}
}
}
-#endif
/* Avoid splitting if possible. */
if (newpos2 == BB_HEAD (src2))
redirect_to->flags |= BB_DIRTY;
/* Recompute the frequencies and counts of outgoing edges. */
- for (s = redirect_to->succ; s; s = s->succ_next)
+ FOR_EACH_EDGE (s, ei, redirect_to->succs)
{
edge s2;
+ edge_iterator ei;
basic_block d = s->dest;
if (FORWARDER_BLOCK_P (d))
- d = d->succ->dest;
+ d = single_succ (d);
- for (s2 = src1->succ; ; s2 = s2->succ_next)
+ FOR_EACH_EDGE (s2, ei, src1->succs)
{
basic_block d2 = s2->dest;
if (FORWARDER_BLOCK_P (d2))
- d2 = d2->succ->dest;
+ d2 = single_succ (d2);
if (d == d2)
break;
}
into infinite loop. */
if (FORWARDER_BLOCK_P (s->dest))
{
- s->dest->succ->count += s2->count;
+ single_succ_edge (s->dest)->count += s2->count;
s->dest->count += s2->count;
s->dest->frequency += EDGE_FREQUENCY (s);
}
if (FORWARDER_BLOCK_P (s2->dest))
{
- s2->dest->succ->count -= s2->count;
- if (s2->dest->succ->count < 0)
- s2->dest->succ->count = 0;
+ single_succ_edge (s2->dest)->count -= s2->count;
+ if (single_succ_edge (s2->dest)->count < 0)
+ single_succ_edge (s2->dest)->count = 0;
s2->dest->count -= s2->count;
s2->dest->frequency -= EDGE_FREQUENCY (s);
if (s2->dest->frequency < 0)
newpos1 = NEXT_INSN (newpos1);
redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
- to_remove = redirect_from->succ->dest;
+ to_remove = single_succ (redirect_from);
- redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
+ redirect_edge_and_branch_force (single_succ_edge (redirect_from), redirect_to);
delete_basic_block (to_remove);
update_forwarder_flag (redirect_from);
static bool
try_crossjump_bb (int mode, basic_block bb)
{
- edge e, e2, nexte2, nexte, fallthru;
+ edge e, e2, fallthru;
bool changed;
- int n = 0, max;
+ unsigned max, ix, ix2;
+ basic_block ev, ev2;
+ edge_iterator ei;
/* Nothing to do if there is not at least two incoming edges. */
- if (!bb->pred || !bb->pred->pred_next)
+ if (EDGE_COUNT (bb->preds) < 2)
+ return false;
+
+ /* Don't crossjump if this block ends in a computed jump,
+ unless we are optimizing for size. */
+ if (!optimize_size
+ && bb != EXIT_BLOCK_PTR
+ && computed_jump_p (BB_END (bb)))
return false;
/* If we are partitioning hot/cold basic blocks, we don't want to
partition boundaries). See the comments at the top of
bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */
- if (flag_reorder_blocks_and_partition
- && (BB_PARTITION (bb->pred->src) != BB_PARTITION (bb->pred->pred_next->src)
- || (bb->pred->flags & EDGE_CROSSING)))
+ if (BB_PARTITION (EDGE_PRED (bb, 0)->src) !=
+ BB_PARTITION (EDGE_PRED (bb, 1)->src)
+ || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING))
return false;
/* It is always cheapest to redirect a block that ends in a branch to
program. We'll try that combination first. */
fallthru = NULL;
max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES);
- for (e = bb->pred; e ; e = e->pred_next, n++)
+
+ if (EDGE_COUNT (bb->preds) > max)
+ return false;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & EDGE_FALLTHRU)
- fallthru = e;
- if (n > max)
- return false;
+ fallthru = e;
}
changed = false;
- for (e = bb->pred; e; e = nexte)
+ for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); )
{
- nexte = e->pred_next;
+ e = EDGE_PRED (ev, ix);
+ ix++;
/* As noted above, first try with the fallthru predecessor. */
if (fallthru)
if (try_crossjump_to_edge (mode, e, fallthru))
{
changed = true;
- nexte = bb->pred;
+ ix = 0;
+ ev = bb;
continue;
}
}
can eliminate redundant checks of crossjump(A,B) by arbitrarily
choosing to do the check from the block for which the edge
in question is the first successor of A. */
- if (e->src->succ != e)
+ if (EDGE_SUCC (e->src, 0) != e)
continue;
- for (e2 = bb->pred; e2; e2 = nexte2)
+ for (ix2 = 0, ev2 = bb; ix2 < EDGE_COUNT (ev2->preds); )
{
- nexte2 = e2->pred_next;
+ e2 = EDGE_PRED (ev2, ix2);
+ ix2++;
if (e2 == e)
continue;
if (try_crossjump_to_edge (mode, e, e2))
{
changed = true;
- nexte = bb->pred;
+ ev2 = bb;
+ ix = 0;
break;
}
}
bool changed_here = false;
/* Delete trivially dead basic blocks. */
- while (b->pred == NULL)
+ while (EDGE_COUNT (b->preds) == 0)
{
c = b->prev_bb;
if (dump_file)
}
/* Remove code labels no longer used. */
- if (b->pred->pred_next == NULL
- && (b->pred->flags & EDGE_FALLTHRU)
- && !(b->pred->flags & EDGE_COMPLEX)
+ if (single_pred_p (b)
+ && (single_pred_edge (b)->flags & EDGE_FALLTHRU)
+ && !(single_pred_edge (b)->flags & EDGE_COMPLEX)
&& LABEL_P (BB_HEAD (b))
/* If the previous block ends with a branch to this
block, we can't delete the label. Normally this
if CASE_DROPS_THRU, this can be a tablejump with
some element going to the same place as the
default (fallthru). */
- && (b->pred->src == ENTRY_BLOCK_PTR
- || !JUMP_P (BB_END (b->pred->src))
+ && (single_pred (b) == ENTRY_BLOCK_PTR
+ || !JUMP_P (BB_END (single_pred (b)))
|| ! label_is_jump_target_p (BB_HEAD (b),
- BB_END (b->pred->src))))
+ BB_END (single_pred (b)))))
{
rtx label = BB_HEAD (b);
/* If we fall through an empty block, we can remove it. */
if (!(mode & CLEANUP_CFGLAYOUT)
- && b->pred->pred_next == NULL
- && (b->pred->flags & EDGE_FALLTHRU)
+ && single_pred_p (b)
+ && (single_pred_edge (b)->flags & EDGE_FALLTHRU)
&& !LABEL_P (BB_HEAD (b))
&& FORWARDER_BLOCK_P (b)
/* Note that forwarder_block_p true ensures that
there is a successor for this block. */
- && (b->succ->flags & EDGE_FALLTHRU)
+ && (single_succ_edge (b)->flags & EDGE_FALLTHRU)
&& n_basic_blocks > 1)
{
if (dump_file)
b->index);
c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
- redirect_edge_succ_nodup (b->pred, b->succ->dest);
+ redirect_edge_succ_nodup (single_pred_edge (b),
+ single_succ (b));
delete_basic_block (b);
changed = true;
b = c;
}
- if ((s = b->succ) != NULL
- && s->succ_next == NULL
+ if (single_succ_p (b)
+ && (s = single_succ_edge (b))
&& !(s->flags & EDGE_COMPLEX)
&& (c = s->dest) != EXIT_BLOCK_PTR
- && c->pred->pred_next == NULL
+ && single_pred_p (c)
&& b != c)
{
/* When not in cfg_layout mode use code aware of reordering
non-trivial jump instruction without side-effects, we
can either delete the jump entirely, or replace it
with a simple unconditional jump. */
- if (b->succ
- && ! b->succ->succ_next
- && b->succ->dest != EXIT_BLOCK_PTR
+ if (single_succ_p (b)
+ && single_succ (b) != EXIT_BLOCK_PTR
&& onlyjump_p (BB_END (b))
&& !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)
- && try_redirect_by_replacing_jump (b->succ, b->succ->dest,
+ && try_redirect_by_replacing_jump (single_succ_edge (b),
+ single_succ (b),
(mode & CLEANUP_CFGLAYOUT) != 0))
{
update_forwarder_flag (b);
for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; )
{
- if (bb->succ
- && !bb->succ->succ_next
- && can_merge_blocks_p (bb, bb->succ->dest))
+ if (single_succ_p (bb)
+ && can_merge_blocks_p (bb, single_succ (bb)))
{
/* Merge the blocks and retry. */
- merge_blocks (bb, bb->succ->dest);
+ merge_blocks (bb, single_succ (bb));
changed = true;
continue;
}