Commit 37bb2709 by Richard Henderson Committed by Richard Henderson

flow.c (mark_used_reg): Clean up looping over multiple hard registers.

        * flow.c (mark_used_reg): Clean up looping over multiple hard
        registers.  Do conditional life bits across multiple hard regs.

From-SVN: r42942
parent e7580d2e
2001-06-06 Richard Henderson <rth@redhat.com>
* flow.c (mark_used_reg): Clean up looping over multiple hard
registers. Do conditional life bits across multiple hard regs.
2001-06-05 Jeffrey D. Oldham <oldham@codesourcery.com> 2001-06-05 Jeffrey D. Oldham <oldham@codesourcery.com>
* reload1.c (reload): Revert Schmidt's change so all USEs are not * reload1.c (reload): Revert Schmidt's change so all USEs are not
......
...@@ -5592,35 +5592,37 @@ mark_used_reg (pbi, reg, cond, insn) ...@@ -5592,35 +5592,37 @@ mark_used_reg (pbi, reg, cond, insn)
rtx cond ATTRIBUTE_UNUSED; rtx cond ATTRIBUTE_UNUSED;
rtx insn; rtx insn;
{ {
int regno = REGNO (reg); unsigned int regno_first, regno_last, i;
int some_was_live = REGNO_REG_SET_P (pbi->reg_live, regno); int some_was_live, some_was_dead, some_not_set;
int some_was_dead = ! some_was_live;
int some_not_set;
int n;
/* A hard reg in a wide mode may really be multiple registers. regno_last = regno_first = REGNO (reg);
If so, mark all of them just like the first. */ if (regno_first < FIRST_PSEUDO_REGISTER)
if (regno < FIRST_PSEUDO_REGISTER) regno_last += HARD_REGNO_NREGS (regno_first, GET_MODE (reg)) - 1;
/* Find out if any of this register is live after this instruction. */
some_was_live = some_was_dead = 0;
for (i = regno_first; i <= regno_last; ++i)
{ {
n = HARD_REGNO_NREGS (regno, GET_MODE (reg)); int needed_regno = REGNO_REG_SET_P (pbi->reg_live, i);
while (--n > 0) some_was_live |= needed_regno;
{ some_was_dead |= ! needed_regno;
int needed_regno = REGNO_REG_SET_P (pbi->reg_live, regno + n);
some_was_live |= needed_regno;
some_was_dead |= ! needed_regno;
}
} }
/* Find out if any of the register was set this insn. */
some_not_set = 0;
for (i = regno_first; i <= regno_last; ++i)
some_not_set |= ! REGNO_REG_SET_P (pbi->new_set, i);
if (pbi->flags & (PROP_LOG_LINKS | PROP_AUTOINC)) if (pbi->flags & (PROP_LOG_LINKS | PROP_AUTOINC))
{ {
/* Record where each reg is used, so when the reg is set we know /* Record where each reg is used, so when the reg is set we know
the next insn that uses it. */ the next insn that uses it. */
pbi->reg_next_use[regno] = insn; pbi->reg_next_use[regno_first] = insn;
} }
if (pbi->flags & PROP_REG_INFO) if (pbi->flags & PROP_REG_INFO)
{ {
if (regno < FIRST_PSEUDO_REGISTER) if (regno_first < FIRST_PSEUDO_REGISTER)
{ {
/* If this is a register we are going to try to eliminate, /* If this is a register we are going to try to eliminate,
don't mark it live here. If we are successful in don't mark it live here. If we are successful in
...@@ -5634,41 +5636,28 @@ mark_used_reg (pbi, reg, cond, insn) ...@@ -5634,41 +5636,28 @@ mark_used_reg (pbi, reg, cond, insn)
register to itself. This should be fixed. In the mean register to itself. This should be fixed. In the mean
time, hack around it. */ time, hack around it. */
if (! (TEST_HARD_REG_BIT (elim_reg_set, regno) if (! (TEST_HARD_REG_BIT (elim_reg_set, regno_first)
&& (regno == FRAME_POINTER_REGNUM && (regno_first == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM))) || regno_first == ARG_POINTER_REGNUM)))
{ for (i = regno_first; i <= regno_last; ++i)
int n = HARD_REGNO_NREGS (regno, GET_MODE (reg)); regs_ever_live[i] = 1;
do
regs_ever_live[regno + --n] = 1;
while (n > 0);
}
} }
else else
{ {
/* Keep track of which basic block each reg appears in. */ /* Keep track of which basic block each reg appears in. */
register int blocknum = pbi->bb->index; register int blocknum = pbi->bb->index;
if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN) if (REG_BASIC_BLOCK (regno_first) == REG_BLOCK_UNKNOWN)
REG_BASIC_BLOCK (regno) = blocknum; REG_BASIC_BLOCK (regno_first) = blocknum;
else if (REG_BASIC_BLOCK (regno) != blocknum) else if (REG_BASIC_BLOCK (regno_first) != blocknum)
REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL; REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
/* Count (weighted) number of uses of each reg. */ /* Count (weighted) number of uses of each reg. */
REG_N_REFS (regno) += (optimize_size ? 1 REG_N_REFS (regno_first)
: pbi->bb->loop_depth + 1); += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
} }
} }
/* Find out if any of the register was set this insn. */
some_not_set = ! REGNO_REG_SET_P (pbi->new_set, regno);
if (regno < FIRST_PSEUDO_REGISTER)
{
n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (--n > 0)
some_not_set |= ! REGNO_REG_SET_P (pbi->new_set, regno + n);
}
/* Record and count the insns in which a reg dies. If it is used in /* Record and count the insns in which a reg dies. If it is used in
this insn and was dead below the insn then it dies in this insn. this insn and was dead below the insn then it dies in this insn.
If it was set in this insn, we do not make a REG_DEAD note; If it was set in this insn, we do not make a REG_DEAD note;
...@@ -5679,116 +5668,102 @@ mark_used_reg (pbi, reg, cond, insn) ...@@ -5679,116 +5668,102 @@ mark_used_reg (pbi, reg, cond, insn)
{ {
/* Check for the case where the register dying partially /* Check for the case where the register dying partially
overlaps the register set by this insn. */ overlaps the register set by this insn. */
if (regno < FIRST_PSEUDO_REGISTER if (regno_first != regno_last)
&& HARD_REGNO_NREGS (regno, GET_MODE (reg)) > 1) for (i = regno_first; i <= regno_last; ++i)
{ some_was_live |= REGNO_REG_SET_P (pbi->new_set, i);
n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (--n >= 0)
some_was_live |= REGNO_REG_SET_P (pbi->new_set, regno + n);
}
/* If none of the words in X is needed, make a REG_DEAD note. /* If none of the words in X is needed, make a REG_DEAD note.
Otherwise, we must make partial REG_DEAD notes. */ Otherwise, we must make partial REG_DEAD notes. */
if (! some_was_live) if (! some_was_live)
{ {
if ((pbi->flags & PROP_DEATH_NOTES) if ((pbi->flags & PROP_DEATH_NOTES)
&& ! find_regno_note (insn, REG_DEAD, regno)) && ! find_regno_note (insn, REG_DEAD, regno_first))
REG_NOTES (insn) REG_NOTES (insn)
= alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn)); = alloc_EXPR_LIST (REG_DEAD, reg, REG_NOTES (insn));
if (pbi->flags & PROP_REG_INFO) if (pbi->flags & PROP_REG_INFO)
REG_N_DEATHS (regno)++; REG_N_DEATHS (regno_first)++;
} }
else else
{ {
/* Don't make a REG_DEAD note for a part of a register /* Don't make a REG_DEAD note for a part of a register
that is set in the insn. */ that is set in the insn. */
for (i = regno_first; i <= regno_last; ++i)
n = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; if (! REGNO_REG_SET_P (pbi->reg_live, i)
for (; n >= regno; n--) && ! dead_or_set_regno_p (insn, i))
if (! REGNO_REG_SET_P (pbi->reg_live, n)
&& ! dead_or_set_regno_p (insn, n))
REG_NOTES (insn) REG_NOTES (insn)
= alloc_EXPR_LIST (REG_DEAD, = alloc_EXPR_LIST (REG_DEAD,
gen_rtx_REG (reg_raw_mode[n], n), gen_rtx_REG (reg_raw_mode[i], i),
REG_NOTES (insn)); REG_NOTES (insn));
} }
} }
SET_REGNO_REG_SET (pbi->reg_live, regno); /* Mark the register as being live. */
if (regno < FIRST_PSEUDO_REGISTER) for (i = regno_first; i <= regno_last; ++i)
{ {
n = HARD_REGNO_NREGS (regno, GET_MODE (reg)); SET_REGNO_REG_SET (pbi->reg_live, i);
while (--n > 0)
SET_REGNO_REG_SET (pbi->reg_live, regno + n);
}
#ifdef HAVE_conditional_execution #ifdef HAVE_conditional_execution
/* If this is a conditional use, record that fact. If it is later /* If this is a conditional use, record that fact. If it is later
conditionally set, we'll know to kill the register. */ conditionally set, we'll know to kill the register. */
if (cond != NULL_RTX) if (cond != NULL_RTX)
{
splay_tree_node node;
struct reg_cond_life_info *rcli;
rtx ncond;
if (some_was_live)
{ {
node = splay_tree_lookup (pbi->reg_cond_dead, regno); splay_tree_node node;
if (node == NULL) struct reg_cond_life_info *rcli;
{ rtx ncond;
/* The register was unconditionally live previously.
No need to do anything. */ if (some_was_live)
}
else
{ {
/* The register was conditionally live previously. node = splay_tree_lookup (pbi->reg_cond_dead, i);
Subtract the new life cond from the old death cond. */ if (node == NULL)
rcli = (struct reg_cond_life_info *) node->value; {
ncond = rcli->condition; /* The register was unconditionally live previously.
ncond = and_reg_cond (ncond, not_reg_cond (cond), 1); No need to do anything. */
}
/* If the register is now unconditionally live, remove the
entry in the splay_tree. */
if (ncond == const0_rtx)
splay_tree_remove (pbi->reg_cond_dead, regno);
else else
{ {
rcli->condition = ncond; /* The register was conditionally live previously.
SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); Subtract the new life cond from the old death cond. */
rcli = (struct reg_cond_life_info *) node->value;
ncond = rcli->condition;
ncond = and_reg_cond (ncond, not_reg_cond (cond), 1);
/* If the register is now unconditionally live,
remove the entry in the splay_tree. */
if (ncond == const0_rtx)
splay_tree_remove (pbi->reg_cond_dead, i);
else
{
rcli->condition = ncond;
SET_REGNO_REG_SET (pbi->reg_cond_reg,
REGNO (XEXP (cond, 0)));
}
} }
} }
} else
else {
{ /* The register was not previously live at all. Record
/* The register was not previously live at all. Record the condition under which it is still dead. */
the condition under which it is still dead. */ rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli));
rcli = (struct reg_cond_life_info *) xmalloc (sizeof (*rcli)); rcli->condition = not_reg_cond (cond);
rcli->condition = not_reg_cond (cond); rcli->stores = const0_rtx;
rcli->stores = const0_rtx; rcli->orig_condition = const0_rtx;
rcli->orig_condition = const0_rtx; splay_tree_insert (pbi->reg_cond_dead, i,
splay_tree_insert (pbi->reg_cond_dead, regno, (splay_tree_value) rcli);
(splay_tree_value) rcli);
SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0))); SET_REGNO_REG_SET (pbi->reg_cond_reg, REGNO (XEXP (cond, 0)));
}
} }
} else if (some_was_live)
else if (some_was_live)
{
splay_tree_node node;
node = splay_tree_lookup (pbi->reg_cond_dead, regno);
if (node != NULL)
{ {
/* The register was conditionally live previously, but is now /* The register may have been conditionally live previously, but
unconditionally so. Remove it from the conditionally dead is now unconditionally live. Remove it from the conditionally
list, so that a conditional set won't cause us to think dead list, so that a conditional set won't cause us to think
it dead. */ it dead. */
splay_tree_remove (pbi->reg_cond_dead, regno); splay_tree_remove (pbi->reg_cond_dead, i);
} }
}
#endif #endif
}
} }
/* Scan expression X and store a 1-bit in NEW_LIVE for each reg it uses. /* Scan expression X and store a 1-bit in NEW_LIVE for each reg it uses.
......
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