flow.c (redirect_edge_and_branch_force): New.
* flow.c (redirect_edge_and_branch_force): New. (can_fallthru): Ensure that basic blocks are succeeding. (try_optimize_cfg): Do not delete basic block if it is the last one. * flow.c (try_redirect_by_replacing_jump): Do not remove jumps with side effects, unlink chain on fallthru edge; set block for new jump instruction; avoid basic block to over by line number note. * flow.c (try_simplify_condjump): Verify that the condjump is not always falling trought. Re-install patch: * flow.c (try_redirect_by_replacing_jump): Remove cc0 setter. * flow.c (forwarder_block_p): Fix for fallthru blocks. (try_redirect_by_replacing_jump): Update properly the count and frequency information. From-SVN: r43867
This commit is contained in:
parent
823e3574e6
commit
2b2c8b3e19
@ -1,3 +1,24 @@
|
||||
Mon Jul 9 17:23:10 CEST 2001 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* flow.c (redirect_edge_and_branch_force): New.
|
||||
(can_fallthru): Ensure that basic blocks are succeeding.
|
||||
(try_optimize_cfg): Do not delete basic block if it is the last one.
|
||||
|
||||
* flow.c (try_redirect_by_replacing_jump): Do not remove
|
||||
jumps with side effects, unlink chain on fallthru edge;
|
||||
set block for new jump instruction; avoid basic block to
|
||||
over by line number note.
|
||||
|
||||
* flow.c (try_simplify_condjump): Verify that the condjump
|
||||
is not always falling trought.
|
||||
|
||||
Re-install patch:
|
||||
* flow.c (try_redirect_by_replacing_jump): Remove cc0 setter.
|
||||
|
||||
* flow.c (forwarder_block_p): Fix for fallthru blocks.
|
||||
(try_redirect_by_replacing_jump): Update properly the count
|
||||
and frequency information.
|
||||
|
||||
Mon Jul 9 06:41:07 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* emit-rtl.c (adjust_address, adjust_address_nv): Handle an
|
||||
|
187
gcc/flow.c
187
gcc/flow.c
@ -476,6 +476,7 @@ static int flow_loops_level_compute PARAMS ((struct loops *));
|
||||
static void allocate_bb_life_data PARAMS ((void));
|
||||
static void find_sub_basic_blocks PARAMS ((basic_block));
|
||||
static bool redirect_edge_and_branch PARAMS ((edge, basic_block));
|
||||
static basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
|
||||
static rtx block_label PARAMS ((basic_block));
|
||||
|
||||
/* Find basic blocks of the current function.
|
||||
@ -1619,18 +1620,19 @@ static bool
|
||||
forwarder_block_p (bb)
|
||||
basic_block bb;
|
||||
{
|
||||
rtx insn;
|
||||
rtx insn = bb->head;
|
||||
if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR
|
||||
|| !bb->succ || bb->succ->succ_next)
|
||||
return false;
|
||||
|
||||
insn = next_active_insn (bb->head);
|
||||
if (!insn)
|
||||
return false;
|
||||
if (GET_CODE (insn) == CODE_LABEL
|
||||
|| (GET_CODE (insn) == JUMP_INSN && onlyjump_p (insn)))
|
||||
return true;
|
||||
return false;
|
||||
while (insn != bb->end)
|
||||
{
|
||||
if (active_insn_p (insn))
|
||||
return false;
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
return (!active_insn_p (insn)
|
||||
|| (GET_CODE (insn) == JUMP_INSN && onlyjump_p (insn)));
|
||||
}
|
||||
|
||||
/* Return nonzero if we can reach target from src by falling trought. */
|
||||
@ -1641,7 +1643,7 @@ can_fallthru (src, target)
|
||||
rtx insn = src->end;
|
||||
rtx insn2 = target->head;
|
||||
|
||||
if (!active_insn_p (insn2))
|
||||
if (src->index + 1 == target->index && !active_insn_p (insn2))
|
||||
insn2 = next_active_insn (insn2);
|
||||
/* ??? Later we may add code to move jump tables offline. */
|
||||
return next_active_insn (insn) == insn2;
|
||||
@ -1663,13 +1665,12 @@ try_redirect_by_replacing_jump (e, target)
|
||||
edge tmp;
|
||||
rtx set;
|
||||
int fallthru = 0;
|
||||
rtx barrier;
|
||||
|
||||
/* Verify that all targets will be TARGET. */
|
||||
for (tmp = src->succ; tmp; tmp = tmp->succ_next)
|
||||
if (tmp->dest != target && tmp != e)
|
||||
break;
|
||||
if (tmp || GET_CODE (insn) != JUMP_INSN)
|
||||
if (tmp || !onlyjump_p (insn))
|
||||
return false;
|
||||
|
||||
/* Avoid removing branch with side effects. */
|
||||
@ -1685,7 +1686,11 @@ try_redirect_by_replacing_jump (e, target)
|
||||
fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
|
||||
flow_delete_insn (insn);
|
||||
fallthru = 1;
|
||||
insn = src->end;
|
||||
|
||||
/* Selectivly unlink whole insn chain. */
|
||||
if (src->end != PREV_INSN (target->head))
|
||||
flow_delete_insn_chain (NEXT_INSN (src->end),
|
||||
PREV_INSN (target->head));
|
||||
}
|
||||
/* If this already is simplejump, redirect it. */
|
||||
else if (simplejump_p (insn))
|
||||
@ -1701,16 +1706,21 @@ try_redirect_by_replacing_jump (e, target)
|
||||
else
|
||||
{
|
||||
rtx target_label = block_label (target);
|
||||
rtx barrier;
|
||||
|
||||
src->end = PREV_INSN (insn);
|
||||
src->end = emit_jump_insn_after (gen_jump (target_label), src->end);
|
||||
JUMP_LABEL (src->end) = target_label;
|
||||
LABEL_NUSES (target_label)++;
|
||||
if (basic_block_for_insn)
|
||||
set_block_for_new_insns (src->end, src);
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "Replacing insn %i by jump %i\n",
|
||||
INSN_UID (insn), INSN_UID (src->end));
|
||||
flow_delete_insn (insn);
|
||||
insn = src->end;
|
||||
barrier = next_nonnote_insn (src->end);
|
||||
if (!barrier || GET_CODE (barrier) != BARRIER)
|
||||
emit_barrier_after (src->end);
|
||||
}
|
||||
|
||||
/* Keep only one edge out and set proper flags. */
|
||||
@ -1721,13 +1731,32 @@ try_redirect_by_replacing_jump (e, target)
|
||||
e->flags = EDGE_FALLTHRU;
|
||||
else
|
||||
e->flags = 0;
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
e->count = src->count;
|
||||
|
||||
/* Fixup barriers. */
|
||||
barrier = next_nonnote_insn (insn);
|
||||
if (fallthru && GET_CODE (barrier) == BARRIER)
|
||||
flow_delete_insn (barrier);
|
||||
else if (!fallthru && GET_CODE (barrier) != BARRIER)
|
||||
emit_barrier_after (insn);
|
||||
/* In case we've zapped an conditional jump, we need to kill the cc0
|
||||
setter too if available. */
|
||||
#ifdef HAVE_cc0
|
||||
insn = src->end;
|
||||
if (GET_CODE (insn) == JUMP_INSN)
|
||||
insn = prev_nonnote_insn (insn);
|
||||
if (sets_cc0_p (insn))
|
||||
{
|
||||
if (insn == src->end)
|
||||
src->end = PREV_INSN (insn);
|
||||
flow_delete_insn (insn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We don't want a block to end on a line-number note since that has
|
||||
the potential of changing the code between -g and not -g. */
|
||||
while (GET_CODE (e->src->end) == NOTE
|
||||
&& NOTE_LINE_NUMBER (e->src->end) >= 0)
|
||||
{
|
||||
rtx prev = PREV_INSN (e->src->end);
|
||||
flow_delete_insn (e->src->end);
|
||||
e->src->end = prev;
|
||||
}
|
||||
|
||||
if (e->dest != target)
|
||||
redirect_edge_succ (e, target);
|
||||
@ -1788,7 +1817,7 @@ redirect_edge_and_branch (e, target)
|
||||
for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
|
||||
if (XEXP (RTVEC_ELT (vec, j), 0) == old_label)
|
||||
{
|
||||
RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (VOIDmode, new_label);
|
||||
RTVEC_ELT (vec, j) = gen_rtx_LABEL_REF (Pmode, new_label);
|
||||
--LABEL_NUSES (old_label);
|
||||
++LABEL_NUSES (new_label);
|
||||
}
|
||||
@ -1837,6 +1866,8 @@ redirect_edge_and_branch (e, target)
|
||||
if (s)
|
||||
{
|
||||
s->flags |= e->flags;
|
||||
s->probability += e->probability;
|
||||
s->count += e->count;
|
||||
remove_edge (e);
|
||||
}
|
||||
else
|
||||
@ -1845,6 +1876,117 @@ redirect_edge_and_branch (e, target)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Redirect edge even at the expense of creating new jump insn or
|
||||
basic block. Return new basic block if created, NULL otherwise.
|
||||
Abort if converison is impossible. */
|
||||
static basic_block
|
||||
redirect_edge_and_branch_force (e, target)
|
||||
edge e;
|
||||
basic_block target;
|
||||
{
|
||||
basic_block new_bb;
|
||||
edge new_edge;
|
||||
rtx label;
|
||||
rtx bb_note;
|
||||
int i, j;
|
||||
|
||||
if (redirect_edge_and_branch (e, target))
|
||||
return NULL;
|
||||
if (e->dest == target)
|
||||
return NULL;
|
||||
if (e->flags & EDGE_ABNORMAL)
|
||||
abort ();
|
||||
if (!(e->flags & EDGE_FALLTHRU))
|
||||
abort ();
|
||||
|
||||
e->flags &= ~EDGE_FALLTHRU;
|
||||
label = block_label (target);
|
||||
/* Case of the fallthru block. */
|
||||
if (!e->src->succ->succ_next)
|
||||
{
|
||||
e->src->end = emit_jump_insn_after (gen_jump (label), e->src->end);
|
||||
JUMP_LABEL (e->src->end) = label;
|
||||
LABEL_NUSES (label)++;
|
||||
if (basic_block_for_insn)
|
||||
set_block_for_insn (e->src->end, e->src);
|
||||
emit_barrier_after (e->src->end);
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
"Emitting jump insn %i to redirect edge %i->%i to %i\n",
|
||||
INSN_UID (e->src->end), e->src->index, e->dest->index,
|
||||
target->index);
|
||||
redirect_edge_succ (e, target);
|
||||
return NULL;
|
||||
}
|
||||
/* Redirecting fallthru edge of the conditional needs extra work. */
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
"Emitting jump insn %i in new BB to redirect edge %i->%i to %i\n",
|
||||
INSN_UID (e->src->end), e->src->index, e->dest->index,
|
||||
target->index);
|
||||
|
||||
/* Create the new structures. */
|
||||
new_bb = (basic_block) obstack_alloc (&flow_obstack, sizeof (*new_bb));
|
||||
new_edge = (edge) xcalloc (1, sizeof (*new_edge));
|
||||
n_edges++;
|
||||
|
||||
memset (new_bb, 0, sizeof (*new_bb));
|
||||
|
||||
new_bb->end = new_bb->head = e->src->end;
|
||||
new_bb->succ = NULL;
|
||||
new_bb->pred = new_edge;
|
||||
new_bb->count = e->count;
|
||||
new_bb->frequency = e->probability * e->src->frequency / REG_BR_PROB_BASE;
|
||||
new_bb->loop_depth = e->dest->loop_depth;
|
||||
|
||||
new_edge->flags = EDGE_FALLTHRU;
|
||||
new_edge->probability = e->probability;
|
||||
new_edge->count = e->count;
|
||||
|
||||
/* Wire edge in. */
|
||||
new_edge->src = e->src;
|
||||
new_edge->dest = new_bb;
|
||||
new_edge->succ_next = e->src->succ;
|
||||
e->src->succ = new_edge;
|
||||
new_edge->pred_next = NULL;
|
||||
|
||||
/* Redirect old edge. */
|
||||
redirect_edge_succ (e, target);
|
||||
redirect_edge_pred (e, new_bb);
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
|
||||
/* Place the new block just after the block being split. */
|
||||
VARRAY_GROW (basic_block_info, ++n_basic_blocks);
|
||||
|
||||
/* Some parts of the compiler expect blocks to be number in
|
||||
sequential order so insert the new block immediately after the
|
||||
block being split.. */
|
||||
j = new_edge->src->index;
|
||||
for (i = n_basic_blocks - 1; i > j + 1; --i)
|
||||
{
|
||||
basic_block tmp = BASIC_BLOCK (i - 1);
|
||||
BASIC_BLOCK (i) = tmp;
|
||||
tmp->index = i;
|
||||
}
|
||||
|
||||
BASIC_BLOCK (i) = new_bb;
|
||||
new_bb->index = i;
|
||||
|
||||
/* Create the basic block note. */
|
||||
bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, new_bb->head);
|
||||
NOTE_BASIC_BLOCK (bb_note) = new_bb;
|
||||
new_bb->head = bb_note;
|
||||
|
||||
new_bb->end = emit_jump_insn_after (gen_jump (label), new_bb->head);
|
||||
JUMP_LABEL (new_bb->end) = label;
|
||||
LABEL_NUSES (label)++;
|
||||
if (basic_block_for_insn)
|
||||
set_block_for_insn (new_bb->end, new_bb);
|
||||
emit_barrier_after (new_bb->end);
|
||||
return new_bb;
|
||||
}
|
||||
|
||||
/* Split a (typically critical) edge. Return the new block.
|
||||
Abort on abnormal edges.
|
||||
|
||||
@ -2874,7 +3016,9 @@ try_simplify_condjump (src)
|
||||
rtx insn = src->end;
|
||||
edge branch, fallthru;
|
||||
|
||||
if (!any_condjump_p (insn))
|
||||
/* Verify that there are exactly two successors. */
|
||||
if (!src->succ || !src->succ->succ_next || src->succ->succ_next->succ_next
|
||||
|| !any_condjump_p (insn))
|
||||
return false;
|
||||
|
||||
fallthru = FALLTHRU_EDGE (src);
|
||||
@ -3007,6 +3151,7 @@ try_optimize_cfg ()
|
||||
/* The fallthru forwarder block can be deleted. */
|
||||
if (b->pred->pred_next == NULL
|
||||
&& forwarder_block_p (b)
|
||||
&& n_basic_blocks > 1
|
||||
&& (b->pred->flags & EDGE_FALLTHRU)
|
||||
&& (b->succ->flags & EDGE_FALLTHRU))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user