parent
e75b25e7bd
commit
d7e4fe8bb9
87
gcc/flow.c
87
gcc/flow.c
|
@ -309,6 +309,7 @@ flow_analysis (f, nregs, file)
|
||||||
{
|
{
|
||||||
register rtx insn;
|
register rtx insn;
|
||||||
register int i;
|
register int i;
|
||||||
|
rtx nonlocal_label_list = nonlocal_label_rtx_list ();
|
||||||
|
|
||||||
#ifdef ELIMINABLE_REGS
|
#ifdef ELIMINABLE_REGS
|
||||||
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
|
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
|
||||||
|
@ -340,9 +341,11 @@ flow_analysis (f, nregs, file)
|
||||||
if (INSN_UID (insn) > max_uid_for_flow)
|
if (INSN_UID (insn) > max_uid_for_flow)
|
||||||
max_uid_for_flow = INSN_UID (insn);
|
max_uid_for_flow = INSN_UID (insn);
|
||||||
if (code == CODE_LABEL
|
if (code == CODE_LABEL
|
||||||
|| (prev_code != INSN && prev_code != CALL_INSN
|
|| (GET_RTX_CLASS (code) == 'i'
|
||||||
&& prev_code != CODE_LABEL
|
&& (prev_code == JUMP_INSN
|
||||||
&& GET_RTX_CLASS (code) == 'i'))
|
|| (prev_code == CALL_INSN
|
||||||
|
&& nonlocal_label_list != 0)
|
||||||
|
|| prev_code == BARRIER)))
|
||||||
i++;
|
i++;
|
||||||
if (code != NOTE)
|
if (code != NOTE)
|
||||||
prev_code = code;
|
prev_code = code;
|
||||||
|
@ -368,7 +371,7 @@ flow_analysis (f, nregs, file)
|
||||||
uid_volatile = (char *) alloca (max_uid_for_flow + 1);
|
uid_volatile = (char *) alloca (max_uid_for_flow + 1);
|
||||||
bzero (uid_volatile, max_uid_for_flow + 1);
|
bzero (uid_volatile, max_uid_for_flow + 1);
|
||||||
|
|
||||||
find_basic_blocks (f);
|
find_basic_blocks (f, nonlocal_label_list);
|
||||||
life_analysis (f, nregs);
|
life_analysis (f, nregs);
|
||||||
if (file)
|
if (file)
|
||||||
dump_flow_info (file);
|
dump_flow_info (file);
|
||||||
|
@ -381,11 +384,13 @@ flow_analysis (f, nregs, file)
|
||||||
/* Find all basic blocks of the function whose first insn is F.
|
/* Find all basic blocks of the function whose first insn is F.
|
||||||
Store the correct data in the tables that describe the basic blocks,
|
Store the correct data in the tables that describe the basic blocks,
|
||||||
set up the chains of references for each CODE_LABEL, and
|
set up the chains of references for each CODE_LABEL, and
|
||||||
delete any entire basic blocks that cannot be reached. */
|
delete any entire basic blocks that cannot be reached.
|
||||||
|
|
||||||
|
NONLOCAL_LABEL_LIST is the same local variable from flow_analysis. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
find_basic_blocks (f)
|
find_basic_blocks (f, nonlocal_label_list)
|
||||||
rtx f;
|
rtx f, nonlocal_label_list;
|
||||||
{
|
{
|
||||||
register rtx insn;
|
register rtx insn;
|
||||||
register int i;
|
register int i;
|
||||||
|
@ -424,10 +429,13 @@ find_basic_blocks (f)
|
||||||
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
|
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
|
||||||
depth--;
|
depth--;
|
||||||
}
|
}
|
||||||
|
/* A basic block starts at label, or after something that can jump. */
|
||||||
else if (code == CODE_LABEL
|
else if (code == CODE_LABEL
|
||||||
|| (prev_code != INSN && prev_code != CALL_INSN
|
|| (GET_RTX_CLASS (code) == 'i'
|
||||||
&& prev_code != CODE_LABEL
|
&& (prev_code == JUMP_INSN
|
||||||
&& GET_RTX_CLASS (code) == 'i'))
|
|| (prev_code == CALL_INSN
|
||||||
|
&& nonlocal_label_list != 0)
|
||||||
|
|| prev_code == BARRIER)))
|
||||||
{
|
{
|
||||||
basic_block_head[++i] = insn;
|
basic_block_head[++i] = insn;
|
||||||
basic_block_end[i] = insn;
|
basic_block_end[i] = insn;
|
||||||
|
@ -457,13 +465,27 @@ find_basic_blocks (f)
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCK_NUM (insn) = i;
|
BLOCK_NUM (insn) = i;
|
||||||
if (code != NOTE)
|
|
||||||
|
/* Don't separare a CALL_INSN from following CLOBBER insns. This is
|
||||||
|
a kludge that will go away when each CALL_INSN records its
|
||||||
|
USE and CLOBBERs. */
|
||||||
|
|
||||||
|
if (code != NOTE
|
||||||
|
&& ! (prev_code == CALL_INSN && code == INSN
|
||||||
|
&& GET_CODE (PATTERN (insn)) == CLOBBER))
|
||||||
prev_code = code;
|
prev_code = code;
|
||||||
}
|
}
|
||||||
if (i + 1 != n_basic_blocks)
|
if (i + 1 != n_basic_blocks)
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't delete the labels that are referenced by non-jump instructions. */
|
||||||
|
{
|
||||||
|
register rtx x;
|
||||||
|
for (x = label_value_list; x; x = XEXP (x, 1))
|
||||||
|
block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Record which basic blocks control can drop in to. */
|
/* Record which basic blocks control can drop in to. */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -508,6 +530,27 @@ find_basic_blocks (f)
|
||||||
insn, 0);
|
insn, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find all call insns and mark them as possibly jumping
|
||||||
|
to all the nonlocal goto handler labels. */
|
||||||
|
|
||||||
|
for (insn = f; insn; insn = NEXT_INSN (insn))
|
||||||
|
if (GET_CODE (insn) == CALL_INSN)
|
||||||
|
{
|
||||||
|
rtx x;
|
||||||
|
for (x = nonlocal_label_list; x; x = XEXP (x, 1))
|
||||||
|
mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
|
||||||
|
insn, 0);
|
||||||
|
/* ??? This could be made smarter:
|
||||||
|
in some cases it's possible to tell that certain
|
||||||
|
calls will not do a nonlocal goto.
|
||||||
|
|
||||||
|
For example, if the nested functions that do the
|
||||||
|
nonlocal gotos do not have their addresses taken, then
|
||||||
|
only calls to those functions or to other nested
|
||||||
|
functions that use them could possibly do nonlocal
|
||||||
|
gotos. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Pass over all blocks, marking each block that is reachable
|
/* Pass over all blocks, marking each block that is reachable
|
||||||
and has not yet been marked.
|
and has not yet been marked.
|
||||||
Keep doing this until, in one pass, no blocks have been marked.
|
Keep doing this until, in one pass, no blocks have been marked.
|
||||||
|
@ -1472,8 +1515,12 @@ insn_dead_p (x, needed, call_ok)
|
||||||
if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
|
if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
|
||||||
/* Make sure insns to set frame pointer aren't deleted. */
|
/* Make sure insns to set frame pointer aren't deleted. */
|
||||||
|| regno == FRAME_POINTER_REGNUM
|
|| regno == FRAME_POINTER_REGNUM
|
||||||
/* Make sure insns to set arg pointer are never deleted. */
|
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||||
|| regno == ARG_POINTER_REGNUM
|
/* Make sure insns to set arg pointer are never deleted
|
||||||
|
(if the arg pointer isn't fixed, there will be a USE for
|
||||||
|
it, so we can treat it normally). */
|
||||||
|
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
|
||||||
|
#endif
|
||||||
|| (needed[offset] & bit) != 0)
|
|| (needed[offset] & bit) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1692,7 +1739,9 @@ mark_set_1 (needed, dead, x, insn, significant)
|
||||||
|
|
||||||
if (GET_CODE (reg) == REG
|
if (GET_CODE (reg) == REG
|
||||||
&& (regno = REGNO (reg), regno != FRAME_POINTER_REGNUM)
|
&& (regno = REGNO (reg), regno != FRAME_POINTER_REGNUM)
|
||||||
&& regno != ARG_POINTER_REGNUM
|
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||||
|
&& ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
|
||||||
|
#endif
|
||||||
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
|
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
|
||||||
/* && regno != STACK_POINTER_REGNUM) -- let's try without this. */
|
/* && regno != STACK_POINTER_REGNUM) -- let's try without this. */
|
||||||
{
|
{
|
||||||
|
@ -2077,10 +2126,12 @@ mark_used_regs (needed, live, x, final, insn)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* For stack ptr or arg pointer,
|
/* For stack ptr or fixed arg pointer,
|
||||||
nothing below can be necessary, so waste no more time. */
|
nothing below can be necessary, so waste no more time. */
|
||||||
if (regno == STACK_POINTER_REGNUM
|
if (regno == STACK_POINTER_REGNUM
|
||||||
|| regno == ARG_POINTER_REGNUM
|
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||||
|
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
|
||||||
|
#endif
|
||||||
|| regno == FRAME_POINTER_REGNUM)
|
|| regno == FRAME_POINTER_REGNUM)
|
||||||
{
|
{
|
||||||
/* If this is a register we are going to try to eliminate,
|
/* If this is a register we are going to try to eliminate,
|
||||||
|
@ -2235,7 +2286,9 @@ mark_used_regs (needed, live, x, final, insn)
|
||||||
|
|
||||||
if (GET_CODE (testreg) == REG
|
if (GET_CODE (testreg) == REG
|
||||||
&& (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM)
|
&& (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM)
|
||||||
&& regno != ARG_POINTER_REGNUM
|
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|
||||||
|
&& ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
|
||||||
|
#endif
|
||||||
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
|
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
|
||||||
{
|
{
|
||||||
mark_used_regs (needed, live, SET_SRC (x), final, insn);
|
mark_used_regs (needed, live, SET_SRC (x), final, insn);
|
||||||
|
|
Loading…
Reference in New Issue