/* 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"
be the last block in the function, and must contain just the
unconditional jump. */
jump_block = cbranch_fallthru_edge->dest;
- if (EDGE_COUNT (jump_block->preds) >= 2
+ if (!single_pred_p (jump_block)
|| jump_block->next_bb == EXIT_BLOCK_PTR
|| !FORWARDER_BLOCK_P (jump_block))
return false;
- jump_dest_block = EDGE_SUCC (jump_block, 0)->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;
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
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;
}
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 (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
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)
- && !(EDGE_SUCC (target, 0)->flags & EDGE_CROSSING)
- && EDGE_SUCC (target, 0)->dest != EXIT_BLOCK_PTR)
+ && !(single_succ_edge (target)->flags & EDGE_CROSSING)
+ && single_succ (target) != EXIT_BLOCK_PTR)
{
/* Bypass trivial infinite loops. */
- if (target == EDGE_SUCC (target, 0)->dest)
+ new_target = single_succ (target);
+ if (target == new_target)
counter = n_basic_blocks;
- new_target = EDGE_SUCC (target, 0)->dest;
}
/* Allow to thread only over one edge at time to simplify updating
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 = (EDGE_SUCC (target, 0)->flags & EDGE_FALLTHRU
? BB_HEAD (target) : prev_nonnote_insn (BB_END (target)));
{
edge t;
- if (EDGE_COUNT (first->succs) > 1)
+ if (!single_succ_p (first))
{
gcc_assert (n < nthreaded_edges);
t = threaded_edges [n++];
if (n < nthreaded_edges
&& first == threaded_edges [n]->src)
n++;
- t = EDGE_SUCC (first, 0);
+ t = single_succ_edge (first);
}
t->count -= edge_count;
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));
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);
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;
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
- if (EDGE_COUNT (bb1->succs) == 1
- && (EDGE_SUCC (bb1, 0)->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 (EDGE_COUNT (bb2->succs) == 1
- && (EDGE_SUCC (bb2, 0)->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
/* Get around possible forwarders on fallthru edges. Other cases
should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest))
- f1 = EDGE_SUCC (f1->dest, 0);
+ f1 = single_succ_edge (f1->dest);
if (FORWARDER_BLOCK_P (f2->dest))
- f2 = EDGE_SUCC (f2->dest, 0);
+ 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 too 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. */
if (fallthru1)
{
basic_block d1 = (forwarder_block_p (fallthru1->dest)
- ? EDGE_SUCC (fallthru1->dest, 0)->dest: fallthru1->dest);
+ ? single_succ (fallthru1->dest): fallthru1->dest);
basic_block d2 = (forwarder_block_p (fallthru2->dest)
- ? EDGE_SUCC (fallthru2->dest, 0)->dest: fallthru2->dest);
+ ? single_succ (fallthru2->dest): fallthru2->dest);
if (d1 != d2)
return false;
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 (EDGE_COUNT (src1->preds) == 1
+ if (single_pred_p (src1)
&& FORWARDER_BLOCK_P (src1))
- e1 = EDGE_PRED (src1, 0), src1 = e1->src;
+ e1 = single_pred_edge (src1), src1 = e1->src;
- if (EDGE_COUNT (src2->preds) == 1
+ if (single_pred_p (src2)
&& FORWARDER_BLOCK_P (src2))
- e2 = EDGE_PRED (src2, 0), 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 (EDGE_SUCC (e1->dest, 0)->dest))
+ && FORWARDER_BLOCK_P (single_succ (e1->dest)))
return false;
if (FORWARDER_BLOCK_P (e2->dest)
- && FORWARDER_BLOCK_P (EDGE_SUCC (e2->dest, 0)->dest))
+ && FORWARDER_BLOCK_P (single_succ (e2->dest)))
return false;
/* Likewise with dead code (possibly newly created by the other optimizations
&& (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))
basic_block d = s->dest;
if (FORWARDER_BLOCK_P (d))
- d = EDGE_SUCC (d, 0)->dest;
+ d = single_succ (d);
FOR_EACH_EDGE (s2, ei, src1->succs)
{
basic_block d2 = s2->dest;
if (FORWARDER_BLOCK_P (d2))
- d2 = EDGE_SUCC (d2, 0)->dest;
+ d2 = single_succ (d2);
if (d == d2)
break;
}
into infinite loop. */
if (FORWARDER_BLOCK_P (s->dest))
{
- EDGE_SUCC (s->dest, 0)->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))
{
- EDGE_SUCC (s2->dest, 0)->count -= s2->count;
- if (EDGE_SUCC (s2->dest, 0)->count < 0)
- EDGE_SUCC (s2->dest, 0)->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 = EDGE_SUCC (redirect_from, 0)->dest;
+ to_remove = single_succ (redirect_from);
- redirect_edge_and_branch_force (EDGE_SUCC (redirect_from, 0), redirect_to);
+ redirect_edge_and_branch_force (single_succ_edge (redirect_from), redirect_to);
delete_basic_block (to_remove);
update_forwarder_flag (redirect_from);
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
mess up unconditional or indirect jumps that cross between hot
and cold sections.
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 (EDGE_PRED (bb, 0)->src) != BB_PARTITION (EDGE_PRED (bb, 1)->src)
- || (EDGE_PRED (bb, 0)->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
}
/* Remove code labels no longer used. */
- if (EDGE_COUNT (b->preds) == 1
- && (EDGE_PRED (b, 0)->flags & EDGE_FALLTHRU)
- && !(EDGE_PRED (b, 0)->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). */
- && (EDGE_PRED (b, 0)->src == ENTRY_BLOCK_PTR
- || !JUMP_P (BB_END (EDGE_PRED (b, 0)->src))
+ && (single_pred (b) == ENTRY_BLOCK_PTR
+ || !JUMP_P (BB_END (single_pred (b)))
|| ! label_is_jump_target_p (BB_HEAD (b),
- BB_END (EDGE_PRED (b, 0)->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)
- && EDGE_COUNT (b->preds) == 1
- && (EDGE_PRED (b, 0)->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. */
- && (EDGE_SUCC (b, 0)->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 (EDGE_PRED (b, 0), EDGE_SUCC (b, 0)->dest);
+ redirect_edge_succ_nodup (single_pred_edge (b),
+ single_succ (b));
delete_basic_block (b);
changed = true;
b = c;
}
- if (EDGE_COUNT (b->succs) == 1
- && (s = EDGE_SUCC (b, 0))
+ if (single_succ_p (b)
+ && (s = single_succ_edge (b))
&& !(s->flags & EDGE_COMPLEX)
&& (c = s->dest) != EXIT_BLOCK_PTR
- && EDGE_COUNT (c->preds) == 1
+ && 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 (EDGE_COUNT (b->succs) == 1
- && EDGE_SUCC (b, 0)->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 (EDGE_SUCC (b, 0), EDGE_SUCC (b, 0)->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 (EDGE_COUNT (bb->succs) == 1
- && can_merge_blocks_p (bb, EDGE_SUCC (bb, 0)->dest))
+ if (single_succ_p (bb)
+ && can_merge_blocks_p (bb, single_succ (bb)))
{
/* Merge the blocks and retry. */
- merge_blocks (bb, EDGE_SUCC (bb, 0)->dest);
+ merge_blocks (bb, single_succ (bb));
changed = true;
continue;
}