Commit 5f0d2358 by Richard Kenner Committed by Richard Kenner

rtl.h (in_expr_list_p): New declaration.

	* rtl.h (in_expr_list_p): New declaration.
	* rtlanal.c (in_expr_list_p): New function.
	* cfgcleanup.c: Reformatting and minor code rearrangement.
	* cfglayout.c, cfgloop.c, cfgrtl.c: Likewise.

From-SVN: r48304
parent e88712b5
Mon Dec 24 10:24:59 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* rtl.h (in_expr_list_p): New declaration.
* rtlanal.c (in_expr_list_p): New function.
* cfgcleanup.c: Reformatting and minor code rearrangement.
* cfglayout.c, cfgloop.c, cfgrtl.c: Likewise.
2001-12-23 Richard Henderson <rth@redhat.com> 2001-12-23 Richard Henderson <rth@redhat.com>
PR c/5163: PR c/5163:
......
...@@ -47,21 +47,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -47,21 +47,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h" #include "obstack.h"
/* cleanup_cfg maintains following flags for each basic block. */ /* cleanup_cfg maintains following flags for each basic block. */
enum bb_flags {
enum bb_flags
{
/* Set if life info needs to be recomputed for given BB. */ /* Set if life info needs to be recomputed for given BB. */
BB_UPDATE_LIFE = 1, BB_UPDATE_LIFE = 1,
/* Set if BB is the forwarder block to avoid too many /* Set if BB is the forwarder block to avoid too many
forwarder_block_p calls. */ forwarder_block_p calls. */
BB_FORWARDER_BLOCK = 2 BB_FORWARDER_BLOCK = 2
}; };
#define BB_FLAGS(bb) (enum bb_flags)(bb)->aux #define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
#define BB_SET_FLAG(bb,flag) \ #define BB_SET_FLAG(BB, FLAG) \
(bb)->aux = (void *) (long) ((enum bb_flags)(bb)->aux | (flag)) (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux | (FLAG))
#define BB_CLEAR_FLAG(bb,flag) \ #define BB_CLEAR_FLAG(BB, FLAG) \
(bb)->aux = (void *) (long) ((enum bb_flags)(bb)->aux & ~(flag)) (BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux & ~(FLAG))
#define FORWARDER_BLOCK_P(bb) (BB_FLAGS(bb) & BB_FORWARDER_BLOCK) #define FORWARDER_BLOCK_P(BB) (BB_FLAGS (BB) & BB_FORWARDER_BLOCK)
static bool try_crossjump_to_edge PARAMS ((int, edge, edge)); static bool try_crossjump_to_edge PARAMS ((int, edge, edge));
static bool try_crossjump_bb PARAMS ((int, basic_block)); static bool try_crossjump_bb PARAMS ((int, basic_block));
...@@ -96,6 +98,7 @@ notice_new_block (bb) ...@@ -96,6 +98,7 @@ notice_new_block (bb)
{ {
if (!bb) if (!bb)
return; return;
BB_SET_FLAG (bb, BB_UPDATE_LIFE); BB_SET_FLAG (bb, BB_UPDATE_LIFE);
if (forwarder_block_p (bb)) if (forwarder_block_p (bb))
BB_SET_FLAG (bb, BB_FORWARDER_BLOCK); BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
...@@ -183,6 +186,7 @@ try_simplify_condjump (cbranch_block) ...@@ -183,6 +186,7 @@ try_simplify_condjump (cbranch_block)
/* Attempt to prove that operation is NOOP using CSElib or mark the effect /* Attempt to prove that operation is NOOP using CSElib or mark the effect
on register. Used by jump threading. */ on register. Used by jump threading. */
static bool static bool
mark_effect (exp, nonequal) mark_effect (exp, nonequal)
rtx exp; rtx exp;
...@@ -196,6 +200,7 @@ mark_effect (exp, nonequal) ...@@ -196,6 +200,7 @@ mark_effect (exp, nonequal)
if (REG_P (XEXP (exp, 0))) if (REG_P (XEXP (exp, 0)))
CLEAR_REGNO_REG_SET (nonequal, REGNO (XEXP (exp, 0))); CLEAR_REGNO_REG_SET (nonequal, REGNO (XEXP (exp, 0)));
return false; return false;
case SET: case SET:
if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp))) if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
return false; return false;
...@@ -203,6 +208,7 @@ mark_effect (exp, nonequal) ...@@ -203,6 +208,7 @@ mark_effect (exp, nonequal)
return true; return true;
SET_REGNO_REG_SET (nonequal, REGNO (SET_SRC (exp))); SET_REGNO_REG_SET (nonequal, REGNO (SET_SRC (exp)));
return false; return false;
default: default:
return false; return false;
} }
...@@ -281,10 +287,11 @@ thread_jump (mode, e, b) ...@@ -281,10 +287,11 @@ thread_jump (mode, e, b)
nonequal = BITMAP_XMALLOC(); nonequal = BITMAP_XMALLOC();
CLEAR_REG_SET (nonequal); CLEAR_REG_SET (nonequal);
/* Now assume that we've continued by the edge E to B and continue /* Now assume that we've continued by the edge E to B and continue
processing as if it were same basic block. processing as if it were same basic block.
Our goal is to prove that whole block is an NOOP. */ Our goal is to prove that whole block is an NOOP. */
for (insn = NEXT_INSN (b->head); insn != b->end && !failed; for (insn = NEXT_INSN (b->head); insn != b->end && !failed;
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
{ {
...@@ -300,6 +307,7 @@ thread_jump (mode, e, b) ...@@ -300,6 +307,7 @@ thread_jump (mode, e, b)
else else
failed |= mark_effect (pat, nonequal); failed |= mark_effect (pat, nonequal);
} }
cselib_process_insn (insn); cselib_process_insn (insn);
} }
...@@ -340,7 +348,7 @@ try_forward_edges (mode, b) ...@@ -340,7 +348,7 @@ try_forward_edges (mode, b)
bool changed = false; bool changed = false;
edge e, next, threaded_edge; edge e, next, threaded_edge;
for (e = b->succ; e ; e = next) for (e = b->succ; e; e = next)
{ {
basic_block target, first; basic_block target, first;
int counter; int counter;
...@@ -372,6 +380,7 @@ try_forward_edges (mode, b) ...@@ -372,6 +380,7 @@ try_forward_edges (mode, b)
counter = n_basic_blocks; counter = n_basic_blocks;
new_target = target->succ->dest; new_target = target->succ->dest;
} }
/* Allow to thread only over one edge at time to simplify updating /* Allow to thread only over one edge at time to simplify updating
of probabilities. */ of probabilities. */
else if ((mode & CLEANUP_THREADING) && !threaded) else if ((mode & CLEANUP_THREADING) && !threaded)
...@@ -383,6 +392,7 @@ try_forward_edges (mode, b) ...@@ -383,6 +392,7 @@ try_forward_edges (mode, b)
new_target_threaded = true; new_target_threaded = true;
} }
} }
if (!new_target) if (!new_target)
break; break;
...@@ -400,7 +410,7 @@ try_forward_edges (mode, b) ...@@ -400,7 +410,7 @@ try_forward_edges (mode, b)
if (GET_CODE (insn) != NOTE) if (GET_CODE (insn) != NOTE)
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
for (;insn && GET_CODE (insn) != CODE_LABEL && !INSN_P (insn); for (; insn && GET_CODE (insn) != CODE_LABEL && !INSN_P (insn);
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
...@@ -409,6 +419,7 @@ try_forward_edges (mode, b) ...@@ -409,6 +419,7 @@ try_forward_edges (mode, b)
if (GET_CODE (insn) == NOTE) if (GET_CODE (insn) == NOTE)
break; break;
} }
counter++; counter++;
target = new_target; target = new_target;
threaded |= new_target_threaded; threaded |= new_target_threaded;
...@@ -438,10 +449,12 @@ try_forward_edges (mode, b) ...@@ -438,10 +449,12 @@ try_forward_edges (mode, b)
else if (!redirect_edge_and_branch (e, target)) else if (!redirect_edge_and_branch (e, target))
{ {
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Forwarding edge %i->%i to %i failed.\n", fprintf (rtl_dump_file,
"Forwarding edge %i->%i to %i failed.\n",
b->index, e->dest->index, target->index); b->index, e->dest->index, target->index);
continue; continue;
} }
/* We successfully forwarded the edge. Now update profile /* We successfully forwarded the edge. Now update profile
data: for each edge we traversed in the chain, remove data: for each edge we traversed in the chain, remove
the original edge's execution count. */ the original edge's execution count. */
...@@ -456,6 +469,7 @@ try_forward_edges (mode, b) ...@@ -456,6 +469,7 @@ try_forward_edges (mode, b)
do do
{ {
edge t; edge t;
first->count -= edge_count; first->count -= edge_count;
first->succ->count -= edge_count; first->succ->count -= edge_count;
first->frequency -= edge_frequency; first->frequency -= edge_frequency;
...@@ -463,6 +477,7 @@ try_forward_edges (mode, b) ...@@ -463,6 +477,7 @@ try_forward_edges (mode, b)
t = threaded_edge; t = threaded_edge;
else else
t = first->succ; t = first->succ;
first = t->dest; first = t->dest;
} }
while (first != target); while (first != target);
...@@ -553,10 +568,8 @@ merge_blocks_move_predecessor_nojumps (a, b) ...@@ -553,10 +568,8 @@ merge_blocks_move_predecessor_nojumps (a, b)
BB_SET_FLAG (a, BB_UPDATE_LIFE); BB_SET_FLAG (a, BB_UPDATE_LIFE);
if (rtl_dump_file) if (rtl_dump_file)
{ fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n", a->index, b->index);
a->index, b->index);
}
/* Swap the records for the two blocks around. Although we are deleting B, /* Swap the records for the two blocks around. Although we are deleting B,
A is now where B was and we want to compact the BB array from where A is now where B was and we want to compact the BB array from where
...@@ -623,10 +636,8 @@ merge_blocks_move_successor_nojumps (a, b) ...@@ -623,10 +636,8 @@ merge_blocks_move_successor_nojumps (a, b)
BB_SET_FLAG (a, BB_UPDATE_LIFE); BB_SET_FLAG (a, BB_UPDATE_LIFE);
if (rtl_dump_file) if (rtl_dump_file)
{ fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n", b->index, a->index);
b->index, a->index);
}
} }
/* Attempt to merge basic blocks that are potentially non-adjacent. /* Attempt to merge basic blocks that are potentially non-adjacent.
...@@ -660,13 +671,12 @@ merge_blocks (e, b, c, mode) ...@@ -660,13 +671,12 @@ merge_blocks (e, b, c, mode)
update_forwarder_flag (b); update_forwarder_flag (b);
if (rtl_dump_file) if (rtl_dump_file)
{ fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
fprintf (rtl_dump_file, "Merged %d and %d without moving.\n", b->index, c->index);
b->index, c->index);
}
return true; return true;
} }
/* Otherwise we will need to move code around. Do that only if expensive /* Otherwise we will need to move code around. Do that only if expensive
transformations are allowed. */ transformations are allowed. */
else if (mode & CLEANUP_EXPENSIVE) else if (mode & CLEANUP_EXPENSIVE)
...@@ -689,11 +699,13 @@ merge_blocks (e, b, c, mode) ...@@ -689,11 +699,13 @@ merge_blocks (e, b, c, mode)
for (tmp_edge = c->succ; tmp_edge; tmp_edge = tmp_edge->succ_next) for (tmp_edge = c->succ; tmp_edge; tmp_edge = tmp_edge->succ_next)
if (tmp_edge->flags & EDGE_FALLTHRU) if (tmp_edge->flags & EDGE_FALLTHRU)
break; break;
c_has_outgoing_fallthru = (tmp_edge != NULL); c_has_outgoing_fallthru = (tmp_edge != NULL);
for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next) for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
if (tmp_edge->flags & EDGE_FALLTHRU) if (tmp_edge->flags & EDGE_FALLTHRU)
break; break;
b_has_incoming_fallthru = (tmp_edge != NULL); b_has_incoming_fallthru = (tmp_edge != NULL);
b_fallthru_edge = tmp_edge; b_fallthru_edge = tmp_edge;
...@@ -714,6 +726,7 @@ merge_blocks (e, b, c, mode) ...@@ -714,6 +726,7 @@ merge_blocks (e, b, c, mode)
if (b_has_incoming_fallthru) if (b_has_incoming_fallthru)
{ {
basic_block bb; basic_block bb;
if (b_fallthru_edge->src == ENTRY_BLOCK_PTR) if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
return false; return false;
bb = force_nonfallthru (b_fallthru_edge); bb = force_nonfallthru (b_fallthru_edge);
...@@ -722,9 +735,11 @@ merge_blocks (e, b, c, mode) ...@@ -722,9 +735,11 @@ merge_blocks (e, b, c, mode)
else else
BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE); BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE);
} }
merge_blocks_move_predecessor_nojumps (b, c); merge_blocks_move_predecessor_nojumps (b, c);
return true; return true;
} }
return false; return false;
} }
...@@ -825,8 +840,10 @@ insns_match_p (mode, i1, i2) ...@@ -825,8 +840,10 @@ insns_match_p (mode, i1, i2)
return true; return true;
} }
} }
return false; return false;
} }
return true; return true;
} }
...@@ -857,6 +874,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2) ...@@ -857,6 +874,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
last1 = i1; last1 = i1;
i1 = PREV_INSN (i1); i1 = PREV_INSN (i1);
} }
i2 = bb2->end; i2 = bb2->end;
if (onlyjump_p (i2) if (onlyjump_p (i2)
|| (returnjump_p (i2) && !side_effects_p (PATTERN (i2)))) || (returnjump_p (i2) && !side_effects_p (PATTERN (i2))))
...@@ -873,6 +891,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2) ...@@ -873,6 +891,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
/* Ignore notes. */ /* Ignore notes. */
while (!active_insn_p (i1) && i1 != bb1->head) while (!active_insn_p (i1) && i1 != bb1->head)
i1 = PREV_INSN (i1); i1 = PREV_INSN (i1);
while (!active_insn_p (i2) && i2 != bb2->head) while (!active_insn_p (i2) && i2 != bb2->head)
i2 = PREV_INSN (i2); i2 = PREV_INSN (i2);
...@@ -905,18 +924,16 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2) ...@@ -905,18 +924,16 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
last1 = i1, last2 = i2; last1 = i1, last2 = i2;
ninsns++; ninsns++;
} }
i1 = PREV_INSN (i1); i1 = PREV_INSN (i1);
i2 = PREV_INSN (i2); i2 = PREV_INSN (i2);
} }
#ifdef HAVE_cc0 #ifdef HAVE_cc0
if (ninsns) /* Don't allow the insn after a compare to be shared by
{ cross-jumping unless the compare is also shared. */
/* Don't allow the insn after a compare to be shared by if (ninsns && reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1))
cross-jumping unless the compare is also shared. */ last1 = afterlast1, last2 = afterlast2, ninsns--;
if (reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1))
last1 = afterlast1, last2 = afterlast2, ninsns--;
}
#endif #endif
/* Include preceding notes and labels in the cross-jump. One, /* Include preceding notes and labels in the cross-jump. One,
...@@ -926,10 +943,13 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2) ...@@ -926,10 +943,13 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
{ {
while (last1 != bb1->head && !active_insn_p (PREV_INSN (last1))) while (last1 != bb1->head && !active_insn_p (PREV_INSN (last1)))
last1 = PREV_INSN (last1); last1 = PREV_INSN (last1);
if (last1 != bb1->head && GET_CODE (PREV_INSN (last1)) == CODE_LABEL) if (last1 != bb1->head && GET_CODE (PREV_INSN (last1)) == CODE_LABEL)
last1 = PREV_INSN (last1); last1 = PREV_INSN (last1);
while (last2 != bb2->head && !active_insn_p (PREV_INSN (last2))) while (last2 != bb2->head && !active_insn_p (PREV_INSN (last2)))
last2 = PREV_INSN (last2); last2 = PREV_INSN (last2);
if (last2 != bb2->head && GET_CODE (PREV_INSN (last2)) == CODE_LABEL) if (last2 != bb2->head && GET_CODE (PREV_INSN (last2)) == CODE_LABEL)
last2 = PREV_INSN (last2); last2 = PREV_INSN (last2);
...@@ -960,12 +980,8 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -960,12 +980,8 @@ outgoing_edges_match (mode, bb1, bb2)
unconditional jump, or a fake edge to exit. */ unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next if (bb1->succ && !bb1->succ->succ_next
&& !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE))) && !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
{ return (bb2->succ && !bb2->succ->succ_next
if (! bb2->succ || bb2->succ->succ_next && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0);
|| (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
return false;
return true;
}
/* Match conditional jumps - this may get tricky when fallthru and branch /* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */ edges are crossed. */
...@@ -996,6 +1012,7 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -996,6 +1012,7 @@ outgoing_edges_match (mode, bb1, bb2)
should be optimized out already. */ should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest)) if (FORWARDER_BLOCK_P (f1->dest))
f1 = f1->dest->succ; f1 = f1->dest->succ;
if (FORWARDER_BLOCK_P (f2->dest)) if (FORWARDER_BLOCK_P (f2->dest))
f2 = f2->dest->succ; f2 = f2->dest->succ;
...@@ -1028,6 +1045,7 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -1028,6 +1045,7 @@ outgoing_edges_match (mode, bb1, bb2)
code2 = reversed_comparison_code (cond2, bb2->end); code2 = reversed_comparison_code (cond2, bb2->end);
else else
code2 = GET_CODE (cond2); code2 = GET_CODE (cond2);
if (code2 == UNKNOWN) if (code2 == UNKNOWN)
return false; return false;
...@@ -1052,6 +1070,7 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -1052,6 +1070,7 @@ outgoing_edges_match (mode, bb1, bb2)
{ {
rtx note1, note2; rtx note1, note2;
int prob1, prob2; int prob1, prob2;
note1 = find_reg_note (bb1->end, REG_BR_PROB, 0); note1 = find_reg_note (bb1->end, REG_BR_PROB, 0);
note2 = find_reg_note (bb2->end, REG_BR_PROB, 0); note2 = find_reg_note (bb2->end, REG_BR_PROB, 0);
...@@ -1067,6 +1086,7 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -1067,6 +1086,7 @@ outgoing_edges_match (mode, bb1, bb2)
if (abs (prob1 - prob2) > REG_BR_PROB_BASE / 20) if (abs (prob1 - prob2) > REG_BR_PROB_BASE / 20)
return false; return false;
} }
else if (note1 || note2) else if (note1 || note2)
return false; return false;
} }
...@@ -1096,19 +1116,20 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -1096,19 +1116,20 @@ outgoing_edges_match (mode, bb1, bb2)
{ {
if (e1->flags & EDGE_EH) if (e1->flags & EDGE_EH)
nehedges1++; nehedges1++;
if (e2->flags & EDGE_EH) if (e2->flags & EDGE_EH)
nehedges2++; nehedges2++;
if (e1->flags & EDGE_FALLTHRU) if (e1->flags & EDGE_FALLTHRU)
fallthru1 = e1; fallthru1 = e1;
if (e2->flags & EDGE_FALLTHRU) if (e2->flags & EDGE_FALLTHRU)
fallthru2 = e2; fallthru2 = e2;
} }
/* If number of edges of various types does not match, fail. */ /* If number of edges of various types does not match, fail. */
if (e1 || e2) if (e1 || e2
return false; || nehedges1 != nehedges2
if (nehedges1 != nehedges2) || (fallthru1 != 0) != (fallthru2 != 0))
return false;
if ((fallthru1 != 0) != (fallthru2 != 0))
return false; return false;
/* fallthru edges must be forwarded to the same destination. */ /* fallthru edges must be forwarded to the same destination. */
...@@ -1118,17 +1139,21 @@ outgoing_edges_match (mode, bb1, bb2) ...@@ -1118,17 +1139,21 @@ outgoing_edges_match (mode, bb1, bb2)
? fallthru1->dest->succ->dest: fallthru1->dest); ? fallthru1->dest->succ->dest: fallthru1->dest);
basic_block d2 = (forwarder_block_p (fallthru2->dest) basic_block d2 = (forwarder_block_p (fallthru2->dest)
? fallthru2->dest->succ->dest: fallthru2->dest); ? fallthru2->dest->succ->dest: fallthru2->dest);
if (d1 != d2) if (d1 != d2)
return false; return false;
} }
/* In case we do have EH edges, ensure we are in the same region. */ /* In case we do have EH edges, ensure we are in the same region. */
if (nehedges1) if (nehedges1)
{ {
rtx n1 = find_reg_note (bb1->end, REG_EH_REGION, 0); rtx n1 = find_reg_note (bb1->end, REG_EH_REGION, 0);
rtx n2 = find_reg_note (bb2->end, REG_EH_REGION, 0); rtx n2 = find_reg_note (bb2->end, REG_EH_REGION, 0);
if (XEXP (n1, 0) != XEXP (n2, 0)) if (XEXP (n1, 0) != XEXP (n2, 0))
return false; return false;
} }
/* We don't need to match the rest of edges as above checks should be enought /* We don't need to match the rest of edges as above checks should be enought
to ensure that they are equivalent. */ to ensure that they are equivalent. */
return true; return true;
...@@ -1159,17 +1184,12 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1159,17 +1184,12 @@ try_crossjump_to_edge (mode, e1, e2)
if (src1->pred if (src1->pred
&& !src1->pred->pred_next && !src1->pred->pred_next
&& FORWARDER_BLOCK_P (src1)) && FORWARDER_BLOCK_P (src1))
{ e1 = src1->pred, src1 = e1->src;
e1 = src1->pred;
src1 = e1->src;
}
if (src2->pred if (src2->pred
&& !src2->pred->pred_next && !src2->pred->pred_next
&& FORWARDER_BLOCK_P (src2)) && FORWARDER_BLOCK_P (src2))
{ e2 = src2->pred, src2 = e2->src;
e2 = src2->pred;
src2 = e2->src;
}
/* Nothing to do if we reach ENTRY, or a common source block. */ /* Nothing to do if we reach ENTRY, or a common source block. */
if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR) if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR)
...@@ -1181,6 +1201,7 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1181,6 +1201,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (FORWARDER_BLOCK_P (e1->dest) if (FORWARDER_BLOCK_P (e1->dest)
&& FORWARDER_BLOCK_P (e1->dest->succ->dest)) && FORWARDER_BLOCK_P (e1->dest->succ->dest))
return false; return false;
if (FORWARDER_BLOCK_P (e2->dest) if (FORWARDER_BLOCK_P (e2->dest)
&& FORWARDER_BLOCK_P (e2->dest->succ->dest)) && FORWARDER_BLOCK_P (e2->dest->succ->dest))
return false; return false;
...@@ -1226,6 +1247,7 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1226,6 +1247,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (FORWARDER_BLOCK_P (d)) if (FORWARDER_BLOCK_P (d))
d = d->succ->dest; d = d->succ->dest;
for (s2 = src1->succ; ; s2 = s2->succ_next) for (s2 = src1->succ; ; s2 = s2->succ_next)
{ {
basic_block d2 = s2->dest; basic_block d2 = s2->dest;
...@@ -1234,6 +1256,7 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1234,6 +1256,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (d == d2) if (d == d2)
break; break;
} }
s->count += s2->count; s->count += s2->count;
/* Take care to update possible forwarder blocks. We verified /* Take care to update possible forwarder blocks. We verified
...@@ -1245,19 +1268,21 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1245,19 +1268,21 @@ try_crossjump_to_edge (mode, e1, e2)
s->dest->count += s2->count; s->dest->count += s2->count;
s->dest->frequency += EDGE_FREQUENCY (s); s->dest->frequency += EDGE_FREQUENCY (s);
} }
if (FORWARDER_BLOCK_P (s2->dest)) if (FORWARDER_BLOCK_P (s2->dest))
{ {
s2->dest->succ->count -= s2->count; s2->dest->succ->count -= s2->count;
s2->dest->count -= s2->count; s2->dest->count -= s2->count;
s2->dest->frequency -= EDGE_FREQUENCY (s); s2->dest->frequency -= EDGE_FREQUENCY (s);
} }
if (!redirect_to->frequency && !src1->frequency) if (!redirect_to->frequency && !src1->frequency)
s->probability = (s->probability + s2->probability) / 2; s->probability = (s->probability + s2->probability) / 2;
else else
s->probability = s->probability
((s->probability * redirect_to->frequency + = ((s->probability * redirect_to->frequency +
s2->probability * src1->frequency) s2->probability * src1->frequency)
/ (redirect_to->frequency + src1->frequency)); / (redirect_to->frequency + src1->frequency));
} }
note = find_reg_note (redirect_to->end, REG_BR_PROB, 0); note = find_reg_note (redirect_to->end, REG_BR_PROB, 0);
...@@ -1269,6 +1294,7 @@ try_crossjump_to_edge (mode, e1, e2) ...@@ -1269,6 +1294,7 @@ try_crossjump_to_edge (mode, e1, e2)
/* Skip possible basic block header. */ /* Skip possible basic block header. */
if (GET_CODE (newpos1) == CODE_LABEL) if (GET_CODE (newpos1) == CODE_LABEL)
newpos1 = NEXT_INSN (newpos1); newpos1 = NEXT_INSN (newpos1);
if (GET_CODE (newpos1) == NOTE) if (GET_CODE (newpos1) == NOTE)
newpos1 = NEXT_INSN (newpos1); newpos1 = NEXT_INSN (newpos1);
last = src1->end; last = src1->end;
...@@ -1409,7 +1435,6 @@ try_optimize_cfg (mode) ...@@ -1409,7 +1435,6 @@ try_optimize_cfg (mode)
/* Attempt to merge blocks as made possible by edge removal. If a block /* Attempt to merge blocks as made possible by edge removal. If a block
has only one successor, and the successor has only one predecessor, has only one successor, and the successor has only one predecessor,
they may be combined. */ they may be combined. */
do do
{ {
changed = false; changed = false;
...@@ -1431,6 +1456,7 @@ try_optimize_cfg (mode) ...@@ -1431,6 +1456,7 @@ try_optimize_cfg (mode)
c = BASIC_BLOCK (b->index - 1); c = BASIC_BLOCK (b->index - 1);
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleting block %i.\n", b->index); fprintf (rtl_dump_file, "Deleting block %i.\n", b->index);
flow_delete_block (b); flow_delete_block (b);
changed = true; changed = true;
b = c; b = c;
...@@ -1455,6 +1481,7 @@ try_optimize_cfg (mode) ...@@ -1455,6 +1481,7 @@ try_optimize_cfg (mode)
|| ! label_is_jump_target_p (b->head, b->pred->src->end))) || ! label_is_jump_target_p (b->head, b->pred->src->end)))
{ {
rtx label = b->head; rtx label = b->head;
b->head = NEXT_INSN (b->head); b->head = NEXT_INSN (b->head);
delete_insn_chain (label, label); delete_insn_chain (label, label);
if (rtl_dump_file) if (rtl_dump_file)
...@@ -1475,6 +1502,7 @@ try_optimize_cfg (mode) ...@@ -1475,6 +1502,7 @@ try_optimize_cfg (mode)
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleting fallthru block %i.\n", fprintf (rtl_dump_file, "Deleting fallthru block %i.\n",
b->index); b->index);
c = BASIC_BLOCK (b->index ? b->index - 1 : 1); c = BASIC_BLOCK (b->index ? b->index - 1 : 1);
redirect_edge_succ_nodup (b->pred, b->succ->dest); redirect_edge_succ_nodup (b->pred, b->succ->dest);
flow_delete_block (b); flow_delete_block (b);
...@@ -1554,6 +1582,7 @@ try_optimize_cfg (mode) ...@@ -1554,6 +1582,7 @@ try_optimize_cfg (mode)
if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall) if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall)
{ {
bool found = 0; bool found = 0;
blocks = sbitmap_alloc (n_basic_blocks); blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks); sbitmap_zero (blocks);
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
...@@ -1562,12 +1591,14 @@ try_optimize_cfg (mode) ...@@ -1562,12 +1591,14 @@ try_optimize_cfg (mode)
found = 1; found = 1;
SET_BIT (blocks, i); SET_BIT (blocks, i);
} }
if (found) if (found)
update_life_info (blocks, UPDATE_LIFE_GLOBAL, update_life_info (blocks, UPDATE_LIFE_GLOBAL,
PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
| PROP_KILL_DEAD_CODE); | PROP_KILL_DEAD_CODE);
sbitmap_free (blocks); sbitmap_free (blocks);
} }
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
BASIC_BLOCK (i)->aux = NULL; BASIC_BLOCK (i)->aux = NULL;
......
/* Basic block reordering routines for the GNU compiler. /* Basic block reordering routines for the GNU compiler.
Copyright (C) 2000, 2001 Free Software Foundation, Inc. Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it GCC is free software; you can redistribute it and/or modify it under
under the terms of the GNU General Public License as published by the terms of the GNU General Public License as published by the Free
the Free Software Foundation; either version 2, or (at your option) Software Foundation; either version 2, or (at your option) any later
any later version. version.
GCC is distributed in the hope that it will be useful, but WITHOUT GCC is distributed in the hope that it will be useful, but WITHOUT ANY
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY WARRANTY; without even the implied warranty of MERCHANTABILITY or
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
License for more details. for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */ 02111-1307, USA. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
...@@ -30,9 +30,7 @@ ...@@ -30,9 +30,7 @@
#include "cfglayout.h" #include "cfglayout.h"
/* The contents of the current function definition are allocated /* The contents of the current function definition are allocated
in this obstack, and all are freed at the end of the function. in this obstack, and all are freed at the end of the function. */
For top-level functions, this is temporary_obstack.
Separate obstacks are made for nested functions. */
extern struct obstack flow_obstack; extern struct obstack flow_obstack;
...@@ -126,7 +124,7 @@ skip_insns_after_block (bb) ...@@ -126,7 +124,7 @@ skip_insns_after_block (bb)
if (bb->index + 1 != n_basic_blocks) if (bb->index + 1 != n_basic_blocks)
next_head = BASIC_BLOCK (bb->index + 1)->head; next_head = BASIC_BLOCK (bb->index + 1)->head;
for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)); ) for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)) != 0; )
{ {
if (insn == next_head) if (insn == next_head)
break; break;
...@@ -172,30 +170,30 @@ skip_insns_after_block (bb) ...@@ -172,30 +170,30 @@ skip_insns_after_block (bb)
break; break;
} }
/* It is possible to hit contradicting sequence. For instance:
/* It is possible to hit contradictory sequence. For instance:
jump_insn jump_insn
NOTE_INSN_LOOP_BEG NOTE_INSN_LOOP_BEG
barrier barrier
Where barrier belongs to jump_insn, but the note does not. Where barrier belongs to jump_insn, but the note does not. This can be
This can be created by removing the basic block originally created by removing the basic block originally following
following NOTE_INSN_LOOP_BEG. NOTE_INSN_LOOP_BEG. In such case reorder the notes. */
In such case reorder the notes. */
for (insn = last_insn; insn != bb->end; insn = prev) for (insn = last_insn; insn != bb->end; insn = prev)
{ {
prev = PREV_INSN (insn); prev = PREV_INSN (insn);
if (GET_CODE (insn) == NOTE) if (GET_CODE (insn) == NOTE)
switch (NOTE_LINE_NUMBER (insn)) switch (NOTE_LINE_NUMBER (insn))
{ {
case NOTE_INSN_LOOP_END: case NOTE_INSN_LOOP_END:
case NOTE_INSN_BLOCK_END: case NOTE_INSN_BLOCK_END:
case NOTE_INSN_DELETED: case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL: case NOTE_INSN_DELETED_LABEL:
continue; continue;
default: default:
reorder_insns (insn, insn, last_insn); reorder_insns (insn, insn, last_insn);
} }
} }
...@@ -213,8 +211,7 @@ label_for_bb (bb) ...@@ -213,8 +211,7 @@ label_for_bb (bb)
if (GET_CODE (label) != CODE_LABEL) if (GET_CODE (label) != CODE_LABEL)
{ {
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Emitting label for block %d\n", fprintf (rtl_dump_file, "Emitting label for block %d\n", bb->index);
bb->index);
label = block_label (bb); label = block_label (bb);
if (bb->head == PREV_INSN (RBI (bb)->eff_head)) if (bb->head == PREV_INSN (RBI (bb)->eff_head))
...@@ -233,7 +230,7 @@ record_effective_endpoints () ...@@ -233,7 +230,7 @@ record_effective_endpoints ()
rtx next_insn = get_insns (); rtx next_insn = get_insns ();
int i; int i;
for (i = 0; i < n_basic_blocks; ++i) for (i = 0; i < n_basic_blocks; i++)
{ {
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
rtx end; rtx end;
...@@ -243,32 +240,33 @@ record_effective_endpoints () ...@@ -243,32 +240,33 @@ record_effective_endpoints ()
RBI (bb)->eff_end = end; RBI (bb)->eff_end = end;
next_insn = NEXT_INSN (end); next_insn = NEXT_INSN (end);
} }
function_tail_eff_head = next_insn; function_tail_eff_head = next_insn;
} }
/* Return the next NOTE_INSN_BASIC_BLOCK after X. */
static rtx static rtx
get_next_bb_note (x) get_next_bb_note (x)
rtx x; rtx x;
{ {
while (x) for (; x; x = NEXT_INSN (x))
{ if (NOTE_INSN_BASIC_BLOCK_P (x))
if (NOTE_INSN_BASIC_BLOCK_P (x)) return x;
return x;
x = NEXT_INSN (x);
}
return NULL; return NULL;
} }
/* Return the fist NOTE_INSN_BASIC_BLOCK before X. */
static rtx static rtx
get_prev_bb_note (x) get_prev_bb_note (x)
rtx x; rtx x;
{ {
while (x) for (; x; x = PREV_INSN (x))
{ if (NOTE_INSN_BASIC_BLOCK_P (x))
if (NOTE_INSN_BASIC_BLOCK_P (x)) return x;
return x;
x = PREV_INSN (x);
}
return NULL; return NULL;
} }
...@@ -313,6 +311,7 @@ relate_bbs_with_scopes (s) ...@@ -313,6 +311,7 @@ relate_bbs_with_scopes (s)
bbnote = get_next_bb_note (s->note_beg); bbnote = get_next_bb_note (s->note_beg);
if (! bbnote) if (! bbnote)
abort (); abort ();
if (NOTE_BASIC_BLOCK (bbnote) == s->bb_end) if (NOTE_BASIC_BLOCK (bbnote) == s->bb_end)
{ {
bbs_spanned = 0; bbs_spanned = 0;
...@@ -335,6 +334,7 @@ relate_bbs_with_scopes (s) ...@@ -335,6 +334,7 @@ relate_bbs_with_scopes (s)
bbnote = get_prev_bb_note (s->note_end); bbnote = get_prev_bb_note (s->note_end);
if (! bbnote) if (! bbnote)
abort (); abort ();
if (NOTE_BASIC_BLOCK (bbnote) == s->bb_beg) if (NOTE_BASIC_BLOCK (bbnote) == s->bb_beg)
{ {
bbs_spanned = 0; bbs_spanned = 0;
...@@ -357,16 +357,15 @@ relate_bbs_with_scopes (s) ...@@ -357,16 +357,15 @@ relate_bbs_with_scopes (s)
bbs_spanned = 0; bbs_spanned = 0;
else else
{ {
rtx x1, x2;
/* Both notes are outside of any bbs. This implies that all the /* Both notes are outside of any bbs. This implies that all the
basic blocks spanned by the pair of notes are contained in basic blocks spanned by the pair of notes are contained in
this scope. this scope.
There is a degenerate case to consider. If the notes do not There is a degenerate case to consider. If the notes do not
span any basic blocks, then it is an empty scope that can span any basic blocks, then it is an empty scope that can
safely be deleted or ignored. Mark these with level = -1. */ safely be deleted or ignored. Mark these with level = -1. */
rtx x1 = get_next_bb_note (s->note_beg);
rtx x2 = get_prev_bb_note (s->note_end);
x1 = get_next_bb_note (s->note_beg);
x2 = get_prev_bb_note (s->note_end);
if (! (x1 && x2)) if (! (x1 && x2))
{ {
s->level = -1; s->level = -1;
...@@ -418,6 +417,7 @@ make_new_scope (level, note) ...@@ -418,6 +417,7 @@ make_new_scope (level, note)
rtx note; rtx note;
{ {
scope new_scope = xcalloc (1, sizeof (struct scope_def)); scope new_scope = xcalloc (1, sizeof (struct scope_def));
new_scope->level = level; new_scope->level = level;
new_scope->note_beg = note; new_scope->note_beg = note;
return new_scope; return new_scope;
...@@ -442,6 +442,7 @@ build_scope_forest (forest) ...@@ -442,6 +442,7 @@ build_scope_forest (forest)
root = NULL; root = NULL;
curr_bb = NULL; curr_bb = NULL;
bbi = 0; bbi = 0;
for (x = get_insns (); x; x = NEXT_INSN (x)) for (x = get_insns (); x; x = NEXT_INSN (x))
{ {
if (bbi < n_basic_blocks && x == BASIC_BLOCK (bbi)->head) if (bbi < n_basic_blocks && x == BASIC_BLOCK (bbi)->head)
...@@ -454,8 +455,10 @@ build_scope_forest (forest) ...@@ -454,8 +455,10 @@ build_scope_forest (forest)
if (root) if (root)
{ {
scope new_scope; scope new_scope;
if (! curr_scope) if (! curr_scope)
abort(); abort();
level++; level++;
new_scope = make_new_scope (level, x); new_scope = make_new_scope (level, x);
new_scope->outer = curr_scope; new_scope->outer = curr_scope;
...@@ -471,10 +474,12 @@ build_scope_forest (forest) ...@@ -471,10 +474,12 @@ build_scope_forest (forest)
curr_scope->inner_last = new_scope; curr_scope->inner_last = new_scope;
} }
curr_scope = curr_scope->inner_last; curr_scope = curr_scope->inner_last;
} }
else else
{ {
int ntrees = forest->num_trees; int ntrees = forest->num_trees;
level++; level++;
curr_scope = make_new_scope (level, x); curr_scope = make_new_scope (level, x);
root = curr_scope; root = curr_scope;
...@@ -482,6 +487,7 @@ build_scope_forest (forest) ...@@ -482,6 +487,7 @@ build_scope_forest (forest)
sizeof (scope) * (ntrees + 1)); sizeof (scope) * (ntrees + 1));
forest->trees[forest->num_trees++] = root; forest->trees[forest->num_trees++] = root;
} }
curr_scope->bb_beg = curr_bb; curr_scope->bb_beg = curr_bb;
} }
else if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END) else if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END)
...@@ -493,22 +499,21 @@ build_scope_forest (forest) ...@@ -493,22 +499,21 @@ build_scope_forest (forest)
if (level == -1) if (level == -1)
root = NULL; root = NULL;
} }
} /* if note */ }
if (curr_bb && curr_bb->end == x) if (curr_bb && curr_bb->end == x)
{ {
curr_bb = NULL; curr_bb = NULL;
bbi++; bbi++;
} }
}
} /* for */
for (i = 0; i < forest->num_trees; i++) for (i = 0; i < forest->num_trees; i++)
relate_bbs_with_scopes (forest->trees[i]); relate_bbs_with_scopes (forest->trees[i]);
} }
/* Remove all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from /* Remove all NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from the insn
the insn chain. */ chain. */
static void static void
remove_scope_notes () remove_scope_notes ()
...@@ -572,7 +577,6 @@ insert_intra_1 (s, ip, bb) ...@@ -572,7 +577,6 @@ insert_intra_1 (s, ip, bb)
} }
} }
/* Insert NOTE_INSN_BLOCK_END notes and NOTE_INSN_BLOCK_BEG notes for /* Insert NOTE_INSN_BLOCK_END notes and NOTE_INSN_BLOCK_BEG notes for
scopes that are contained within BB. */ scopes that are contained within BB. */
...@@ -598,7 +602,6 @@ insert_intra_bb_scope_notes (bb) ...@@ -598,7 +602,6 @@ insert_intra_bb_scope_notes (bb)
} }
} }
/* Given two consecutive basic blocks BB1 and BB2 with different scopes, /* Given two consecutive basic blocks BB1 and BB2 with different scopes,
insert NOTE_INSN_BLOCK_END notes after BB1 and NOTE_INSN_BLOCK_BEG insert NOTE_INSN_BLOCK_END notes after BB1 and NOTE_INSN_BLOCK_BEG
notes before BB2 such that the notes are correctly balanced. If BB1 or notes before BB2 such that the notes are correctly balanced. If BB1 or
...@@ -619,8 +622,10 @@ insert_inter_bb_scope_notes (bb1, bb2) ...@@ -619,8 +622,10 @@ insert_inter_bb_scope_notes (bb1, bb2)
{ {
scope s1 = RBI (bb1)->scope; scope s1 = RBI (bb1)->scope;
scope s2 = RBI (bb2)->scope; scope s2 = RBI (bb2)->scope;
if (! s1 && ! s2) if (! s1 && ! s2)
return; return;
if (! s1) if (! s1)
bb1 = NULL; bb1 = NULL;
else if (! s2) else if (! s2)
...@@ -632,10 +637,9 @@ insert_inter_bb_scope_notes (bb1, bb2) ...@@ -632,10 +637,9 @@ insert_inter_bb_scope_notes (bb1, bb2)
{ {
scope s1 = RBI (bb1)->scope; scope s1 = RBI (bb1)->scope;
scope s2 = RBI (bb2)->scope; scope s2 = RBI (bb2)->scope;
while (s1 != s2) while (s1 != s2)
{ {
if (! (s1 && s2))
abort ();
if (s1->level > s2->level) if (s1->level > s2->level)
s1 = s1->outer; s1 = s1->outer;
else if (s2->level > s1->level) else if (s2->level > s1->level)
...@@ -646,6 +650,7 @@ insert_inter_bb_scope_notes (bb1, bb2) ...@@ -646,6 +650,7 @@ insert_inter_bb_scope_notes (bb1, bb2)
s2 = s2->outer; s2 = s2->outer;
} }
} }
com = s1; com = s1;
} }
else else
...@@ -655,18 +660,16 @@ insert_inter_bb_scope_notes (bb1, bb2) ...@@ -655,18 +660,16 @@ insert_inter_bb_scope_notes (bb1, bb2)
if (bb1) if (bb1)
{ {
rtx end = bb1->end; rtx end = bb1->end;
scope s;
scope s = RBI (bb1)->scope;
ip = RBI (bb1)->eff_end; ip = RBI (bb1)->eff_end;
while (s != com) for (s = RBI (bb1)->scope; s != com; s = s->outer)
{ if (NOTE_BLOCK (s->note_beg))
if (NOTE_BLOCK (s->note_beg)) {
{ ip = emit_note_after (NOTE_INSN_BLOCK_END, ip);
ip = emit_note_after (NOTE_INSN_BLOCK_END, ip); NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end); }
}
s = s->outer;
}
/* Emitting note may move the end of basic block to unwanted place. */ /* Emitting note may move the end of basic block to unwanted place. */
bb1->end = end; bb1->end = end;
} }
...@@ -674,17 +677,15 @@ insert_inter_bb_scope_notes (bb1, bb2) ...@@ -674,17 +677,15 @@ insert_inter_bb_scope_notes (bb1, bb2)
/* Open scopes. */ /* Open scopes. */
if (bb2) if (bb2)
{ {
scope s = RBI (bb2)->scope; scope s;
ip = bb2->head; ip = bb2->head;
while (s != com) for (s = RBI (bb2)->scope; s != com; s = s->outer)
{ if (NOTE_BLOCK (s->note_beg))
if (NOTE_BLOCK (s->note_beg)) {
{ ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip);
ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip); NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg); }
}
s = s->outer;
}
} }
} }
...@@ -709,6 +710,7 @@ rebuild_scope_notes (forest) ...@@ -709,6 +710,7 @@ rebuild_scope_notes (forest)
{ {
basic_block bb1 = BASIC_BLOCK (i); basic_block bb1 = BASIC_BLOCK (i);
basic_block bb2 = BASIC_BLOCK (i + 1); basic_block bb2 = BASIC_BLOCK (i + 1);
if (RBI (bb1)->scope != RBI (bb2)->scope) if (RBI (bb1)->scope != RBI (bb2)->scope)
insert_inter_bb_scope_notes (bb1, bb2); insert_inter_bb_scope_notes (bb1, bb2);
insert_intra_bb_scope_notes (bb1); insert_intra_bb_scope_notes (bb1);
...@@ -745,6 +747,7 @@ free_scope_forest (forest) ...@@ -745,6 +747,7 @@ free_scope_forest (forest)
scope_forest_info *forest; scope_forest_info *forest;
{ {
int i; int i;
for (i = 0; i < forest->num_trees; i++) for (i = 0; i < forest->num_trees; i++)
free_scope_forest_1 (forest->trees[i]); free_scope_forest_1 (forest->trees[i]);
} }
...@@ -755,15 +758,15 @@ void ...@@ -755,15 +758,15 @@ void
dump_scope_forest (forest) dump_scope_forest (forest)
scope_forest_info *forest; scope_forest_info *forest;
{ {
int i;
if (forest->num_trees == 0) if (forest->num_trees == 0)
fprintf (stderr, "\n< Empty scope forest >\n"); fprintf (stderr, "\n< Empty scope forest >\n");
else else
{ fprintf (stderr, "\n< Scope forest >\n");
int i;
fprintf (stderr, "\n< Scope forest >\n"); for (i = 0; i < forest->num_trees; i++)
for (i = 0; i < forest->num_trees; i++) dump_scope_forest_1 (forest->trees[i], 0);
dump_scope_forest_1 (forest->trees[i], 0);
}
} }
/* Recursive portion of dump_scope_forest. */ /* Recursive portion of dump_scope_forest. */
...@@ -813,33 +816,28 @@ fixup_reorder_chain () ...@@ -813,33 +816,28 @@ fixup_reorder_chain ()
/* First do the bulk reordering -- rechain the blocks without regard to /* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */ the needed changes to jumps and labels. */
last_bb = BASIC_BLOCK (0); for (last_bb = BASIC_BLOCK (0), bb = RBI (last_bb)->next, index = 1;
bb = RBI (last_bb)->next; bb != 0;
index = 1; last_bb = bb, bb = RBI (bb)->next, index++)
while (bb)
{ {
rtx last_e = RBI (last_bb)->eff_end; rtx last_e = RBI (last_bb)->eff_end;
rtx curr_h = RBI (bb)->eff_head; rtx curr_h = RBI (bb)->eff_head;
NEXT_INSN (last_e) = curr_h; NEXT_INSN (last_e) = curr_h;
PREV_INSN (curr_h) = last_e; PREV_INSN (curr_h) = last_e;
last_bb = bb;
bb = RBI (bb)->next;
index++;
} }
if (index != n_basic_blocks) if (index != n_basic_blocks)
abort (); abort ();
insn = RBI (last_bb)->eff_end; insn = RBI (last_bb)->eff_end;
NEXT_INSN (insn) = function_tail_eff_head; NEXT_INSN (insn) = function_tail_eff_head;
if (function_tail_eff_head) if (function_tail_eff_head)
PREV_INSN (function_tail_eff_head) = insn; PREV_INSN (function_tail_eff_head) = insn;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
set_last_insn (insn); set_last_insn (insn);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_insn_chain (); verify_insn_chain ();
...@@ -884,6 +882,7 @@ fixup_reorder_chain () ...@@ -884,6 +882,7 @@ fixup_reorder_chain ()
if (RBI (bb)->next != e_taken->dest) if (RBI (bb)->next != e_taken->dest)
{ {
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0); rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
if (note if (note
&& INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2 && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
&& invert_jump (bb_end_insn, && invert_jump (bb_end_insn,
...@@ -913,6 +912,7 @@ fixup_reorder_chain () ...@@ -913,6 +912,7 @@ fixup_reorder_chain ()
99% case, there should not have been a fallthru edge. */ 99% case, there should not have been a fallthru edge. */
if (! e_fall) if (! e_fall)
continue; continue;
#ifdef CASE_DROPS_THROUGH #ifdef CASE_DROPS_THROUGH
/* Except for VAX. Since we didn't have predication for the /* Except for VAX. Since we didn't have predication for the
tablejump, the fallthru block should not have moved. */ tablejump, the fallthru block should not have moved. */
...@@ -936,15 +936,13 @@ fixup_reorder_chain () ...@@ -936,15 +936,13 @@ fixup_reorder_chain ()
if (RBI (bb)->next == e_fall->dest) if (RBI (bb)->next == e_fall->dest)
continue; continue;
/* An fallthru to exit block. */ /* A fallthru to exit block. */
if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR) if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR)
continue; continue;
} }
/* We got here if we need to add a new jump insn. */ /* We got here if we need to add a new jump insn. */
nb = force_nonfallthru (e_fall); nb = force_nonfallthru (e_fall);
if (nb) if (nb)
{ {
alloc_aux_for_block (nb, sizeof (struct reorder_block_def)); alloc_aux_for_block (nb, sizeof (struct reorder_block_def));
...@@ -965,18 +963,17 @@ fixup_reorder_chain () ...@@ -965,18 +963,17 @@ fixup_reorder_chain ()
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Reordered sequence:\n"); fprintf (rtl_dump_file, "Reordered sequence:\n");
while (bb)
for (; bb; bb = RBI (bb)->next, index++)
{ {
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, " %i %sbb %i freq %i\n", index, fprintf (rtl_dump_file, " %i %sbb %i freq %i\n", index,
bb->index >= old_n_basic_blocks ? "compensation " : "", bb->index >= old_n_basic_blocks ? "compensation " : "",
bb->index, bb->index,
bb->frequency); bb->frequency);
bb->index = index; bb->index = index;
BASIC_BLOCK (index) = bb; BASIC_BLOCK (index) = bb;
bb = RBI (bb)->next;
index++;
} }
} }
...@@ -989,62 +986,31 @@ fixup_reorder_chain () ...@@ -989,62 +986,31 @@ fixup_reorder_chain ()
void void
verify_insn_chain () verify_insn_chain ()
{ {
rtx x, rtx x, prevx, nextx;
prevx, int insn_cnt1, insn_cnt2;
nextx;
int insn_cnt1,
insn_cnt2;
prevx = NULL;
insn_cnt1 = 1;
for (x = get_insns (); x; x = NEXT_INSN (x))
{
if (PREV_INSN (x) != prevx)
{
fprintf (stderr, "Forward traversal: insn chain corrupt.\n");
fprintf (stderr, "previous insn:\n");
debug_rtx (prevx);
fprintf (stderr, "current insn:\n");
debug_rtx (x);
abort ();
}
++insn_cnt1;
prevx = x;
}
if (prevx != get_last_insn ()) for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
{ x != 0;
fprintf (stderr, "last_insn corrupt.\n"); prevx = x, insn_cnt1++, x = NEXT_INSN (x))
if (PREV_INSN (x) != prevx)
abort (); abort ();
}
nextx = NULL; if (prevx != get_last_insn ())
insn_cnt2 = 1; abort ();
for (x = get_last_insn (); x; x = PREV_INSN (x))
{
if (NEXT_INSN (x) != nextx)
{
fprintf (stderr, "Reverse traversal: insn chain corrupt.\n");
fprintf (stderr, "current insn:\n");
debug_rtx (x);
fprintf (stderr, "next insn:\n");
debug_rtx (nextx);
abort ();
}
++insn_cnt2;
nextx = x;
}
if (insn_cnt1 != insn_cnt2) for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
{ x != 0;
fprintf (stderr, "insn_cnt1 (%d) not equal to insn_cnt2 (%d).\n", nextx = x, insn_cnt2++, x = PREV_INSN (x))
insn_cnt1, insn_cnt2); if (NEXT_INSN (x) != nextx)
abort (); abort ();
}
if (insn_cnt1 != insn_cnt2)
abort ();
} }
/* The block falling through to exit must be the last one in the /* The block falling through to exit must be the last one in the reordered
reordered chain. Ensure that this condition is met. */ chain. Ensure it is. */
static void static void
fixup_fallthru_exit_predecessor () fixup_fallthru_exit_predecessor ()
{ {
...@@ -1054,21 +1020,25 @@ fixup_fallthru_exit_predecessor () ...@@ -1054,21 +1020,25 @@ fixup_fallthru_exit_predecessor ()
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
bb = e->src; bb = e->src;
if (bb && RBI (bb)->next) if (bb && RBI (bb)->next)
{ {
basic_block c = BASIC_BLOCK (0); basic_block c = BASIC_BLOCK (0);
while (RBI (c)->next != bb) while (RBI (c)->next != bb)
c = RBI (c)->next; c = RBI (c)->next;
RBI (c)->next = RBI (bb)->next; RBI (c)->next = RBI (bb)->next;
while (RBI (c)->next) while (RBI (c)->next)
c = RBI (c)->next; c = RBI (c)->next;
RBI (c)->next = bb; RBI (c)->next = bb;
RBI (bb)->next = NULL; RBI (bb)->next = NULL;
} }
} }
/* Main entry point to this module - initialize the datastructures for /* Main entry point to this module: initialize the datastructures for CFG
CFG layout changes. */ layout changes. */
void void
cfg_layout_initialize () cfg_layout_initialize ()
...@@ -1081,14 +1051,15 @@ cfg_layout_initialize () ...@@ -1081,14 +1051,15 @@ cfg_layout_initialize ()
record_effective_endpoints (); record_effective_endpoints ();
} }
/* Finalize the changes - reorder insn list according to the sequence, /* Finalize the changes: reorder insn list according to the sequence, enter
enter compensation code, rebuild scope forest. */ compensation code, rebuild scope forest. */
void void
cfg_layout_finalize () cfg_layout_finalize ()
{ {
fixup_fallthru_exit_predecessor (); fixup_fallthru_exit_predecessor ();
fixup_reorder_chain (); fixup_reorder_chain ();
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_insn_chain (); verify_insn_chain ();
#endif #endif
......
...@@ -31,11 +31,13 @@ static int flow_loop_nested_p PARAMS ((struct loop *, ...@@ -31,11 +31,13 @@ static int flow_loop_nested_p PARAMS ((struct loop *,
static int flow_loop_entry_edges_find PARAMS ((basic_block, const sbitmap, static int flow_loop_entry_edges_find PARAMS ((basic_block, const sbitmap,
edge **)); edge **));
static int flow_loop_exit_edges_find PARAMS ((const sbitmap, edge **)); static int flow_loop_exit_edges_find PARAMS ((const sbitmap, edge **));
static int flow_loop_nodes_find PARAMS ((basic_block, basic_block, sbitmap)); static int flow_loop_nodes_find PARAMS ((basic_block, basic_block,
static void flow_loop_pre_header_scan PARAMS ((struct loop *)); sbitmap));
static void flow_loop_pre_header_scan PARAMS ((struct loop *));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block, static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
const sbitmap *)); const sbitmap *));
static void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *)); static void flow_loop_tree_node_add PARAMS ((struct loop *,
struct loop *));
static void flow_loops_tree_build PARAMS ((struct loops *)); static void flow_loops_tree_build PARAMS ((struct loops *));
static int flow_loop_level_compute PARAMS ((struct loop *, int)); static int flow_loop_level_compute PARAMS ((struct loop *, int));
static int flow_loops_level_compute PARAMS ((struct loops *)); static int flow_loops_level_compute PARAMS ((struct loops *));
...@@ -68,14 +70,17 @@ flow_loops_cfg_dump (loops, file) ...@@ -68,14 +70,17 @@ flow_loops_cfg_dump (loops, file)
fputs (";; DFS order: ", file); fputs (";; DFS order: ", file);
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.dfs_order[i]); fprintf (file, "%d ", loops->cfg.dfs_order[i]);
fputs ("\n", file); fputs ("\n", file);
} }
/* Dump the reverse completion node order. */ /* Dump the reverse completion node order. */
if (loops->cfg.rc_order) if (loops->cfg.rc_order)
{ {
fputs (";; RC order: ", file); fputs (";; RC order: ", file);
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.rc_order[i]); fprintf (file, "%d ", loops->cfg.rc_order[i]);
fputs ("\n", file); fputs ("\n", file);
} }
} }
...@@ -107,12 +112,10 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose) ...@@ -107,12 +112,10 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
fprintf (file, ";;\n;; Loop %d (%d to %d):%s%s\n", fprintf (file, ";;\n;; Loop %d (%d to %d):%s%s\n",
loop->num, INSN_UID (loop->first->head), loop->num, INSN_UID (loop->first->head),
INSN_UID (loop->last->end), INSN_UID (loop->last->end),
loop->shared ? " shared" : "", loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
loop->invalid ? " invalid" : "");
else else
fprintf (file, ";;\n;; Loop %d:%s%s\n", loop->num, fprintf (file, ";;\n;; Loop %d:%s%s\n", loop->num,
loop->shared ? " shared" : "", loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
loop->invalid ? " invalid" : "");
fprintf (file, ";; header %d, latch %d, pre-header %d, first %d, last %d\n", fprintf (file, ";; header %d, latch %d, pre-header %d, first %d, last %d\n",
loop->header->index, loop->latch->index, loop->header->index, loop->latch->index,
...@@ -125,14 +128,17 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose) ...@@ -125,14 +128,17 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
if (loop->pre_header_edges) if (loop->pre_header_edges)
flow_edge_list_print (";; pre-header edges", loop->pre_header_edges, flow_edge_list_print (";; pre-header edges", loop->pre_header_edges,
loop->num_pre_header_edges, file); loop->num_pre_header_edges, file);
flow_edge_list_print (";; entry edges", loop->entry_edges, flow_edge_list_print (";; entry edges", loop->entry_edges,
loop->num_entries, file); loop->num_entries, file);
fprintf (file, ";; %d", loop->num_nodes); fprintf (file, ";; %d", loop->num_nodes);
flow_nodes_print (" nodes", loop->nodes, file); flow_nodes_print (" nodes", loop->nodes, file);
flow_edge_list_print (";; exit edges", loop->exit_edges, flow_edge_list_print (";; exit edges", loop->exit_edges,
loop->num_exits, file); loop->num_exits, file);
if (loop->exits_doms) if (loop->exits_doms)
flow_nodes_print (";; exit doms", loop->exits_doms, file); flow_nodes_print (";; exit doms", loop->exits_doms, file);
if (loop_dump_aux) if (loop_dump_aux)
loop_dump_aux (loop, file, verbose); loop_dump_aux (loop, file, verbose);
} }
...@@ -147,49 +153,42 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose) ...@@ -147,49 +153,42 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose)
void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int)); void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
int verbose; int verbose;
{ {
int i; int i, j;
int num_loops; int num_loops;
num_loops = loops->num; num_loops = loops->num;
if (! num_loops || ! file) if (! num_loops || ! file)
return; return;
fprintf (file, ";; %d loops found, %d levels\n", fprintf (file, ";; %d loops found, %d levels\n", num_loops, loops->levels);
num_loops, loops->levels);
for (i = 0; i < num_loops; i++) for (i = 0; i < num_loops; i++)
{ {
struct loop *loop = &loops->array[i]; struct loop *loop = &loops->array[i];
flow_loop_dump (loop, file, loop_dump_aux, verbose); flow_loop_dump (loop, file, loop_dump_aux, verbose);
if (loop->shared) if (loop->shared)
{ for (j = 0; j < i; j++)
int j; {
struct loop *oloop = &loops->array[j];
for (j = 0; j < i; j++)
{ if (loop->header == oloop->header)
struct loop *oloop = &loops->array[j]; {
int disjoint;
if (loop->header == oloop->header) int smaller;
{
int disjoint; smaller = loop->num_nodes < oloop->num_nodes;
int smaller;
/* If the union of LOOP and OLOOP is different than
smaller = loop->num_nodes < oloop->num_nodes; the larger of LOOP and OLOOP then LOOP and OLOOP
must be disjoint. */
/* If the union of LOOP and OLOOP is different than disjoint = ! flow_loop_nested_p (smaller ? loop : oloop,
the larger of LOOP and OLOOP then LOOP and OLOOP smaller ? oloop : loop);
must be disjoint. */ fprintf (file,
disjoint = ! flow_loop_nested_p (smaller ? loop : oloop, ";; loop header %d shared by loops %d, %d %s\n",
smaller ? oloop : loop); loop->header->index, i, j,
fprintf (file, disjoint ? "disjoint" : "nested");
";; loop header %d shared by loops %d, %d %s\n", }
loop->header->index, i, j, }
disjoint ? "disjoint" : "nested");
}
}
}
} }
if (verbose) if (verbose)
...@@ -225,11 +224,13 @@ flow_loops_free (loops) ...@@ -225,11 +224,13 @@ flow_loops_free (loops)
if (loop->exits_doms) if (loop->exits_doms)
sbitmap_free (loop->exits_doms); sbitmap_free (loop->exits_doms);
} }
free (loops->array); free (loops->array);
loops->array = NULL; loops->array = NULL;
if (loops->cfg.dom) if (loops->cfg.dom)
sbitmap_vector_free (loops->cfg.dom); sbitmap_vector_free (loops->cfg.dom);
if (loops->cfg.dfs_order) if (loops->cfg.dfs_order)
free (loops->cfg.dfs_order); free (loops->cfg.dfs_order);
...@@ -394,42 +395,33 @@ static void ...@@ -394,42 +395,33 @@ static void
flow_loop_pre_header_scan (loop) flow_loop_pre_header_scan (loop)
struct loop *loop; struct loop *loop;
{ {
int num = 0; int num;
basic_block ebb; basic_block ebb;
edge e;
loop->num_pre_header_edges = 0; loop->num_pre_header_edges = 0;
if (loop->num_entries != 1) if (loop->num_entries != 1)
return; return;
ebb = loop->entry_edges[0]->src; ebb = loop->entry_edges[0]->src;
if (ebb == ENTRY_BLOCK_PTR)
return;
if (ebb != ENTRY_BLOCK_PTR) /* Count number of edges along trace from loop header to
{ root of pre-header extended basic block. Usually this is
edge e; only one or two edges. */
for (num = 1; ebb->pred->src != ENTRY_BLOCK_PTR && ! ebb->pred->pred_next;
/* Count number of edges along trace from loop header to num++)
root of pre-header extended basic block. Usually this is ebb = ebb->pred->src;
only one or two edges. */
num++; loop->pre_header_edges = (edge *) xmalloc (num * sizeof (edge *));
while (ebb->pred->src != ENTRY_BLOCK_PTR && ! ebb->pred->pred_next) loop->num_pre_header_edges = num;
{
ebb = ebb->pred->src; /* Store edges in order that they are followed. The source of the first edge
num++; is the root node of the pre-header extended basic block and the
} destination of the last last edge is the loop header. */
for (e = loop->entry_edges[0]; num; e = e->src->pred)
loop->pre_header_edges = (edge *) xmalloc (num * sizeof (edge *)); loop->pre_header_edges[--num] = e;
loop->num_pre_header_edges = num;
/* Store edges in order that they are followed. The source
of the first edge is the root node of the pre-header extended
basic block and the destination of the last last edge is
the loop header. */
for (e = loop->entry_edges[0]; num; e = e->src->pred)
{
loop->pre_header_edges[--num] = e;
}
}
} }
/* Return the block for the pre-header of the loop with header /* Return the block for the pre-header of the loop with header
...@@ -465,6 +457,7 @@ flow_loop_pre_header_find (header, dom) ...@@ -465,6 +457,7 @@ flow_loop_pre_header_find (header, dom)
} }
} }
} }
return pre_header; return pre_header;
} }
...@@ -485,16 +478,13 @@ flow_loop_tree_node_add (prevloop, loop) ...@@ -485,16 +478,13 @@ flow_loop_tree_node_add (prevloop, loop)
return; return;
} }
while (prevloop->outer) for (; prevloop->outer; prevloop = prevloop->outer)
{ if (flow_loop_nested_p (prevloop->outer, loop))
if (flow_loop_nested_p (prevloop->outer, loop)) {
{ prevloop->next = loop;
prevloop->next = loop; loop->outer = prevloop->outer;
loop->outer = prevloop->outer; return;
return; }
}
prevloop = prevloop->outer;
}
prevloop->next = loop; prevloop->next = loop;
loop->outer = NULL; loop->outer = NULL;
...@@ -517,7 +507,8 @@ flow_loops_tree_build (loops) ...@@ -517,7 +507,8 @@ flow_loops_tree_build (loops)
Since we used a depth first search this should be the Since we used a depth first search this should be the
outermost loop. */ outermost loop. */
loops->tree_root = &loops->array[0]; loops->tree_root = &loops->array[0];
loops->tree_root->outer = loops->tree_root->inner = loops->tree_root->next = NULL; loops->tree_root->outer = loops->tree_root->inner
= loops->tree_root->next = NULL;
/* Add the remaining loops to the tree. */ /* Add the remaining loops to the tree. */
for (i = 1; i < num_loops; i++) for (i = 1; i < num_loops; i++)
...@@ -546,13 +537,11 @@ flow_loop_level_compute (loop, depth) ...@@ -546,13 +537,11 @@ flow_loop_level_compute (loop, depth)
itself). */ itself). */
for (inner = loop->inner; inner; inner = inner->next) for (inner = loop->inner; inner; inner = inner->next)
{ {
int ilevel; int ilevel = flow_loop_level_compute (inner, depth + 1) + 1;
ilevel = flow_loop_level_compute (inner, depth + 1) + 1;
if (ilevel > level) level = MAX (ilevel, level);
level = ilevel;
} }
loop->level = level; loop->level = level;
loop->depth = depth; loop->depth = depth;
return level; return level;
...@@ -566,17 +555,17 @@ static int ...@@ -566,17 +555,17 @@ static int
flow_loops_level_compute (loops) flow_loops_level_compute (loops)
struct loops *loops; struct loops *loops;
{ {
int levels = 0;
struct loop *loop; struct loop *loop;
int level; int level;
int levels = 0;
/* Traverse all the outer level loops. */ /* Traverse all the outer level loops. */
for (loop = loops->tree_root; loop; loop = loop->next) for (loop = loops->tree_root; loop; loop = loop->next)
{ {
level = flow_loop_level_compute (loop, 1); level = flow_loop_level_compute (loop, 1);
if (level > levels) levels = MAX (levels, level);
levels = level;
} }
return levels; return levels;
} }
...@@ -594,23 +583,15 @@ flow_loop_scan (loops, loop, flags) ...@@ -594,23 +583,15 @@ flow_loop_scan (loops, loop, flags)
flags |= LOOP_EXIT_EDGES; flags |= LOOP_EXIT_EDGES;
if (flags & LOOP_ENTRY_EDGES) if (flags & LOOP_ENTRY_EDGES)
{ /* Find edges which enter the loop header. Note that the entry edges
/* Find edges which enter the loop header. should only enter the header of a natural loop. */
Note that the entry edges should only loop->num_entries = flow_loop_entry_edges_find (loop->header, loop->nodes,
enter the header of a natural loop. */ &loop->entry_edges);
loop->num_entries
= flow_loop_entry_edges_find (loop->header,
loop->nodes,
&loop->entry_edges);
}
if (flags & LOOP_EXIT_EDGES) if (flags & LOOP_EXIT_EDGES)
{ /* Find edges which exit the loop. */
/* Find edges which exit the loop. */ loop->num_exits
loop->num_exits = flow_loop_exit_edges_find (loop->nodes, &loop->exit_edges);
= flow_loop_exit_edges_find (loop->nodes,
&loop->exit_edges);
}
if (flags & LOOP_EXITS_DOMS) if (flags & LOOP_EXITS_DOMS)
{ {
...@@ -640,13 +621,14 @@ flow_loop_scan (loops, loop, flags) ...@@ -640,13 +621,14 @@ flow_loop_scan (loops, loop, flags)
the loop pre-header. */ the loop pre-header. */
flow_loop_pre_header_scan (loop); flow_loop_pre_header_scan (loop);
} }
return 1; return 1;
} }
/* Find all the natural loops in the function and save in LOOPS structure /* Find all the natural loops in the function and save in LOOPS structure and
and recalculate loop_depth information in basic block structures. recalculate loop_depth information in basic block structures. FLAGS
FLAGS controls which loop information is collected. controls which loop information is collected. Return the number of natural
Return the number of natural loops found. */ loops found. */
int int
flow_loops_find (loops, flags) flow_loops_find (loops, flags)
...@@ -668,7 +650,7 @@ flow_loops_find (loops, flags) ...@@ -668,7 +650,7 @@ flow_loops_find (loops, flags)
if (! (flags & LOOP_TREE)) if (! (flags & LOOP_TREE))
abort (); abort ();
memset (loops, 0, sizeof (*loops)); memset (loops, 0, sizeof *loops);
/* Taking care of this degenerate case makes the rest of /* Taking care of this degenerate case makes the rest of
this code simpler. */ this code simpler. */
...@@ -684,7 +666,6 @@ flow_loops_find (loops, flags) ...@@ -684,7 +666,6 @@ flow_loops_find (loops, flags)
/* Count the number of loop edges (back edges). This should be the /* Count the number of loop edges (back edges). This should be the
same as the number of natural loops. */ same as the number of natural loops. */
num_loops = 0; num_loops = 0;
for (b = 0; b < n_basic_blocks; b++) for (b = 0; b < n_basic_blocks; b++)
{ {
...@@ -810,9 +791,7 @@ flow_loops_find (loops, flags) ...@@ -810,9 +791,7 @@ flow_loops_find (loops, flags)
sbitmap_free (headers); sbitmap_free (headers);
} }
else else
{ sbitmap_vector_free (dom);
sbitmap_vector_free (dom);
}
loops->num = num_loops; loops->num = num_loops;
...@@ -828,6 +807,7 @@ flow_loops_find (loops, flags) ...@@ -828,6 +807,7 @@ flow_loops_find (loops, flags)
/* Update the information regarding the loops in the CFG /* Update the information regarding the loops in the CFG
specified by LOOPS. */ specified by LOOPS. */
int int
flow_loops_update (loops, flags) flow_loops_update (loops, flags)
struct loops *loops; struct loops *loops;
...@@ -850,5 +830,7 @@ flow_loop_outside_edge_p (loop, e) ...@@ -850,5 +830,7 @@ flow_loop_outside_edge_p (loop, e)
{ {
if (e->dest != loop->header) if (e->dest != loop->header)
abort (); abort ();
return (e->src == ENTRY_BLOCK_PTR) || ! TEST_BIT (loop->nodes, e->src->index);
return (e->src == ENTRY_BLOCK_PTR)
|| ! TEST_BIT (loop->nodes, e->src->index);
} }
...@@ -19,28 +19,28 @@ along with GCC; see the file COPYING. If not, write to the Free ...@@ -19,28 +19,28 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */ 02111-1307, USA. */
/* This file contains low level functions to manipulate with CFG and analyze it /* This file contains low level functions to manipulate the CFG and analyze it
that are aware of RTL intermediate language. that are aware of the RTL intermediate language.
Available functionality: Available functionality:
- CFG aware instruction chain manipulation - CFG-aware instruction chain manipulation
delete_insn, delete_insn_chain delete_insn, delete_insn_chain
- Basic block manipulation - Basic block manipulation
create_basic_block, flow_delete_block, split_block, merge_blocks_nomove create_basic_block, flow_delete_block, split_block,
- Infrastructure to determine quickly basic block for instruction. merge_blocks_nomove
- Infrastructure to determine quickly basic block for insn
compute_bb_for_insn, update_bb_for_insn, set_block_for_insn, compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
- Edge redirection with updating and optimizing instruction chain - Edge redirection with updating and optimizing of insn chain
block_label, redirect_edge_and_branch, block_label, redirect_edge_and_branch,
redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
- Edge splitting and commiting to edges - Edge splitting and commiting to edges
split_edge, insert_insn_on_edge, commit_edge_insertions split_edge, insert_insn_on_edge, commit_edge_insertions
- Dumping and debugging - Dumping and debugging
print_rtl_with_bb, dump_bb, debug_bb, debug_bb_n print_rtl_with_bb, dump_bb, debug_bb, debug_bb_n
- Consistency checking - Consistency checking
verify_flow_info verify_flow_info
- CFG updating after constant propagation - CFG updating after constant propagation
purge_dead_edges, purge_all_dead_edges purge_dead_edges, purge_all_dead_edges */
*/
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
...@@ -57,20 +57,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -57,20 +57,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h" #include "tm_p.h"
#include "obstack.h" #include "obstack.h"
/* Stubs in case we haven't got a return insn. */ /* Stubs in case we don't have a return insn. */
#ifndef HAVE_return #ifndef HAVE_return
#define HAVE_return 0 #define HAVE_return 0
#define gen_return() NULL_RTX #define gen_return() NULL_RTX
#endif #endif
/* The basic block structure for every insn, indexed by uid. */ /* The basic block structure for every insn, indexed by uid. */
varray_type basic_block_for_insn; varray_type basic_block_for_insn;
/* The labels mentioned in non-jump rtl. Valid during find_basic_blocks. */ /* The labels mentioned in non-jump rtl. Valid during find_basic_blocks. */
/* ??? Should probably be using LABEL_NUSES instead. It would take a /* ??? Should probably be using LABEL_NUSES instead. It would take a
bit of surgery to be able to use or co-opt the routines in jump. */ bit of surgery to be able to use or co-opt the routines in jump. */
rtx label_value_list; rtx label_value_list;
rtx tail_recursion_label_list; rtx tail_recursion_label_list;
...@@ -83,7 +81,7 @@ static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block)); ...@@ -83,7 +81,7 @@ static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
static basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block)); static basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block));
/* Return true if NOTE is not one of the ones that must be kept paired, /* Return true if NOTE is not one of the ones that must be kept paired,
so that we may simply delete them. */ so that we may simply delete it. */
static int static int
can_delete_note_p (note) can_delete_note_p (note)
...@@ -99,26 +97,12 @@ static int ...@@ -99,26 +97,12 @@ static int
can_delete_label_p (label) can_delete_label_p (label)
rtx label; rtx label;
{ {
rtx x; return (!LABEL_PRESERVE_P (label)
/* User declared labels must be preserved. */
if (LABEL_PRESERVE_P (label)) && LABEL_NAME (label) == 0
return 0; && !in_expr_list_p (forced_labels, label)
&& !in_expr_list_p (label_value_list, label)
for (x = forced_labels; x; x = XEXP (x, 1)) && !in_expr_list_p (exception_handler_labels, label));
if (label == XEXP (x, 0))
return 0;
for (x = label_value_list; x; x = XEXP (x, 1))
if (label == XEXP (x, 0))
return 0;
for (x = exception_handler_labels; x; x = XEXP (x, 1))
if (label == XEXP (x, 0))
return 0;
/* User declared labels must be preserved. */
if (LABEL_NAME (label) != 0)
return 0;
return 1;
} }
/* Delete INSN by patching it out. Return the next insn. */ /* Delete INSN by patching it out. Return the next insn. */
...@@ -145,6 +129,7 @@ delete_insn (insn) ...@@ -145,6 +129,7 @@ delete_insn (insn)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL; NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
NOTE_SOURCE_FILE (insn) = name; NOTE_SOURCE_FILE (insn) = name;
} }
remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels); remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
} }
...@@ -189,12 +174,11 @@ void ...@@ -189,12 +174,11 @@ void
delete_insn_chain (start, finish) delete_insn_chain (start, finish)
rtx start, finish; rtx start, finish;
{ {
/* Unchain the insns one by one. It would be quicker to delete all
of these with a single unchaining, rather than one at a time, but
we need to keep the NOTE's. */
rtx next; rtx next;
/* Unchain the insns one by one. It would be quicker to delete all of these
with a single unchaining, rather than one at a time, but we need to keep
the NOTE's. */
while (1) while (1)
{ {
next = NEXT_INSN (start); next = NEXT_INSN (start);
...@@ -209,14 +193,12 @@ delete_insn_chain (start, finish) ...@@ -209,14 +193,12 @@ delete_insn_chain (start, finish)
} }
} }
/* Create a new basic block consisting of the instructions between /* Create a new basic block consisting of the instructions between HEAD and END
HEAD and END inclusive. This function is designed to allow fast inclusive. This function is designed to allow fast BB construction - reuses
BB construction - reuses the note and basic block struct the note and basic block struct in BB_NOTE, if any and do not grow
in BB_NOTE, if any and do not grow BASIC_BLOCK chain and should BASIC_BLOCK chain and should be used directly only by CFG construction code.
be used directly only by CFG construction code. END can be NULL in to create new empty basic block before HEAD. Both END
END can be NULL in to create new empty basic block before HEAD. and HEAD can be NULL to create basic block at the end of INSN chain. */
Both END and HEAD can be NULL to create basic block at the end of
INSN chain. */
basic_block basic_block
create_basic_block_structure (index, head, end, bb_note) create_basic_block_structure (index, head, end, bb_note)
...@@ -252,10 +234,8 @@ create_basic_block_structure (index, head, end, bb_note) ...@@ -252,10 +234,8 @@ create_basic_block_structure (index, head, end, bb_note)
bb = alloc_block (); bb = alloc_block ();
if (!head && !end) if (!head && !end)
{ head = end = bb_note
head = end = bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, = emit_note_after (NOTE_INSN_BASIC_BLOCK, get_last_insn ());
get_last_insn ());
}
else if (GET_CODE (head) == CODE_LABEL && end) else if (GET_CODE (head) == CODE_LABEL && end)
{ {
bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head); bb_note = emit_note_after (NOTE_INSN_BASIC_BLOCK, head);
...@@ -269,6 +249,7 @@ create_basic_block_structure (index, head, end, bb_note) ...@@ -269,6 +249,7 @@ create_basic_block_structure (index, head, end, bb_note)
if (!end) if (!end)
end = head; end = head;
} }
NOTE_BASIC_BLOCK (bb_note) = bb; NOTE_BASIC_BLOCK (bb_note) = bb;
} }
...@@ -290,11 +271,10 @@ create_basic_block_structure (index, head, end, bb_note) ...@@ -290,11 +271,10 @@ create_basic_block_structure (index, head, end, bb_note)
return bb; return bb;
} }
/* Create new basic block consisting of instructions in between HEAD and /* Create new basic block consisting of instructions in between HEAD and END
END and place it to the BB chain at position INDEX. and place it to the BB chain at position INDEX. END can be NULL in to
END can be NULL in to create new empty basic block before HEAD. create new empty basic block before HEAD. Both END and HEAD can be NULL to
Both END and HEAD can be NULL to create basic block at the end of create basic block at the end of INSN chain. */
INSN chain. */
basic_block basic_block
create_basic_block (index, head, end) create_basic_block (index, head, end)
...@@ -313,6 +293,7 @@ create_basic_block (index, head, end) ...@@ -313,6 +293,7 @@ create_basic_block (index, head, end)
for (i = n_basic_blocks - 1; i > index; --i) for (i = n_basic_blocks - 1; i > index; --i)
{ {
basic_block tmp = BASIC_BLOCK (i - 1); basic_block tmp = BASIC_BLOCK (i - 1);
BASIC_BLOCK (i) = tmp; BASIC_BLOCK (i) = tmp;
tmp->index = i; tmp->index = i;
} }
...@@ -397,23 +378,22 @@ compute_bb_for_insn (max) ...@@ -397,23 +378,22 @@ compute_bb_for_insn (max)
if (basic_block_for_insn) if (basic_block_for_insn)
VARRAY_FREE (basic_block_for_insn); VARRAY_FREE (basic_block_for_insn);
VARRAY_BB_INIT (basic_block_for_insn, max, "basic_block_for_insn"); VARRAY_BB_INIT (basic_block_for_insn, max, "basic_block_for_insn");
for (i = 0; i < n_basic_blocks; ++i) for (i = 0; i < n_basic_blocks; ++i)
{ {
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
rtx insn, end; rtx end = bb->end;
rtx insn;
end = bb->end; for (insn = bb->head; ; insn = NEXT_INSN (insn))
insn = bb->head;
while (1)
{ {
int uid = INSN_UID (insn); if (INSN_UID (insn) < max)
if (uid < max) VARRAY_BB (basic_block_for_insn, INSN_UID (insn)) = bb;
VARRAY_BB (basic_block_for_insn, uid) = bb;
if (insn == end) if (insn == end)
break; break;
insn = NEXT_INSN (insn);
} }
} }
} }
...@@ -425,6 +405,7 @@ free_bb_for_insn () ...@@ -425,6 +405,7 @@ free_bb_for_insn ()
{ {
if (basic_block_for_insn) if (basic_block_for_insn)
VARRAY_FREE (basic_block_for_insn); VARRAY_FREE (basic_block_for_insn);
basic_block_for_insn = 0; basic_block_for_insn = 0;
} }
...@@ -442,7 +423,6 @@ update_bb_for_insn (bb) ...@@ -442,7 +423,6 @@ update_bb_for_insn (bb)
for (insn = bb->head; ; insn = NEXT_INSN (insn)) for (insn = bb->head; ; insn = NEXT_INSN (insn))
{ {
set_block_for_insn (insn, bb); set_block_for_insn (insn, bb);
if (insn == bb->end) if (insn == bb->end)
break; break;
} }
...@@ -456,15 +436,15 @@ set_block_for_insn (insn, bb) ...@@ -456,15 +436,15 @@ set_block_for_insn (insn, bb)
basic_block bb; basic_block bb;
{ {
size_t uid = INSN_UID (insn); size_t uid = INSN_UID (insn);
if (uid >= basic_block_for_insn->num_elements) if (uid >= basic_block_for_insn->num_elements)
{ {
int new_size;
/* Add one-eighth the size so we don't keep calling xrealloc. */ /* Add one-eighth the size so we don't keep calling xrealloc. */
new_size = uid + (uid + 7) / 8; size_t new_size = uid + (uid + 7) / 8;
VARRAY_GROW (basic_block_for_insn, new_size); VARRAY_GROW (basic_block_for_insn, new_size);
} }
VARRAY_BB (basic_block_for_insn, uid) = bb; VARRAY_BB (basic_block_for_insn, uid) = bb;
} }
...@@ -528,37 +508,37 @@ void ...@@ -528,37 +508,37 @@ void
merge_blocks_nomove (a, b) merge_blocks_nomove (a, b)
basic_block a, b; basic_block a, b;
{ {
edge e; rtx b_head = b->head, b_end = b->end, a_end = a->end;
rtx b_head, b_end, a_end;
rtx del_first = NULL_RTX, del_last = NULL_RTX; rtx del_first = NULL_RTX, del_last = NULL_RTX;
int b_empty = 0; int b_empty = 0;
edge e;
/* If there was a CODE_LABEL beginning B, delete it. */ /* If there was a CODE_LABEL beginning B, delete it. */
b_head = b->head;
b_end = b->end;
if (GET_CODE (b_head) == CODE_LABEL) if (GET_CODE (b_head) == CODE_LABEL)
{ {
/* Detect basic blocks with nothing but a label. This can happen /* Detect basic blocks with nothing but a label. This can happen
in particular at the end of a function. */ in particular at the end of a function. */
if (b_head == b_end) if (b_head == b_end)
b_empty = 1; b_empty = 1;
del_first = del_last = b_head; del_first = del_last = b_head;
b_head = NEXT_INSN (b_head); b_head = NEXT_INSN (b_head);
} }
/* Delete the basic block note. */ /* Delete the basic block note and handle blocks containing just that
note. */
if (NOTE_INSN_BASIC_BLOCK_P (b_head)) if (NOTE_INSN_BASIC_BLOCK_P (b_head))
{ {
if (b_head == b_end) if (b_head == b_end)
b_empty = 1; b_empty = 1;
if (! del_last) if (! del_last)
del_first = b_head; del_first = b_head;
del_last = b_head; del_last = b_head;
b_head = NEXT_INSN (b_head); b_head = NEXT_INSN (b_head);
} }
/* If there was a jump out of A, delete it. */ /* If there was a jump out of A, delete it. */
a_end = a->end;
if (GET_CODE (a_end) == JUMP_INSN) if (GET_CODE (a_end) == JUMP_INSN)
{ {
rtx prev; rtx prev;
...@@ -577,6 +557,7 @@ merge_blocks_nomove (a, b) ...@@ -577,6 +557,7 @@ merge_blocks_nomove (a, b)
if (only_sets_cc0_p (prev)) if (only_sets_cc0_p (prev))
{ {
rtx tmp = prev; rtx tmp = prev;
prev = prev_nonnote_insn (prev); prev = prev_nonnote_insn (prev);
if (!prev) if (!prev)
prev = a->head; prev = a->head;
...@@ -614,22 +595,24 @@ merge_blocks_nomove (a, b) ...@@ -614,22 +595,24 @@ merge_blocks_nomove (a, b)
/* Reassociate the insns of B with A. */ /* Reassociate the insns of B with A. */
if (!b_empty) if (!b_empty)
{ {
rtx x = a_end;
if (basic_block_for_insn) if (basic_block_for_insn)
{ {
BLOCK_FOR_INSN (x) = a; rtx x;
while (x != b_end)
{ for (x = a_end; x != b_end; x = NEXT_INSN (x))
x = NEXT_INSN (x); BLOCK_FOR_INSN (x) = a;
BLOCK_FOR_INSN (x) = a;
} BLOCK_FOR_INSN (b_end) = a;
} }
a_end = b_end; a_end = b_end;
} }
a->end = a_end; a->end = a_end;
} }
/* Return label in the head of basic block. Create one if it doesn't exist. */ /* Return the label in the head of basic block BLOCK. Create one if it doesn't
exist. */
rtx rtx
block_label (block) block_label (block)
...@@ -637,21 +620,21 @@ block_label (block) ...@@ -637,21 +620,21 @@ block_label (block)
{ {
if (block == EXIT_BLOCK_PTR) if (block == EXIT_BLOCK_PTR)
return NULL_RTX; return NULL_RTX;
if (GET_CODE (block->head) != CODE_LABEL) if (GET_CODE (block->head) != CODE_LABEL)
{ {
block->head = emit_label_before (gen_label_rtx (), block->head); block->head = emit_label_before (gen_label_rtx (), block->head);
if (basic_block_for_insn) if (basic_block_for_insn)
set_block_for_insn (block->head, block); set_block_for_insn (block->head, block);
} }
return block->head; return block->head;
} }
/* Attempt to perform edge redirection by replacing possibly complex jump /* Attempt to perform edge redirection by replacing possibly complex jump
instruction by unconditional jump or removing jump completely. instruction by unconditional jump or removing jump completely. This can
This can apply only if all edges now point to the same block. apply only if all edges now point to the same block. The parameters and
return values are equivalent to redirect_edge_and_branch. */
The parameters and return values are equivalent to redirect_edge_and_branch.
*/
static bool static bool
try_redirect_by_replacing_jump (e, target) try_redirect_by_replacing_jump (e, target)
...@@ -668,6 +651,7 @@ try_redirect_by_replacing_jump (e, target) ...@@ -668,6 +651,7 @@ try_redirect_by_replacing_jump (e, target)
for (tmp = src->succ; tmp; tmp = tmp->succ_next) for (tmp = src->succ; tmp; tmp = tmp->succ_next)
if (tmp->dest != target && tmp != e) if (tmp->dest != target && tmp != e)
break; break;
if (tmp || !onlyjump_p (insn)) if (tmp || !onlyjump_p (insn))
return false; return false;
...@@ -694,6 +678,7 @@ try_redirect_by_replacing_jump (e, target) ...@@ -694,6 +678,7 @@ try_redirect_by_replacing_jump (e, target)
/* Selectively unlink whole insn chain. */ /* Selectively unlink whole insn chain. */
delete_insn_chain (kill_from, PREV_INSN (target->head)); delete_insn_chain (kill_from, PREV_INSN (target->head));
} }
/* If this already is simplejump, redirect it. */ /* If this already is simplejump, redirect it. */
else if (simplejump_p (insn)) else if (simplejump_p (insn))
{ {
...@@ -704,6 +689,7 @@ try_redirect_by_replacing_jump (e, target) ...@@ -704,6 +689,7 @@ try_redirect_by_replacing_jump (e, target)
INSN_UID (insn), e->dest->index, target->index); INSN_UID (insn), e->dest->index, target->index);
redirect_jump (insn, block_label (target), 0); redirect_jump (insn, block_label (target), 0);
} }
/* Or replace possibly complicated jump insn by simple jump insn. */ /* Or replace possibly complicated jump insn by simple jump insn. */
else else
{ {
...@@ -732,6 +718,7 @@ try_redirect_by_replacing_jump (e, target) ...@@ -732,6 +718,7 @@ try_redirect_by_replacing_jump (e, target)
e->flags = EDGE_FALLTHRU; e->flags = EDGE_FALLTHRU;
else else
e->flags = 0; e->flags = 0;
e->probability = REG_BR_PROB_BASE; e->probability = REG_BR_PROB_BASE;
e->count = src->count; e->count = src->count;
...@@ -743,43 +730,41 @@ try_redirect_by_replacing_jump (e, target) ...@@ -743,43 +730,41 @@ try_redirect_by_replacing_jump (e, target)
if (e->dest != target) if (e->dest != target)
redirect_edge_succ (e, target); redirect_edge_succ (e, target);
return true; return true;
} }
/* Return last loop_beg note appearing after INSN, before start of next /* Return last loop_beg note appearing after INSN, before start of next
basic block. Return INSN if there are no such notes. basic block. Return INSN if there are no such notes.
When emitting jump to redirect an fallthru edge, it should always When emitting jump to redirect an fallthru edge, it should always appear
appear after the LOOP_BEG notes, as loop optimizer expect loop to after the LOOP_BEG notes, as loop optimizer expect loop to either start by
either start by fallthru edge or jump following the LOOP_BEG note fallthru edge or jump following the LOOP_BEG note jumping to the loop exit
jumping to the loop exit test. */ test. */
static rtx static rtx
last_loop_beg_note (insn) last_loop_beg_note (insn)
rtx insn; rtx insn;
{ {
rtx last = insn; rtx last = insn;
insn = NEXT_INSN (insn);
while (insn && GET_CODE (insn) == NOTE for (insn = NEXT_INSN (insn); insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK) && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
{ insn = NEXT_INSN (insn))
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
last = insn; last = insn;
insn = NEXT_INSN (insn);
}
return last; return last;
} }
/* Attempt to change code to redirect edge E to TARGET. /* Attempt to change code to redirect edge E to TARGET. Don't do that on
Don't do that on expense of adding new instructions or reordering expense of adding new instructions or reordering basic blocks.
basic blocks.
Function can be also called with edge destination equivalent to the Function can be also called with edge destination equivalent to the TARGET.
TARGET. Then it should try the simplifications and do nothing if Then it should try the simplifications and do nothing if none is possible.
none is possible.
Return true if transformation succeeded. We still return false in case Return true if transformation succeeded. We still return false in case E
E already destinated TARGET and we didn't managed to simplify instruction already destinated TARGET and we didn't managed to simplify instruction
stream. */ stream. */
bool bool
...@@ -797,6 +782,7 @@ redirect_edge_and_branch (e, target) ...@@ -797,6 +782,7 @@ redirect_edge_and_branch (e, target)
if (try_redirect_by_replacing_jump (e, target)) if (try_redirect_by_replacing_jump (e, target))
return true; return true;
/* Do this fast path late, as we want above code to simplify for cases /* Do this fast path late, as we want above code to simplify for cases
where called on single edge leaving basic block containing nontrivial where called on single edge leaving basic block containing nontrivial
jump insn. */ jump insn. */
...@@ -806,7 +792,7 @@ redirect_edge_and_branch (e, target) ...@@ -806,7 +792,7 @@ redirect_edge_and_branch (e, target)
/* We can only redirect non-fallthru edges of jump insn. */ /* We can only redirect non-fallthru edges of jump insn. */
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
return false; return false;
if (GET_CODE (insn) != JUMP_INSN) else if (GET_CODE (insn) != JUMP_INSN)
return false; return false;
/* Recognize a tablejump and adjust all matching cases. */ /* Recognize a tablejump and adjust all matching cases. */
...@@ -851,27 +837,26 @@ redirect_edge_and_branch (e, target) ...@@ -851,27 +837,26 @@ redirect_edge_and_branch (e, target)
/* ?? We may play the games with moving the named labels from /* ?? We may play the games with moving the named labels from
one basic block to the other in case only one computed_jump is one basic block to the other in case only one computed_jump is
available. */ available. */
if (computed_jump_p (insn)) if (computed_jump_p (insn)
return false; /* A return instruction can't be redirected. */
|| returnjump_p (insn))
/* A return instruction can't be redirected. */
if (returnjump_p (insn))
return false; return false;
/* If the insn doesn't go where we think, we're confused. */ /* If the insn doesn't go where we think, we're confused. */
if (JUMP_LABEL (insn) != old_label) if (JUMP_LABEL (insn) != old_label
abort (); /* If the substitution doesn't succeed, die. This can happen
/* If the substitution doesn't succeed, die. This can happen if the back end emitted unrecognizable instructions. */
if the back end emitted unrecognizable instructions. */ || !redirect_jump (insn, block_label (target), 0))
if (! redirect_jump (insn, block_label (target), 0))
abort (); abort ();
} }
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Edge %i->%i redirected to %i\n", fprintf (rtl_dump_file, "Edge %i->%i redirected to %i\n",
e->src->index, e->dest->index, target->index); e->src->index, e->dest->index, target->index);
if (e->dest != target) if (e->dest != target)
redirect_edge_succ_nodup (e, target); redirect_edge_succ_nodup (e, target);
return true; return true;
} }
...@@ -889,23 +874,24 @@ force_nonfallthru_and_redirect (e, target) ...@@ -889,23 +874,24 @@ force_nonfallthru_and_redirect (e, target)
if (e->flags & EDGE_ABNORMAL) if (e->flags & EDGE_ABNORMAL)
abort (); abort ();
if (!(e->flags & EDGE_FALLTHRU)) else if (!(e->flags & EDGE_FALLTHRU))
abort (); abort ();
if (e->src->succ->succ_next) else if (e->src->succ->succ_next)
{ {
/* Create the new structures. */ /* Create the new structures. */
note = last_loop_beg_note (e->src->end); note = last_loop_beg_note (e->src->end);
jump_block = create_basic_block (e->src->index + 1, NEXT_INSN (note), NULL); jump_block
= create_basic_block (e->src->index + 1, NEXT_INSN (note), NULL);
jump_block->count = e->count; jump_block->count = e->count;
jump_block->frequency = EDGE_FREQUENCY (e); jump_block->frequency = EDGE_FREQUENCY (e);
jump_block->loop_depth = target->loop_depth; jump_block->loop_depth = target->loop_depth;
if (target->global_live_at_start) if (target->global_live_at_start)
{ {
jump_block->global_live_at_start = jump_block->global_live_at_start
OBSTACK_ALLOC_REG_SET (&flow_obstack); = OBSTACK_ALLOC_REG_SET (&flow_obstack);
jump_block->global_live_at_end = jump_block->global_live_at_end
OBSTACK_ALLOC_REG_SET (&flow_obstack); = OBSTACK_ALLOC_REG_SET (&flow_obstack);
COPY_REG_SET (jump_block->global_live_at_start, COPY_REG_SET (jump_block->global_live_at_start,
target->global_live_at_start); target->global_live_at_start);
COPY_REG_SET (jump_block->global_live_at_end, COPY_REG_SET (jump_block->global_live_at_end,
...@@ -925,6 +911,7 @@ force_nonfallthru_and_redirect (e, target) ...@@ -925,6 +911,7 @@ force_nonfallthru_and_redirect (e, target)
} }
else else
jump_block = e->src; jump_block = e->src;
e->flags &= ~EDGE_FALLTHRU; e->flags &= ~EDGE_FALLTHRU;
if (target == EXIT_BLOCK_PTR) if (target == EXIT_BLOCK_PTR)
{ {
...@@ -940,6 +927,7 @@ force_nonfallthru_and_redirect (e, target) ...@@ -940,6 +927,7 @@ force_nonfallthru_and_redirect (e, target)
JUMP_LABEL (jump_block->end) = label; JUMP_LABEL (jump_block->end) = label;
LABEL_NUSES (label)++; LABEL_NUSES (label)++;
} }
emit_barrier_after (jump_block->end); emit_barrier_after (jump_block->end);
redirect_edge_succ_nodup (e, target); redirect_edge_succ_nodup (e, target);
...@@ -949,6 +937,7 @@ force_nonfallthru_and_redirect (e, target) ...@@ -949,6 +937,7 @@ force_nonfallthru_and_redirect (e, target)
/* Edge E is assumed to be fallthru edge. Emit needed jump instruction /* Edge E is assumed to be fallthru edge. Emit needed jump instruction
(and possibly create new basic block) to make edge non-fallthru. (and possibly create new basic block) to make edge non-fallthru.
Return newly created BB or NULL if none. */ Return newly created BB or NULL if none. */
basic_block basic_block
force_nonfallthru (e) force_nonfallthru (e)
edge e; edge e;
...@@ -965,17 +954,13 @@ redirect_edge_and_branch_force (e, target) ...@@ -965,17 +954,13 @@ redirect_edge_and_branch_force (e, target)
edge e; edge e;
basic_block target; basic_block target;
{ {
basic_block new_bb; if (redirect_edge_and_branch (e, target)
|| e->dest == target)
if (redirect_edge_and_branch (e, target))
return NULL;
if (e->dest == target)
return NULL; return NULL;
/* In case the edge redirection failed, try to force it to be non-fallthru /* In case the edge redirection failed, try to force it to be non-fallthru
and redirect newly created simplejump. */ and redirect newly created simplejump. */
new_bb = force_nonfallthru_and_redirect (e, target); return force_nonfallthru_and_redirect (e, target);
return new_bb;
} }
/* The given edge should potentially be a fallthru edge. If that is in /* The given edge should potentially be a fallthru edge. If that is in
...@@ -1042,7 +1027,7 @@ tidy_fallthru_edges () ...@@ -1042,7 +1027,7 @@ tidy_fallthru_edges ()
{ {
int i; int i;
for (i = 1; i < n_basic_blocks; ++i) for (i = 1; i < n_basic_blocks; i++)
{ {
basic_block b = BASIC_BLOCK (i - 1); basic_block b = BASIC_BLOCK (i - 1);
basic_block c = BASIC_BLOCK (i); basic_block c = BASIC_BLOCK (i);
...@@ -1059,6 +1044,7 @@ tidy_fallthru_edges () ...@@ -1059,6 +1044,7 @@ tidy_fallthru_edges ()
Furthermore, the edge will be marked as a fallthru because we Furthermore, the edge will be marked as a fallthru because we
merge the flags for the duplicate edges. So we do not want to merge the flags for the duplicate edges. So we do not want to
check that the edge is not a FALLTHRU edge. */ check that the edge is not a FALLTHRU edge. */
if ((s = b->succ) != NULL if ((s = b->succ) != NULL
&& ! (s->flags & EDGE_COMPLEX) && ! (s->flags & EDGE_COMPLEX)
&& s->succ_next == NULL && s->succ_next == NULL
...@@ -1082,8 +1068,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2) ...@@ -1082,8 +1068,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2)
if (bb1->index > bb2->index) if (bb1->index > bb2->index)
return false; return false;
else if (bb1->index == bb2->index)
if (bb1->index == bb2->index)
return true; return true;
for (insn = bb1->end; insn != bb2->head && count >= 0; for (insn = bb1->end; insn != bb2->head && count >= 0;
...@@ -1092,7 +1077,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2) ...@@ -1092,7 +1077,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2)
{ {
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
count++; count++;
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
count--; count--;
} }
...@@ -1123,6 +1108,7 @@ split_edge (edge_in) ...@@ -1123,6 +1108,7 @@ split_edge (edge_in)
if ((edge_in->flags & EDGE_FALLTHRU) == 0) if ((edge_in->flags & EDGE_FALLTHRU) == 0)
{ {
edge e; edge e;
for (e = edge_in->dest->pred; e; e = e->pred_next) for (e = edge_in->dest->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
break; break;
...@@ -1152,7 +1138,8 @@ split_edge (edge_in) ...@@ -1152,7 +1138,8 @@ split_edge (edge_in)
if (edge_in->dest != EXIT_BLOCK_PTR if (edge_in->dest != EXIT_BLOCK_PTR
&& PREV_INSN (edge_in->dest->head) && PREV_INSN (edge_in->dest->head)
&& GET_CODE (PREV_INSN (edge_in->dest->head)) == NOTE && GET_CODE (PREV_INSN (edge_in->dest->head)) == NOTE
&& NOTE_LINE_NUMBER (PREV_INSN (edge_in->dest->head)) == NOTE_INSN_LOOP_BEG && (NOTE_LINE_NUMBER (PREV_INSN (edge_in->dest->head))
== NOTE_INSN_LOOP_BEG)
&& !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src)) && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
before = PREV_INSN (edge_in->dest->head); before = PREV_INSN (edge_in->dest->head);
else if (edge_in->dest != EXIT_BLOCK_PTR) else if (edge_in->dest != EXIT_BLOCK_PTR)
...@@ -1170,8 +1157,10 @@ split_edge (edge_in) ...@@ -1170,8 +1157,10 @@ split_edge (edge_in)
{ {
bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack); bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack); bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
COPY_REG_SET (bb->global_live_at_start, edge_in->dest->global_live_at_start); COPY_REG_SET (bb->global_live_at_start,
COPY_REG_SET (bb->global_live_at_end, edge_in->dest->global_live_at_start); edge_in->dest->global_live_at_start);
COPY_REG_SET (bb->global_live_at_end,
edge_in->dest->global_live_at_start);
} }
edge_out = make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU); edge_out = make_single_succ_edge (bb, edge_in->dest, EDGE_FALLTHRU);
...@@ -1254,6 +1243,7 @@ commit_one_edge_insertion (e) ...@@ -1254,6 +1243,7 @@ commit_one_edge_insertion (e)
&& e->src != ENTRY_BLOCK_PTR) && e->src != ENTRY_BLOCK_PTR)
{ {
bb = e->src; bb = e->src;
/* It is possible to have a non-simple jump here. Consider a target /* It is possible to have a non-simple jump here. Consider a target
where some forms of unconditional jumps clobber a register. This where some forms of unconditional jumps clobber a register. This
happens on the fr30 for example. happens on the fr30 for example.
...@@ -1261,12 +1251,11 @@ commit_one_edge_insertion (e) ...@@ -1261,12 +1251,11 @@ commit_one_edge_insertion (e)
We know this block has a single successor, so we can just emit We know this block has a single successor, so we can just emit
the queued insns before the jump. */ the queued insns before the jump. */
if (GET_CODE (bb->end) == JUMP_INSN) if (GET_CODE (bb->end) == JUMP_INSN)
{ for (before = bb->end;
before = bb->end; GET_CODE (PREV_INSN (before)) == NOTE
while (GET_CODE (PREV_INSN (before)) == NOTE && NOTE_LINE_NUMBER (PREV_INSN (before)) == NOTE_INSN_LOOP_BEG;
&& NOTE_LINE_NUMBER (PREV_INSN (before)) == NOTE_INSN_LOOP_BEG) before = PREV_INSN (before))
before = PREV_INSN (before); ;
}
else else
{ {
/* We'd better be fallthru, or we've lost track of what's what. */ /* We'd better be fallthru, or we've lost track of what's what. */
...@@ -1306,8 +1295,8 @@ commit_one_edge_insertion (e) ...@@ -1306,8 +1295,8 @@ commit_one_edge_insertion (e)
|| e->succ_next != NULL || e->succ_next != NULL
|| (e->flags & EDGE_FALLTHRU) == 0) || (e->flags & EDGE_FALLTHRU) == 0)
abort (); abort ();
e->flags &= ~EDGE_FALLTHRU;
e->flags &= ~EDGE_FALLTHRU;
emit_barrier_after (last); emit_barrier_after (last);
if (before) if (before)
...@@ -1315,6 +1304,7 @@ commit_one_edge_insertion (e) ...@@ -1315,6 +1304,7 @@ commit_one_edge_insertion (e)
} }
else if (GET_CODE (last) == JUMP_INSN) else if (GET_CODE (last) == JUMP_INSN)
abort (); abort ();
find_sub_basic_blocks (bb); find_sub_basic_blocks (bb);
} }
...@@ -1374,8 +1364,7 @@ dump_bb (bb, outf) ...@@ -1374,8 +1364,7 @@ dump_bb (bb, outf)
dump_regset (bb->global_live_at_start, outf); dump_regset (bb->global_live_at_start, outf);
putc ('\n', outf); putc ('\n', outf);
for (insn = bb->head, last = NEXT_INSN (bb->end); for (insn = bb->head, last = NEXT_INSN (bb->end); insn != last;
insn != last;
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
print_rtl_single (outf, insn); print_rtl_single (outf, insn);
...@@ -1420,12 +1409,12 @@ print_rtl_with_bb (outf, rtx_first) ...@@ -1420,12 +1409,12 @@ print_rtl_with_bb (outf, rtx_first)
int i; int i;
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB }; enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
int max_uid = get_max_uid (); int max_uid = get_max_uid ();
basic_block *start = (basic_block *) basic_block *start
xcalloc (max_uid, sizeof (basic_block)); = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
basic_block *end = (basic_block *) basic_block *end
xcalloc (max_uid, sizeof (basic_block)); = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
enum bb_state *in_bb_p = (enum bb_state *) enum bb_state *in_bb_p
xcalloc (max_uid, sizeof (enum bb_state)); = (enum bb_state *) xcalloc (max_uid, sizeof (enum bb_state));
for (i = n_basic_blocks - 1; i >= 0; i--) for (i = n_basic_blocks - 1; i >= 0; i--)
{ {
...@@ -1437,6 +1426,7 @@ print_rtl_with_bb (outf, rtx_first) ...@@ -1437,6 +1426,7 @@ print_rtl_with_bb (outf, rtx_first)
for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x)) for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
{ {
enum bb_state state = IN_MULTIPLE_BB; enum bb_state state = IN_MULTIPLE_BB;
if (in_bb_p[INSN_UID (x)] == NOT_IN_BB) if (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
state = IN_ONE_BB; state = IN_ONE_BB;
in_bb_p[INSN_UID (x)] = state; in_bb_p[INSN_UID (x)] = state;
...@@ -1508,7 +1498,7 @@ print_rtl_with_bb (outf, rtx_first) ...@@ -1508,7 +1498,7 @@ print_rtl_with_bb (outf, rtx_first)
- scans body of the basic block for JUMP_INSN, CODE_LABEL - scans body of the basic block for JUMP_INSN, CODE_LABEL
and NOTE_INSN_BASIC_BLOCK and NOTE_INSN_BASIC_BLOCK
- check that all insns are in the basic blocks - check that all insns are in the basic blocks
(except the switch handling code, barriers and notes) (except the switch handling code, barriers and notes)
- check that all returns are followed by barriers - check that all returns are followed by barriers
In future it can be extended check a lot of other stuff as well In future it can be extended check a lot of other stuff as well
...@@ -1540,6 +1530,7 @@ verify_flow_info () ...@@ -1540,6 +1530,7 @@ verify_flow_info ()
for (x = last_head; x != NULL_RTX; x = PREV_INSN (x)) for (x = last_head; x != NULL_RTX; x = PREV_INSN (x))
if (x == end) if (x == end)
break; break;
if (!x) if (!x)
{ {
error ("end insn %d for block %d not found in the insn stream", error ("end insn %d for block %d not found in the insn stream",
...@@ -1560,6 +1551,7 @@ verify_flow_info () ...@@ -1560,6 +1551,7 @@ verify_flow_info ()
INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index); INSN_UID (x), bb->index, bb_info[INSN_UID (x)]->index);
err = 1; err = 1;
} }
bb_info[INSN_UID (x)] = bb; bb_info[INSN_UID (x)] = bb;
if (x == head) if (x == head)
...@@ -1582,8 +1574,7 @@ verify_flow_info () ...@@ -1582,8 +1574,7 @@ verify_flow_info ()
int has_fallthru = 0; int has_fallthru = 0;
edge e; edge e;
e = bb->succ; for (e = bb->succ; e; e = e->succ_next)
while (e)
{ {
if (last_visited [e->dest->index + 2] == bb) if (last_visited [e->dest->index + 2] == bb)
{ {
...@@ -1591,6 +1582,7 @@ verify_flow_info () ...@@ -1591,6 +1582,7 @@ verify_flow_info ()
e->src->index, e->dest->index); e->src->index, e->dest->index);
err = 1; err = 1;
} }
last_visited [e->dest->index + 2] = bb; last_visited [e->dest->index + 2] = bb;
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
...@@ -1601,21 +1593,24 @@ verify_flow_info () ...@@ -1601,21 +1593,24 @@ verify_flow_info ()
&& e->dest != EXIT_BLOCK_PTR) && e->dest != EXIT_BLOCK_PTR)
{ {
rtx insn; rtx insn;
if (e->src->index + 1 != e->dest->index) if (e->src->index + 1 != e->dest->index)
{ {
error ("verify_flow_info: Incorrect blocks for fallthru %i->%i", error
e->src->index, e->dest->index); ("verify_flow_info: Incorrect blocks for fallthru %i->%i",
err = 1; e->src->index, e->dest->index);
err = 1;
} }
else else
for (insn = NEXT_INSN (e->src->end); insn != e->dest->head; for (insn = NEXT_INSN (e->src->end); insn != e->dest->head;
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
if (GET_CODE (insn) == BARRIER if (GET_CODE (insn) == BARRIER
#ifndef CASE_DROPS_THROUGH #ifndef CASE_DROPS_THROUGH
|| INSN_P (insn)) || INSN_P (insn)
#else #else
|| (INSN_P (insn) && ! JUMP_TABLE_DATA_P (insn))) || (INSN_P (insn) && ! JUMP_TABLE_DATA_P (insn))
#endif #endif
)
{ {
error ("verify_flow_info: Incorrect fallthru %i->%i", error ("verify_flow_info: Incorrect fallthru %i->%i",
e->src->index, e->dest->index); e->src->index, e->dest->index);
...@@ -1623,6 +1618,7 @@ verify_flow_info () ...@@ -1623,6 +1618,7 @@ verify_flow_info ()
err = 1; err = 1;
} }
} }
if (e->src != bb) if (e->src != bb)
{ {
error ("verify_flow_info: Basic block %d succ edge is corrupted", error ("verify_flow_info: Basic block %d succ edge is corrupted",
...@@ -1634,9 +1630,10 @@ verify_flow_info () ...@@ -1634,9 +1630,10 @@ verify_flow_info ()
fprintf (stderr, "\n"); fprintf (stderr, "\n");
err = 1; err = 1;
} }
edge_checksum[e->dest->index + 2] += (size_t) e; edge_checksum[e->dest->index + 2] += (size_t) e;
e = e->succ_next;
} }
if (!has_fallthru) if (!has_fallthru)
{ {
rtx insn; rtx insn;
...@@ -1654,8 +1651,7 @@ verify_flow_info () ...@@ -1654,8 +1651,7 @@ verify_flow_info ()
} }
} }
e = bb->pred; for (e = bb->pred; e; e = e->pred_next)
while (e)
{ {
if (e->dest != bb) if (e->dest != bb)
{ {
...@@ -1668,20 +1664,23 @@ verify_flow_info () ...@@ -1668,20 +1664,23 @@ verify_flow_info ()
err = 1; err = 1;
} }
edge_checksum[e->dest->index + 2] -= (size_t) e; edge_checksum[e->dest->index + 2] -= (size_t) e;
e = e->pred_next;
} }
for (x = bb->head; x != NEXT_INSN (bb->end); x = NEXT_INSN (x))
if (basic_block_for_insn && BLOCK_FOR_INSN (x) != bb) for (x = bb->head; x != NEXT_INSN (bb->end); x = NEXT_INSN (x))
{ if (basic_block_for_insn && BLOCK_FOR_INSN (x) != bb)
debug_rtx (x); {
if (! BLOCK_FOR_INSN (x)) debug_rtx (x);
error ("insn %d is inside basic block %d but block_for_insn is NULL", if (! BLOCK_FOR_INSN (x))
INSN_UID (x), bb->index); error
else ("insn %d inside basic block %d but block_for_insn is NULL",
error ("insn %d is inside basic block %d but block_for_insn is %i", INSN_UID (x), bb->index);
INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index); else
err = 1; error
} ("insn %d inside basic block %d but block_for_insn is %i",
INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index);
err = 1;
}
/* OK pointers are correct. Now check the header of basic /* OK pointers are correct. Now check the header of basic
block. It ought to contain optional CODE_LABEL followed block. It ought to contain optional CODE_LABEL followed
...@@ -1695,8 +1694,10 @@ verify_flow_info () ...@@ -1695,8 +1694,10 @@ verify_flow_info ()
bb->index); bb->index);
err = 1; err = 1;
} }
x = NEXT_INSN (x); x = NEXT_INSN (x);
} }
if (!NOTE_INSN_BASIC_BLOCK_P (x) || NOTE_BASIC_BLOCK (x) != bb) if (!NOTE_INSN_BASIC_BLOCK_P (x) || NOTE_BASIC_BLOCK (x) != bb)
{ {
error ("NOTE_INSN_BASIC_BLOCK is missing for block %d", error ("NOTE_INSN_BASIC_BLOCK is missing for block %d",
...@@ -1705,42 +1706,38 @@ verify_flow_info () ...@@ -1705,42 +1706,38 @@ verify_flow_info ()
} }
if (bb->end == x) if (bb->end == x)
{ /* Do checks for empty blocks her. e */
/* Do checks for empty blocks here */ ;
}
else else
{ for (x = NEXT_INSN (x); x; x = NEXT_INSN (x))
x = NEXT_INSN (x); {
while (x) if (NOTE_INSN_BASIC_BLOCK_P (x))
{ {
if (NOTE_INSN_BASIC_BLOCK_P (x)) error ("NOTE_INSN_BASIC_BLOCK %d in middle of basic block %d",
{ INSN_UID (x), bb->index);
error ("NOTE_INSN_BASIC_BLOCK %d in the middle of basic block %d", err = 1;
INSN_UID (x), bb->index); }
err = 1;
} if (x == bb->end)
break;
if (x == bb->end)
break;
if (GET_CODE (x) == JUMP_INSN
|| GET_CODE (x) == CODE_LABEL
|| GET_CODE (x) == BARRIER)
{
error ("in basic block %d:", bb->index);
fatal_insn ("flow control insn inside a basic block", x);
}
x = NEXT_INSN (x); if (GET_CODE (x) == JUMP_INSN
} || GET_CODE (x) == CODE_LABEL
} || GET_CODE (x) == BARRIER)
{
error ("in basic block %d:", bb->index);
fatal_insn ("flow control insn inside a basic block", x);
}
}
} }
/* Complete edge checksumming for ENTRY and EXIT. */ /* Complete edge checksumming for ENTRY and EXIT. */
{ {
edge e; edge e;
for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next) for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
edge_checksum[e->dest->index + 2] += (size_t) e; edge_checksum[e->dest->index + 2] += (size_t) e;
for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next) for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
edge_checksum[e->dest->index + 2] -= (size_t) e; edge_checksum[e->dest->index + 2] -= (size_t) e;
} }
...@@ -1754,12 +1751,12 @@ verify_flow_info () ...@@ -1754,12 +1751,12 @@ verify_flow_info ()
last_bb_num_seen = -1; last_bb_num_seen = -1;
num_bb_notes = 0; num_bb_notes = 0;
x = rtx_first; for (x = rtx_first; x; x = NEXT_INSN (x))
while (x)
{ {
if (NOTE_INSN_BASIC_BLOCK_P (x)) if (NOTE_INSN_BASIC_BLOCK_P (x))
{ {
basic_block bb = NOTE_BASIC_BLOCK (x); basic_block bb = NOTE_BASIC_BLOCK (x);
num_bb_notes++; num_bb_notes++;
if (bb->index != last_bb_num_seen + 1) if (bb->index != last_bb_num_seen + 1)
internal_error ("basic blocks not numbered consecutively"); internal_error ("basic blocks not numbered consecutively");
...@@ -1781,9 +1778,7 @@ verify_flow_info () ...@@ -1781,9 +1778,7 @@ verify_flow_info ()
&& GET_CODE (NEXT_INSN (x)) == JUMP_INSN && GET_CODE (NEXT_INSN (x)) == JUMP_INSN
&& (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
|| GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC)) || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
{ x = NEXT_INSN (x);
x = NEXT_INSN (x);
}
/* But in any case, non-deletable labels can appear anywhere. */ /* But in any case, non-deletable labels can appear anywhere. */
break; break;
...@@ -1798,8 +1793,6 @@ verify_flow_info () ...@@ -1798,8 +1793,6 @@ verify_flow_info ()
&& returnjump_p (x) && ! condjump_p (x) && returnjump_p (x) && ! condjump_p (x)
&& ! (NEXT_INSN (x) && GET_CODE (NEXT_INSN (x)) == BARRIER)) && ! (NEXT_INSN (x) && GET_CODE (NEXT_INSN (x)) == BARRIER))
fatal_insn ("return not followed by barrier", x); fatal_insn ("return not followed by barrier", x);
x = NEXT_INSN (x);
} }
if (num_bb_notes != n_basic_blocks) if (num_bb_notes != n_basic_blocks)
...@@ -1828,17 +1821,21 @@ purge_dead_edges (bb) ...@@ -1828,17 +1821,21 @@ purge_dead_edges (bb)
rtx insn = bb->end, note; rtx insn = bb->end, note;
bool purged = false; bool purged = false;
/* ??? This makes no sense since the later test includes more cases. */
if (GET_CODE (insn) == JUMP_INSN && !simplejump_p (insn)) if (GET_CODE (insn) == JUMP_INSN && !simplejump_p (insn))
return false; return false;
if (GET_CODE (insn) == JUMP_INSN) if (GET_CODE (insn) == JUMP_INSN)
{ {
rtx note; rtx note;
edge b,f; edge b,f;
/* We do care only about conditional jumps and simplejumps. */ /* We do care only about conditional jumps and simplejumps. */
if (!any_condjump_p (insn) if (!any_condjump_p (insn)
&& !returnjump_p (insn) && !returnjump_p (insn)
&& !simplejump_p (insn)) && !simplejump_p (insn))
return false; return false;
for (e = bb->succ; e; e = next) for (e = bb->succ; e; e = next)
{ {
next = e->succ_next; next = e->succ_next;
...@@ -1852,19 +1849,23 @@ purge_dead_edges (bb) ...@@ -1852,19 +1849,23 @@ purge_dead_edges (bb)
if ((e->flags & EDGE_FALLTHRU) if ((e->flags & EDGE_FALLTHRU)
&& any_condjump_p (insn)) && any_condjump_p (insn))
continue; continue;
if (e->dest != EXIT_BLOCK_PTR else if (e->dest != EXIT_BLOCK_PTR
&& e->dest->head == JUMP_LABEL (insn)) && e->dest->head == JUMP_LABEL (insn))
continue; continue;
if (e->dest == EXIT_BLOCK_PTR else if (e->dest == EXIT_BLOCK_PTR
&& returnjump_p (insn)) && returnjump_p (insn))
continue; continue;
purged = true; purged = true;
remove_edge (e); remove_edge (e);
} }
if (!bb->succ || !purged) if (!bb->succ || !purged)
return false; return false;
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index); fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
if (!optimize) if (!optimize)
return purged; return purged;
...@@ -1879,6 +1880,7 @@ purge_dead_edges (bb) ...@@ -1879,6 +1880,7 @@ purge_dead_edges (bb)
note = find_reg_note (insn, REG_BR_PROB, NULL); note = find_reg_note (insn, REG_BR_PROB, NULL);
if (!note) if (!note)
return purged; return purged;
b = BRANCH_EDGE (bb); b = BRANCH_EDGE (bb);
f = FALLTHRU_EDGE (bb); f = FALLTHRU_EDGE (bb);
b->probability = INTVAL (XEXP (note, 0)); b->probability = INTVAL (XEXP (note, 0));
...@@ -1886,6 +1888,7 @@ purge_dead_edges (bb) ...@@ -1886,6 +1888,7 @@ purge_dead_edges (bb)
b->count = bb->count * b->probability / REG_BR_PROB_BASE; b->count = bb->count * b->probability / REG_BR_PROB_BASE;
f->count = bb->count * f->probability / REG_BR_PROB_BASE; f->count = bb->count * f->probability / REG_BR_PROB_BASE;
} }
return purged; return purged;
} }
...@@ -1894,6 +1897,7 @@ purge_dead_edges (bb) ...@@ -1894,6 +1897,7 @@ purge_dead_edges (bb)
&& (note = find_reg_note (insn, REG_EH_REGION, NULL))) && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
{ {
rtx eqnote; rtx eqnote;
if (! may_trap_p (PATTERN (insn)) if (! may_trap_p (PATTERN (insn))
|| ((eqnote = find_reg_equal_equiv_note (insn)) || ((eqnote = find_reg_equal_equiv_note (insn))
&& ! may_trap_p (XEXP (eqnote, 0)))) && ! may_trap_p (XEXP (eqnote, 0))))
...@@ -1919,17 +1923,22 @@ purge_dead_edges (bb) ...@@ -1919,17 +1923,22 @@ purge_dead_edges (bb)
edge we know that there used to be a jump here and can then safely edge we know that there used to be a jump here and can then safely
remove all non-fallthru edges. */ remove all non-fallthru edges. */
for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU)); for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU));
e = e->succ_next); e = e->succ_next)
;
if (!e) if (!e)
return purged; return purged;
for (e = bb->succ; e; e = next) for (e = bb->succ; e; e = next)
{ {
next = e->succ_next; next = e->succ_next;
if (!(e->flags & EDGE_FALLTHRU)) if (!(e->flags & EDGE_FALLTHRU))
remove_edge (e), purged = true; remove_edge (e), purged = true;
} }
if (!bb->succ || bb->succ->succ_next) if (!bb->succ || bb->succ->succ_next)
abort (); abort ();
bb->succ->probability = REG_BR_PROB_BASE; bb->succ->probability = REG_BR_PROB_BASE;
bb->succ->count = bb->count; bb->succ->count = bb->count;
...@@ -1939,10 +1948,8 @@ purge_dead_edges (bb) ...@@ -1939,10 +1948,8 @@ purge_dead_edges (bb)
return purged; return purged;
} }
/* Search all basic blocks for potentially dead edges and purge them. /* Search all basic blocks for potentially dead edges and purge them. Return
true if some edge has been eliminated. */
Return true iff some edge has been eliminated.
*/
bool bool
purge_all_dead_edges (update_life_p) purge_all_dead_edges (update_life_p)
...@@ -1956,18 +1963,21 @@ purge_all_dead_edges (update_life_p) ...@@ -1956,18 +1963,21 @@ purge_all_dead_edges (update_life_p)
blocks = sbitmap_alloc (n_basic_blocks); blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks); sbitmap_zero (blocks);
} }
for (i = 0; i < n_basic_blocks; i++) for (i = 0; i < n_basic_blocks; i++)
{ {
bool purged_here; bool purged_here = purge_dead_edges (BASIC_BLOCK (i));
purged_here = purge_dead_edges (BASIC_BLOCK (i));
purged |= purged_here; purged |= purged_here;
if (purged_here && update_life_p) if (purged_here && update_life_p)
SET_BIT (blocks, i); SET_BIT (blocks, i);
} }
if (update_life_p && purged) if (update_life_p && purged)
update_life_info (blocks, UPDATE_LIFE_GLOBAL, update_life_info (blocks, UPDATE_LIFE_GLOBAL,
PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
| PROP_KILL_DEAD_CODE); | PROP_KILL_DEAD_CODE);
if (update_life_p) if (update_life_p)
sbitmap_free (blocks); sbitmap_free (blocks);
return purged; return purged;
......
...@@ -1483,6 +1483,7 @@ typedef int (*rtx_function) PARAMS ((rtx *, void *)); ...@@ -1483,6 +1483,7 @@ typedef int (*rtx_function) PARAMS ((rtx *, void *));
extern int for_each_rtx PARAMS ((rtx *, rtx_function, void *)); extern int for_each_rtx PARAMS ((rtx *, rtx_function, void *));
extern rtx regno_use_in PARAMS ((unsigned int, rtx)); extern rtx regno_use_in PARAMS ((unsigned int, rtx));
extern int auto_inc_p PARAMS ((rtx)); extern int auto_inc_p PARAMS ((rtx));
extern int in_expr_list_p PARAMS ((rtx, rtx));
extern void remove_node_from_expr_list PARAMS ((rtx, rtx *)); extern void remove_node_from_expr_list PARAMS ((rtx, rtx *));
extern int insns_safe_to_move_p PARAMS ((rtx, rtx, rtx *)); extern int insns_safe_to_move_p PARAMS ((rtx, rtx, rtx *));
extern int loc_mentioned_in_p PARAMS ((rtx *, rtx)); extern int loc_mentioned_in_p PARAMS ((rtx *, rtx));
......
...@@ -1954,6 +1954,24 @@ remove_note (insn, note) ...@@ -1954,6 +1954,24 @@ remove_note (insn, note)
} }
/* Search LISTP (an EXPR_LIST) for an entry whose first operand is NODE and /* Search LISTP (an EXPR_LIST) for an entry whose first operand is NODE and
return 1 if it is found. A simple equality test is used to determine if
NODE matches. */
int
in_expr_list_p (listp, node)
rtx listp;
rtx node;
{
rtx x;
for (x = listp; x; x = XEXP (x, 1))
if (node == XEXP (x, 0))
return 1;
return 0;
}
/* Search LISTP (an EXPR_LIST) for an entry whose first operand is NODE and
remove that entry from the list if it is found. remove that entry from the list if it is found.
A simple equality test is used to determine if NODE matches. */ A simple equality test is used to determine if NODE matches. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment