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
This commit is contained in:
Richard Kenner 2001-12-24 15:44:45 +00:00 committed by Richard Kenner
parent e88712b55b
commit 5f0d23589f
7 changed files with 554 additions and 534 deletions

View File

@ -1,3 +1,10 @@
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>
PR c/5163:

View File

@ -47,21 +47,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h"
/* 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. */
BB_UPDATE_LIFE = 1,
/* Set if BB is the forwarder block to avoid too many
forwarder_block_p calls. */
BB_FORWARDER_BLOCK = 2
};
};
#define BB_FLAGS(bb) (enum bb_flags)(bb)->aux
#define BB_SET_FLAG(bb,flag) \
(bb)->aux = (void *) (long) ((enum bb_flags)(bb)->aux | (flag))
#define BB_CLEAR_FLAG(bb,flag) \
(bb)->aux = (void *) (long) ((enum bb_flags)(bb)->aux & ~(flag))
#define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
#define BB_SET_FLAG(BB, FLAG) \
(BB)->aux = (void *) (long) ((enum bb_flags) (BB)->aux | (FLAG))
#define BB_CLEAR_FLAG(BB, 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_bb PARAMS ((int, basic_block));
@ -96,6 +98,7 @@ notice_new_block (bb)
{
if (!bb)
return;
BB_SET_FLAG (bb, BB_UPDATE_LIFE);
if (forwarder_block_p (bb))
BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
@ -183,6 +186,7 @@ try_simplify_condjump (cbranch_block)
/* Attempt to prove that operation is NOOP using CSElib or mark the effect
on register. Used by jump threading. */
static bool
mark_effect (exp, nonequal)
rtx exp;
@ -196,6 +200,7 @@ mark_effect (exp, nonequal)
if (REG_P (XEXP (exp, 0)))
CLEAR_REGNO_REG_SET (nonequal, REGNO (XEXP (exp, 0)));
return false;
case SET:
if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
return false;
@ -203,6 +208,7 @@ mark_effect (exp, nonequal)
return true;
SET_REGNO_REG_SET (nonequal, REGNO (SET_SRC (exp)));
return false;
default:
return false;
}
@ -281,10 +287,11 @@ thread_jump (mode, e, b)
nonequal = BITMAP_XMALLOC();
CLEAR_REG_SET (nonequal);
/* Now assume that we've continued by the edge E to B and continue
processing as if it were same basic block.
Our goal is to prove that whole block is an NOOP. */
for (insn = NEXT_INSN (b->head); insn != b->end && !failed;
insn = NEXT_INSN (insn))
{
@ -300,6 +307,7 @@ thread_jump (mode, e, b)
else
failed |= mark_effect (pat, nonequal);
}
cselib_process_insn (insn);
}
@ -340,7 +348,7 @@ try_forward_edges (mode, b)
bool changed = false;
edge e, next, threaded_edge;
for (e = b->succ; e ; e = next)
for (e = b->succ; e; e = next)
{
basic_block target, first;
int counter;
@ -372,6 +380,7 @@ try_forward_edges (mode, b)
counter = n_basic_blocks;
new_target = target->succ->dest;
}
/* Allow to thread only over one edge at time to simplify updating
of probabilities. */
else if ((mode & CLEANUP_THREADING) && !threaded)
@ -383,6 +392,7 @@ try_forward_edges (mode, b)
new_target_threaded = true;
}
}
if (!new_target)
break;
@ -400,7 +410,7 @@ try_forward_edges (mode, b)
if (GET_CODE (insn) != NOTE)
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))
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
@ -409,6 +419,7 @@ try_forward_edges (mode, b)
if (GET_CODE (insn) == NOTE)
break;
}
counter++;
target = new_target;
threaded |= new_target_threaded;
@ -438,10 +449,12 @@ try_forward_edges (mode, b)
else if (!redirect_edge_and_branch (e, target))
{
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);
continue;
}
/* We successfully forwarded the edge. Now update profile
data: for each edge we traversed in the chain, remove
the original edge's execution count. */
@ -456,6 +469,7 @@ try_forward_edges (mode, b)
do
{
edge t;
first->count -= edge_count;
first->succ->count -= edge_count;
first->frequency -= edge_frequency;
@ -463,6 +477,7 @@ try_forward_edges (mode, b)
t = threaded_edge;
else
t = first->succ;
first = t->dest;
}
while (first != target);
@ -553,10 +568,8 @@ merge_blocks_move_predecessor_nojumps (a, b)
BB_SET_FLAG (a, BB_UPDATE_LIFE);
if (rtl_dump_file)
{
fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
a->index, b->index);
}
fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
a->index, b->index);
/* 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
@ -623,10 +636,8 @@ merge_blocks_move_successor_nojumps (a, b)
BB_SET_FLAG (a, BB_UPDATE_LIFE);
if (rtl_dump_file)
{
fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
b->index, a->index);
}
fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
b->index, a->index);
}
/* Attempt to merge basic blocks that are potentially non-adjacent.
@ -660,13 +671,12 @@ merge_blocks (e, b, c, mode)
update_forwarder_flag (b);
if (rtl_dump_file)
{
fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
b->index, c->index);
}
fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
b->index, c->index);
return true;
}
/* Otherwise we will need to move code around. Do that only if expensive
transformations are allowed. */
else if (mode & CLEANUP_EXPENSIVE)
@ -689,11 +699,13 @@ merge_blocks (e, b, c, mode)
for (tmp_edge = c->succ; tmp_edge; tmp_edge = tmp_edge->succ_next)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
c_has_outgoing_fallthru = (tmp_edge != NULL);
for (tmp_edge = b->pred; tmp_edge; tmp_edge = tmp_edge->pred_next)
if (tmp_edge->flags & EDGE_FALLTHRU)
break;
b_has_incoming_fallthru = (tmp_edge != NULL);
b_fallthru_edge = tmp_edge;
@ -714,6 +726,7 @@ merge_blocks (e, b, c, mode)
if (b_has_incoming_fallthru)
{
basic_block bb;
if (b_fallthru_edge->src == ENTRY_BLOCK_PTR)
return false;
bb = force_nonfallthru (b_fallthru_edge);
@ -722,9 +735,11 @@ merge_blocks (e, b, c, mode)
else
BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE);
}
merge_blocks_move_predecessor_nojumps (b, c);
return true;
}
return false;
}
@ -825,8 +840,10 @@ insns_match_p (mode, i1, i2)
return true;
}
}
return false;
}
return true;
}
@ -857,6 +874,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
last1 = i1;
i1 = PREV_INSN (i1);
}
i2 = bb2->end;
if (onlyjump_p (i2)
|| (returnjump_p (i2) && !side_effects_p (PATTERN (i2))))
@ -873,6 +891,7 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
/* Ignore notes. */
while (!active_insn_p (i1) && i1 != bb1->head)
i1 = PREV_INSN (i1);
while (!active_insn_p (i2) && i2 != bb2->head)
i2 = PREV_INSN (i2);
@ -905,18 +924,16 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
last1 = i1, last2 = i2;
ninsns++;
}
i1 = PREV_INSN (i1);
i2 = PREV_INSN (i2);
}
#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. */
if (reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1))
last1 = afterlast1, last2 = afterlast2, ninsns--;
}
/* Don't allow the insn after a compare to be shared by
cross-jumping unless the compare is also shared. */
if (ninsns && reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1))
last1 = afterlast1, last2 = afterlast2, ninsns--;
#endif
/* Include preceding notes and labels in the cross-jump. One,
@ -926,10 +943,13 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
{
while (last1 != bb1->head && !active_insn_p (PREV_INSN (last1)))
last1 = PREV_INSN (last1);
if (last1 != bb1->head && GET_CODE (PREV_INSN (last1)) == CODE_LABEL)
last1 = PREV_INSN (last1);
while (last2 != bb2->head && !active_insn_p (PREV_INSN (last2)))
last2 = PREV_INSN (last2);
if (last2 != bb2->head && GET_CODE (PREV_INSN (last2)) == CODE_LABEL)
last2 = PREV_INSN (last2);
@ -960,12 +980,8 @@ outgoing_edges_match (mode, bb1, bb2)
unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next
&& !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
{
if (! bb2->succ || bb2->succ->succ_next
|| (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
return false;
return true;
}
return (bb2->succ && !bb2->succ->succ_next
&& (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0);
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */
@ -996,6 +1012,7 @@ outgoing_edges_match (mode, bb1, bb2)
should be optimized out already. */
if (FORWARDER_BLOCK_P (f1->dest))
f1 = f1->dest->succ;
if (FORWARDER_BLOCK_P (f2->dest))
f2 = f2->dest->succ;
@ -1028,6 +1045,7 @@ outgoing_edges_match (mode, bb1, bb2)
code2 = reversed_comparison_code (cond2, bb2->end);
else
code2 = GET_CODE (cond2);
if (code2 == UNKNOWN)
return false;
@ -1052,6 +1070,7 @@ outgoing_edges_match (mode, bb1, bb2)
{
rtx note1, note2;
int prob1, prob2;
note1 = find_reg_note (bb1->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)
if (abs (prob1 - prob2) > REG_BR_PROB_BASE / 20)
return false;
}
else if (note1 || note2)
return false;
}
@ -1096,19 +1116,20 @@ outgoing_edges_match (mode, bb1, bb2)
{
if (e1->flags & EDGE_EH)
nehedges1++;
if (e2->flags & EDGE_EH)
nehedges2++;
if (e1->flags & EDGE_FALLTHRU)
fallthru1 = e1;
if (e2->flags & EDGE_FALLTHRU)
fallthru2 = e2;
}
/* If number of edges of various types does not match, fail. */
if (e1 || e2)
return false;
if (nehedges1 != nehedges2)
return false;
if ((fallthru1 != 0) != (fallthru2 != 0))
if (e1 || e2
|| nehedges1 != nehedges2
|| (fallthru1 != 0) != (fallthru2 != 0))
return false;
/* fallthru edges must be forwarded to the same destination. */
@ -1118,17 +1139,21 @@ outgoing_edges_match (mode, bb1, bb2)
? fallthru1->dest->succ->dest: fallthru1->dest);
basic_block d2 = (forwarder_block_p (fallthru2->dest)
? fallthru2->dest->succ->dest: fallthru2->dest);
if (d1 != d2)
return false;
}
/* In case we do have EH edges, ensure we are in the same region. */
if (nehedges1)
{
rtx n1 = find_reg_note (bb1->end, REG_EH_REGION, 0);
rtx n2 = find_reg_note (bb2->end, REG_EH_REGION, 0);
if (XEXP (n1, 0) != XEXP (n2, 0))
return false;
}
/* We don't need to match the rest of edges as above checks should be enought
to ensure that they are equivalent. */
return true;
@ -1159,17 +1184,12 @@ try_crossjump_to_edge (mode, e1, e2)
if (src1->pred
&& !src1->pred->pred_next
&& FORWARDER_BLOCK_P (src1))
{
e1 = src1->pred;
src1 = e1->src;
}
e1 = src1->pred, src1 = e1->src;
if (src2->pred
&& !src2->pred->pred_next
&& 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. */
if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR)
@ -1181,6 +1201,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (FORWARDER_BLOCK_P (e1->dest)
&& FORWARDER_BLOCK_P (e1->dest->succ->dest))
return false;
if (FORWARDER_BLOCK_P (e2->dest)
&& FORWARDER_BLOCK_P (e2->dest->succ->dest))
return false;
@ -1226,6 +1247,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (FORWARDER_BLOCK_P (d))
d = d->succ->dest;
for (s2 = src1->succ; ; s2 = s2->succ_next)
{
basic_block d2 = s2->dest;
@ -1234,6 +1256,7 @@ try_crossjump_to_edge (mode, e1, e2)
if (d == d2)
break;
}
s->count += s2->count;
/* Take care to update possible forwarder blocks. We verified
@ -1245,19 +1268,21 @@ try_crossjump_to_edge (mode, e1, e2)
s->dest->count += s2->count;
s->dest->frequency += EDGE_FREQUENCY (s);
}
if (FORWARDER_BLOCK_P (s2->dest))
{
s2->dest->succ->count -= s2->count;
s2->dest->count -= s2->count;
s2->dest->frequency -= EDGE_FREQUENCY (s);
}
if (!redirect_to->frequency && !src1->frequency)
s->probability = (s->probability + s2->probability) / 2;
else
s->probability =
((s->probability * redirect_to->frequency +
s2->probability * src1->frequency)
/ (redirect_to->frequency + src1->frequency));
s->probability
= ((s->probability * redirect_to->frequency +
s2->probability * src1->frequency)
/ (redirect_to->frequency + src1->frequency));
}
note = find_reg_note (redirect_to->end, REG_BR_PROB, 0);
@ -1269,6 +1294,7 @@ try_crossjump_to_edge (mode, e1, e2)
/* Skip possible basic block header. */
if (GET_CODE (newpos1) == CODE_LABEL)
newpos1 = NEXT_INSN (newpos1);
if (GET_CODE (newpos1) == NOTE)
newpos1 = NEXT_INSN (newpos1);
last = src1->end;
@ -1409,7 +1435,6 @@ try_optimize_cfg (mode)
/* Attempt to merge blocks as made possible by edge removal. If a block
has only one successor, and the successor has only one predecessor,
they may be combined. */
do
{
changed = false;
@ -1431,6 +1456,7 @@ try_optimize_cfg (mode)
c = BASIC_BLOCK (b->index - 1);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleting block %i.\n", b->index);
flow_delete_block (b);
changed = true;
b = c;
@ -1455,6 +1481,7 @@ try_optimize_cfg (mode)
|| ! label_is_jump_target_p (b->head, b->pred->src->end)))
{
rtx label = b->head;
b->head = NEXT_INSN (b->head);
delete_insn_chain (label, label);
if (rtl_dump_file)
@ -1475,6 +1502,7 @@ try_optimize_cfg (mode)
if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleting fallthru block %i.\n",
b->index);
c = BASIC_BLOCK (b->index ? b->index - 1 : 1);
redirect_edge_succ_nodup (b->pred, b->succ->dest);
flow_delete_block (b);
@ -1554,6 +1582,7 @@ try_optimize_cfg (mode)
if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall)
{
bool found = 0;
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
for (i = 0; i < n_basic_blocks; i++)
@ -1562,12 +1591,14 @@ try_optimize_cfg (mode)
found = 1;
SET_BIT (blocks, i);
}
if (found)
update_life_info (blocks, UPDATE_LIFE_GLOBAL,
PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
| PROP_KILL_DEAD_CODE);
sbitmap_free (blocks);
}
for (i = 0; i < n_basic_blocks; i++)
BASIC_BLOCK (i)->aux = NULL;

View File

@ -1,22 +1,22 @@
/* Basic block reordering routines for the GNU compiler.
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
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
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
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
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
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "config.h"
#include "system.h"
@ -30,9 +30,7 @@
#include "cfglayout.h"
/* The contents of the current function definition are allocated
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. */
in this obstack, and all are freed at the end of the function. */
extern struct obstack flow_obstack;
@ -126,7 +124,7 @@ skip_insns_after_block (bb)
if (bb->index + 1 != n_basic_blocks)
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)
break;
@ -172,30 +170,30 @@ skip_insns_after_block (bb)
break;
}
/* It is possible to hit contradicting sequence. For instance:
/* It is possible to hit contradictory sequence. For instance:
jump_insn
NOTE_INSN_LOOP_BEG
barrier
Where barrier belongs to jump_insn, but the note does not.
This can be created by removing the basic block originally
following NOTE_INSN_LOOP_BEG.
Where barrier belongs to jump_insn, but the note does not. This can be
created by removing the basic block originally following
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)
{
prev = PREV_INSN (insn);
if (GET_CODE (insn) == NOTE)
switch (NOTE_LINE_NUMBER (insn))
{
prev = PREV_INSN (insn);
if (GET_CODE (insn) == NOTE)
switch (NOTE_LINE_NUMBER (insn))
{
case NOTE_INSN_LOOP_END:
case NOTE_INSN_BLOCK_END:
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
continue;
continue;
default:
reorder_insns (insn, insn, last_insn);
reorder_insns (insn, insn, last_insn);
}
}
@ -213,8 +211,7 @@ label_for_bb (bb)
if (GET_CODE (label) != CODE_LABEL)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, "Emitting label for block %d\n",
bb->index);
fprintf (rtl_dump_file, "Emitting label for block %d\n", bb->index);
label = block_label (bb);
if (bb->head == PREV_INSN (RBI (bb)->eff_head))
@ -233,7 +230,7 @@ record_effective_endpoints ()
rtx next_insn = get_insns ();
int i;
for (i = 0; i < n_basic_blocks; ++i)
for (i = 0; i < n_basic_blocks; i++)
{
basic_block bb = BASIC_BLOCK (i);
rtx end;
@ -243,32 +240,33 @@ record_effective_endpoints ()
RBI (bb)->eff_end = end;
next_insn = NEXT_INSN (end);
}
function_tail_eff_head = next_insn;
}
/* Return the next NOTE_INSN_BASIC_BLOCK after X. */
static rtx
get_next_bb_note (x)
rtx x;
{
while (x)
{
if (NOTE_INSN_BASIC_BLOCK_P (x))
return x;
x = NEXT_INSN (x);
}
for (; x; x = NEXT_INSN (x))
if (NOTE_INSN_BASIC_BLOCK_P (x))
return x;
return NULL;
}
/* Return the fist NOTE_INSN_BASIC_BLOCK before X. */
static rtx
get_prev_bb_note (x)
rtx x;
{
while (x)
{
if (NOTE_INSN_BASIC_BLOCK_P (x))
return x;
x = PREV_INSN (x);
}
for (; x; x = PREV_INSN (x))
if (NOTE_INSN_BASIC_BLOCK_P (x))
return x;
return NULL;
}
@ -313,6 +311,7 @@ relate_bbs_with_scopes (s)
bbnote = get_next_bb_note (s->note_beg);
if (! bbnote)
abort ();
if (NOTE_BASIC_BLOCK (bbnote) == s->bb_end)
{
bbs_spanned = 0;
@ -335,6 +334,7 @@ relate_bbs_with_scopes (s)
bbnote = get_prev_bb_note (s->note_end);
if (! bbnote)
abort ();
if (NOTE_BASIC_BLOCK (bbnote) == s->bb_beg)
{
bbs_spanned = 0;
@ -357,16 +357,15 @@ relate_bbs_with_scopes (s)
bbs_spanned = 0;
else
{
rtx x1, x2;
/* Both notes are outside of any bbs. This implies that all the
basic blocks spanned by the pair of notes are contained in
this scope.
There is a degenerate case to consider. If the notes do not
span any basic blocks, then it is an empty scope that can
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))
{
s->level = -1;
@ -418,6 +417,7 @@ make_new_scope (level, note)
rtx note;
{
scope new_scope = xcalloc (1, sizeof (struct scope_def));
new_scope->level = level;
new_scope->note_beg = note;
return new_scope;
@ -442,6 +442,7 @@ build_scope_forest (forest)
root = NULL;
curr_bb = NULL;
bbi = 0;
for (x = get_insns (); x; x = NEXT_INSN (x))
{
if (bbi < n_basic_blocks && x == BASIC_BLOCK (bbi)->head)
@ -454,8 +455,10 @@ build_scope_forest (forest)
if (root)
{
scope new_scope;
if (! curr_scope)
abort();
level++;
new_scope = make_new_scope (level, x);
new_scope->outer = curr_scope;
@ -471,10 +474,12 @@ build_scope_forest (forest)
curr_scope->inner_last = new_scope;
}
curr_scope = curr_scope->inner_last;
}
else
{
int ntrees = forest->num_trees;
level++;
curr_scope = make_new_scope (level, x);
root = curr_scope;
@ -482,6 +487,7 @@ build_scope_forest (forest)
sizeof (scope) * (ntrees + 1));
forest->trees[forest->num_trees++] = root;
}
curr_scope->bb_beg = curr_bb;
}
else if (NOTE_LINE_NUMBER (x) == NOTE_INSN_BLOCK_END)
@ -493,22 +499,21 @@ build_scope_forest (forest)
if (level == -1)
root = NULL;
}
} /* if note */
}
if (curr_bb && curr_bb->end == x)
{
curr_bb = NULL;
bbi++;
}
} /* for */
}
for (i = 0; i < forest->num_trees; i++)
relate_bbs_with_scopes (forest->trees[i]);
}
/* Remove all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from
the insn chain. */
/* Remove all NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes from the insn
chain. */
static void
remove_scope_notes ()
@ -572,7 +577,6 @@ insert_intra_1 (s, ip, bb)
}
}
/* Insert NOTE_INSN_BLOCK_END notes and NOTE_INSN_BLOCK_BEG notes for
scopes that are contained within BB. */
@ -598,7 +602,6 @@ insert_intra_bb_scope_notes (bb)
}
}
/* Given two consecutive basic blocks BB1 and BB2 with different scopes,
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
@ -619,8 +622,10 @@ insert_inter_bb_scope_notes (bb1, bb2)
{
scope s1 = RBI (bb1)->scope;
scope s2 = RBI (bb2)->scope;
if (! s1 && ! s2)
return;
if (! s1)
bb1 = NULL;
else if (! s2)
@ -632,10 +637,9 @@ insert_inter_bb_scope_notes (bb1, bb2)
{
scope s1 = RBI (bb1)->scope;
scope s2 = RBI (bb2)->scope;
while (s1 != s2)
{
if (! (s1 && s2))
abort ();
if (s1->level > s2->level)
s1 = s1->outer;
else if (s2->level > s1->level)
@ -646,6 +650,7 @@ insert_inter_bb_scope_notes (bb1, bb2)
s2 = s2->outer;
}
}
com = s1;
}
else
@ -655,18 +660,16 @@ insert_inter_bb_scope_notes (bb1, bb2)
if (bb1)
{
rtx end = bb1->end;
scope s;
scope s = RBI (bb1)->scope;
ip = RBI (bb1)->eff_end;
while (s != com)
{
if (NOTE_BLOCK (s->note_beg))
{
ip = emit_note_after (NOTE_INSN_BLOCK_END, ip);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end);
}
s = s->outer;
}
for (s = RBI (bb1)->scope; s != com; s = s->outer)
if (NOTE_BLOCK (s->note_beg))
{
ip = emit_note_after (NOTE_INSN_BLOCK_END, ip);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_end);
}
/* Emitting note may move the end of basic block to unwanted place. */
bb1->end = end;
}
@ -674,17 +677,15 @@ insert_inter_bb_scope_notes (bb1, bb2)
/* Open scopes. */
if (bb2)
{
scope s = RBI (bb2)->scope;
scope s;
ip = bb2->head;
while (s != com)
{
if (NOTE_BLOCK (s->note_beg))
{
ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg);
}
s = s->outer;
}
for (s = RBI (bb2)->scope; s != com; s = s->outer)
if (NOTE_BLOCK (s->note_beg))
{
ip = emit_note_before (NOTE_INSN_BLOCK_BEG, ip);
NOTE_BLOCK (ip) = NOTE_BLOCK (s->note_beg);
}
}
}
@ -709,6 +710,7 @@ rebuild_scope_notes (forest)
{
basic_block bb1 = BASIC_BLOCK (i);
basic_block bb2 = BASIC_BLOCK (i + 1);
if (RBI (bb1)->scope != RBI (bb2)->scope)
insert_inter_bb_scope_notes (bb1, bb2);
insert_intra_bb_scope_notes (bb1);
@ -745,6 +747,7 @@ free_scope_forest (forest)
scope_forest_info *forest;
{
int i;
for (i = 0; i < forest->num_trees; i++)
free_scope_forest_1 (forest->trees[i]);
}
@ -755,15 +758,15 @@ void
dump_scope_forest (forest)
scope_forest_info *forest;
{
int i;
if (forest->num_trees == 0)
fprintf (stderr, "\n< Empty scope forest >\n");
else
{
int i;
fprintf (stderr, "\n< Scope forest >\n");
for (i = 0; i < forest->num_trees; i++)
dump_scope_forest_1 (forest->trees[i], 0);
}
fprintf (stderr, "\n< Scope forest >\n");
for (i = 0; i < forest->num_trees; i++)
dump_scope_forest_1 (forest->trees[i], 0);
}
/* Recursive portion of dump_scope_forest. */
@ -813,33 +816,28 @@ fixup_reorder_chain ()
/* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */
last_bb = BASIC_BLOCK (0);
bb = RBI (last_bb)->next;
index = 1;
while (bb)
for (last_bb = BASIC_BLOCK (0), bb = RBI (last_bb)->next, index = 1;
bb != 0;
last_bb = bb, bb = RBI (bb)->next, index++)
{
rtx last_e = RBI (last_bb)->eff_end;
rtx curr_h = RBI (bb)->eff_head;
NEXT_INSN (last_e) = curr_h;
PREV_INSN (curr_h) = last_e;
last_bb = bb;
bb = RBI (bb)->next;
index++;
}
if (index != n_basic_blocks)
abort ();
insn = RBI (last_bb)->eff_end;
NEXT_INSN (insn) = function_tail_eff_head;
if (function_tail_eff_head)
PREV_INSN (function_tail_eff_head) = insn;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
set_last_insn (insn);
#ifdef ENABLE_CHECKING
verify_insn_chain ();
@ -884,6 +882,7 @@ fixup_reorder_chain ()
if (RBI (bb)->next != e_taken->dest)
{
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
if (note
&& INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
&& invert_jump (bb_end_insn,
@ -913,6 +912,7 @@ fixup_reorder_chain ()
99% case, there should not have been a fallthru edge. */
if (! e_fall)
continue;
#ifdef CASE_DROPS_THROUGH
/* Except for VAX. Since we didn't have predication for the
tablejump, the fallthru block should not have moved. */
@ -936,15 +936,13 @@ fixup_reorder_chain ()
if (RBI (bb)->next == e_fall->dest)
continue;
/* An fallthru to exit block. */
/* A fallthru to exit block. */
if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR)
continue;
}
/* We got here if we need to add a new jump insn. */
nb = force_nonfallthru (e_fall);
if (nb)
{
alloc_aux_for_block (nb, sizeof (struct reorder_block_def));
@ -965,18 +963,17 @@ fixup_reorder_chain ()
if (rtl_dump_file)
fprintf (rtl_dump_file, "Reordered sequence:\n");
while (bb)
for (; bb; bb = RBI (bb)->next, index++)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, " %i %sbb %i freq %i\n", index,
bb->index >= old_n_basic_blocks ? "compensation " : "",
bb->index,
bb->frequency);
bb->index = index;
BASIC_BLOCK (index) = bb;
bb = RBI (bb)->next;
index++;
}
}
@ -989,62 +986,31 @@ fixup_reorder_chain ()
void
verify_insn_chain ()
{
rtx x,
prevx,
nextx;
int insn_cnt1,
insn_cnt2;
rtx x, prevx, 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;
}
for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
x != 0;
prevx = x, insn_cnt1++, x = NEXT_INSN (x))
if (PREV_INSN (x) != prevx)
abort ();
if (prevx != get_last_insn ())
{
fprintf (stderr, "last_insn corrupt.\n");
abort ();
}
abort ();
nextx = NULL;
insn_cnt2 = 1;
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;
}
for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
x != 0;
nextx = x, insn_cnt2++, x = PREV_INSN (x))
if (NEXT_INSN (x) != nextx)
abort ();
if (insn_cnt1 != insn_cnt2)
{
fprintf (stderr, "insn_cnt1 (%d) not equal to insn_cnt2 (%d).\n",
insn_cnt1, insn_cnt2);
abort ();
}
abort ();
}
/* The block falling through to exit must be the last one in the
reordered chain. Ensure that this condition is met. */
/* The block falling through to exit must be the last one in the reordered
chain. Ensure it is. */
static void
fixup_fallthru_exit_predecessor ()
{
@ -1054,21 +1020,25 @@ fixup_fallthru_exit_predecessor ()
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU)
bb = e->src;
if (bb && RBI (bb)->next)
{
basic_block c = BASIC_BLOCK (0);
while (RBI (c)->next != bb)
c = RBI (c)->next;
RBI (c)->next = RBI (bb)->next;
while (RBI (c)->next)
c = RBI (c)->next;
RBI (c)->next = bb;
RBI (bb)->next = NULL;
}
}
/* Main entry point to this module - initialize the datastructures for
CFG layout changes. */
/* Main entry point to this module: initialize the datastructures for CFG
layout changes. */
void
cfg_layout_initialize ()
@ -1081,14 +1051,15 @@ cfg_layout_initialize ()
record_effective_endpoints ();
}
/* Finalize the changes - reorder insn list according to the sequence,
enter compensation code, rebuild scope forest. */
/* Finalize the changes: reorder insn list according to the sequence, enter
compensation code, rebuild scope forest. */
void
cfg_layout_finalize ()
{
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
#ifdef ENABLE_CHECKING
verify_insn_chain ();
#endif

View File

@ -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,
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 void flow_loop_pre_header_scan PARAMS ((struct loop *));
static int flow_loop_nodes_find PARAMS ((basic_block, basic_block,
sbitmap));
static void flow_loop_pre_header_scan PARAMS ((struct loop *));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
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 int flow_loop_level_compute PARAMS ((struct loop *, int));
static int flow_loops_level_compute PARAMS ((struct loops *));
@ -68,14 +70,17 @@ flow_loops_cfg_dump (loops, file)
fputs (";; DFS order: ", file);
for (i = 0; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.dfs_order[i]);
fputs ("\n", file);
}
/* Dump the reverse completion node order. */
if (loops->cfg.rc_order)
{
fputs (";; RC order: ", file);
for (i = 0; i < n_basic_blocks; i++)
fprintf (file, "%d ", loops->cfg.rc_order[i]);
fputs ("\n", file);
}
}
@ -107,12 +112,10 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
fprintf (file, ";;\n;; Loop %d (%d to %d):%s%s\n",
loop->num, INSN_UID (loop->first->head),
INSN_UID (loop->last->end),
loop->shared ? " shared" : "",
loop->invalid ? " invalid" : "");
loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
else
fprintf (file, ";;\n;; Loop %d:%s%s\n", loop->num,
loop->shared ? " shared" : "",
loop->invalid ? " invalid" : "");
loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
fprintf (file, ";; header %d, latch %d, pre-header %d, first %d, last %d\n",
loop->header->index, loop->latch->index,
@ -125,14 +128,17 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
if (loop->pre_header_edges)
flow_edge_list_print (";; pre-header edges", loop->pre_header_edges,
loop->num_pre_header_edges, file);
flow_edge_list_print (";; entry edges", loop->entry_edges,
loop->num_entries, file);
fprintf (file, ";; %d", loop->num_nodes);
flow_nodes_print (" nodes", loop->nodes, file);
flow_edge_list_print (";; exit edges", loop->exit_edges,
loop->num_exits, file);
if (loop->exits_doms)
flow_nodes_print (";; exit doms", loop->exits_doms, file);
if (loop_dump_aux)
loop_dump_aux (loop, file, verbose);
}
@ -147,49 +153,42 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose)
void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
int verbose;
{
int i;
int i, j;
int num_loops;
num_loops = loops->num;
if (! num_loops || ! file)
return;
fprintf (file, ";; %d loops found, %d levels\n",
num_loops, loops->levels);
fprintf (file, ";; %d loops found, %d levels\n", num_loops, loops->levels);
for (i = 0; i < num_loops; i++)
{
struct loop *loop = &loops->array[i];
flow_loop_dump (loop, file, loop_dump_aux, verbose);
if (loop->shared)
{
int j;
for (j = 0; j < i; j++)
{
struct loop *oloop = &loops->array[j];
for (j = 0; j < i; j++)
{
struct loop *oloop = &loops->array[j];
if (loop->header == oloop->header)
{
int disjoint;
int smaller;
if (loop->header == oloop->header)
{
int disjoint;
int smaller;
smaller = loop->num_nodes < oloop->num_nodes;
smaller = loop->num_nodes < oloop->num_nodes;
/* If the union of LOOP and OLOOP is different than
the larger of LOOP and OLOOP then LOOP and OLOOP
must be disjoint. */
disjoint = ! flow_loop_nested_p (smaller ? loop : oloop,
smaller ? oloop : loop);
fprintf (file,
";; loop header %d shared by loops %d, %d %s\n",
loop->header->index, i, j,
disjoint ? "disjoint" : "nested");
}
}
}
/* If the union of LOOP and OLOOP is different than
the larger of LOOP and OLOOP then LOOP and OLOOP
must be disjoint. */
disjoint = ! flow_loop_nested_p (smaller ? loop : oloop,
smaller ? oloop : loop);
fprintf (file,
";; loop header %d shared by loops %d, %d %s\n",
loop->header->index, i, j,
disjoint ? "disjoint" : "nested");
}
}
}
if (verbose)
@ -225,11 +224,13 @@ flow_loops_free (loops)
if (loop->exits_doms)
sbitmap_free (loop->exits_doms);
}
free (loops->array);
loops->array = NULL;
if (loops->cfg.dom)
sbitmap_vector_free (loops->cfg.dom);
if (loops->cfg.dfs_order)
free (loops->cfg.dfs_order);
@ -394,42 +395,33 @@ static void
flow_loop_pre_header_scan (loop)
struct loop *loop;
{
int num = 0;
int num;
basic_block ebb;
edge e;
loop->num_pre_header_edges = 0;
if (loop->num_entries != 1)
return;
return;
ebb = loop->entry_edges[0]->src;
if (ebb == ENTRY_BLOCK_PTR)
return;
if (ebb != ENTRY_BLOCK_PTR)
{
edge e;
/* Count number of edges along trace from loop header to
root of pre-header extended basic block. Usually this is
only one or two edges. */
for (num = 1; ebb->pred->src != ENTRY_BLOCK_PTR && ! ebb->pred->pred_next;
num++)
ebb = ebb->pred->src;
/* Count number of edges along trace from loop header to
root of pre-header extended basic block. Usually this is
only one or two edges. */
num++;
while (ebb->pred->src != ENTRY_BLOCK_PTR && ! ebb->pred->pred_next)
{
ebb = ebb->pred->src;
num++;
}
loop->pre_header_edges = (edge *) xmalloc (num * sizeof (edge *));
loop->num_pre_header_edges = num;
loop->pre_header_edges = (edge *) xmalloc (num * sizeof (edge *));
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;
}
}
/* 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
@ -465,6 +457,7 @@ flow_loop_pre_header_find (header, dom)
}
}
}
return pre_header;
}
@ -485,16 +478,13 @@ flow_loop_tree_node_add (prevloop, loop)
return;
}
while (prevloop->outer)
{
if (flow_loop_nested_p (prevloop->outer, loop))
{
prevloop->next = loop;
loop->outer = prevloop->outer;
return;
}
prevloop = prevloop->outer;
}
for (; prevloop->outer; prevloop = prevloop->outer)
if (flow_loop_nested_p (prevloop->outer, loop))
{
prevloop->next = loop;
loop->outer = prevloop->outer;
return;
}
prevloop->next = loop;
loop->outer = NULL;
@ -517,7 +507,8 @@ flow_loops_tree_build (loops)
Since we used a depth first search this should be the
outermost loop. */
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. */
for (i = 1; i < num_loops; i++)
@ -546,13 +537,11 @@ flow_loop_level_compute (loop, depth)
itself). */
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 = ilevel;
level = MAX (ilevel, level);
}
loop->level = level;
loop->depth = depth;
return level;
@ -566,17 +555,17 @@ static int
flow_loops_level_compute (loops)
struct loops *loops;
{
int levels = 0;
struct loop *loop;
int level;
int levels = 0;
/* Traverse all the outer level loops. */
for (loop = loops->tree_root; loop; loop = loop->next)
{
level = flow_loop_level_compute (loop, 1);
if (level > levels)
levels = level;
levels = MAX (levels, level);
}
return levels;
}
@ -594,23 +583,15 @@ flow_loop_scan (loops, loop, flags)
flags |= LOOP_EXIT_EDGES;
if (flags & LOOP_ENTRY_EDGES)
{
/* Find edges which enter the loop header.
Note that the entry edges should only
enter the header of a natural loop. */
loop->num_entries
= flow_loop_entry_edges_find (loop->header,
loop->nodes,
&loop->entry_edges);
}
/* Find edges which enter the loop header. Note that the entry edges
should only enter the header of a natural loop. */
loop->num_entries = flow_loop_entry_edges_find (loop->header, loop->nodes,
&loop->entry_edges);
if (flags & LOOP_EXIT_EDGES)
{
/* Find edges which exit the loop. */
loop->num_exits
= flow_loop_exit_edges_find (loop->nodes,
&loop->exit_edges);
}
/* Find edges which exit the loop. */
loop->num_exits
= flow_loop_exit_edges_find (loop->nodes, &loop->exit_edges);
if (flags & LOOP_EXITS_DOMS)
{
@ -640,13 +621,14 @@ flow_loop_scan (loops, loop, flags)
the loop pre-header. */
flow_loop_pre_header_scan (loop);
}
return 1;
}
/* Find all the natural loops in the function and save in LOOPS structure
and recalculate loop_depth information in basic block structures.
FLAGS controls which loop information is collected.
Return the number of natural loops found. */
/* Find all the natural loops in the function and save in LOOPS structure and
recalculate loop_depth information in basic block structures. FLAGS
controls which loop information is collected. Return the number of natural
loops found. */
int
flow_loops_find (loops, flags)
@ -668,7 +650,7 @@ flow_loops_find (loops, flags)
if (! (flags & LOOP_TREE))
abort ();
memset (loops, 0, sizeof (*loops));
memset (loops, 0, sizeof *loops);
/* Taking care of this degenerate case makes the rest of
this code simpler. */
@ -684,7 +666,6 @@ flow_loops_find (loops, flags)
/* Count the number of loop edges (back edges). This should be the
same as the number of natural loops. */
num_loops = 0;
for (b = 0; b < n_basic_blocks; b++)
{
@ -810,9 +791,7 @@ flow_loops_find (loops, flags)
sbitmap_free (headers);
}
else
{
sbitmap_vector_free (dom);
}
sbitmap_vector_free (dom);
loops->num = num_loops;
@ -828,6 +807,7 @@ flow_loops_find (loops, flags)
/* Update the information regarding the loops in the CFG
specified by LOOPS. */
int
flow_loops_update (loops, flags)
struct loops *loops;
@ -850,5 +830,7 @@ flow_loop_outside_edge_p (loop, e)
{
if (e->dest != loop->header)
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);
}

File diff suppressed because it is too large Load Diff

View File

@ -1483,6 +1483,7 @@ typedef int (*rtx_function) PARAMS ((rtx *, void *));
extern int for_each_rtx PARAMS ((rtx *, rtx_function, void *));
extern rtx regno_use_in PARAMS ((unsigned int, 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 int insns_safe_to_move_p PARAMS ((rtx, rtx, rtx *));
extern int loc_mentioned_in_p PARAMS ((rtx *, rtx));

View File

@ -1953,6 +1953,24 @@ remove_note (insn, note)
abort ();
}
/* 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.