Commit 6e25d159 by Richard Kenner

(newpat_used_regs): New variable.

(mark_used_regs_combine): New function.
(try_combine): Use them.
(reg_dead_at_p): Registers marked in newpat_used_regs must always be
considered to be live.

From-SVN: r6826
parent 1c78fc52
...@@ -184,6 +184,11 @@ static rtx subst_prev_insn; ...@@ -184,6 +184,11 @@ static rtx subst_prev_insn;
static int subst_low_cuid; static int subst_low_cuid;
/* This contains any hard registers that are used in newpat; reg_dead_at_p
must consider all these registers to be always live. */
static HARD_REG_SET newpat_used_regs;
/* This is an insn to which a LOG_LINKS entry has been added. If this /* This is an insn to which a LOG_LINKS entry has been added. If this
insn is the earlier than I2 or I3, combine should rescan starting at insn is the earlier than I2 or I3, combine should rescan starting at
that location. */ that location. */
...@@ -433,6 +438,7 @@ static void move_deaths PROTO((rtx, int, rtx, rtx *)); ...@@ -433,6 +438,7 @@ static void move_deaths PROTO((rtx, int, rtx, rtx *));
static int reg_bitfield_target_p PROTO((rtx, rtx)); static int reg_bitfield_target_p PROTO((rtx, rtx));
static void distribute_notes PROTO((rtx, rtx, rtx, rtx, rtx, rtx)); static void distribute_notes PROTO((rtx, rtx, rtx, rtx, rtx, rtx));
static void distribute_links PROTO((rtx)); static void distribute_links PROTO((rtx));
static void mark_used_regs_combine PROTO((rtx));
/* Main entry point for combiner. F is the first insn of the function. /* Main entry point for combiner. F is the first insn of the function.
NREGS is the first unused pseudo-reg number. */ NREGS is the first unused pseudo-reg number. */
...@@ -1219,6 +1225,9 @@ try_combine (i3, i2, i1) ...@@ -1219,6 +1225,9 @@ try_combine (i3, i2, i1)
accept this combination. */ accept this combination. */
undobuf.storage = (char *) oballoc (0); undobuf.storage = (char *) oballoc (0);
/* Reset the hard register usage information. */
CLEAR_HARD_REG_SET (newpat_used_regs);
/* If I1 and I2 both feed I3, they can be in any order. To simplify the /* If I1 and I2 both feed I3, they can be in any order. To simplify the
code below, set I1 to be the earlier of the two insns. */ code below, set I1 to be the earlier of the two insns. */
if (i1 && INSN_CUID (i1) > INSN_CUID (i2)) if (i1 && INSN_CUID (i1) > INSN_CUID (i2))
...@@ -1640,6 +1649,9 @@ try_combine (i3, i2, i1) ...@@ -1640,6 +1649,9 @@ try_combine (i3, i2, i1)
destination of I3. */ destination of I3. */
validate_replacement: validate_replacement:
/* Note which hard regs this insn has as inputs. */
mark_used_regs_combine (newpat);
/* Is the result of combination a valid instruction? */ /* Is the result of combination a valid instruction? */
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
...@@ -1999,6 +2011,8 @@ try_combine (i3, i2, i1) ...@@ -1999,6 +2011,8 @@ try_combine (i3, i2, i1)
rtx new_other_notes; rtx new_other_notes;
rtx note, next; rtx note, next;
CLEAR_HARD_REG_SET (newpat_used_regs);
other_code_number = recog_for_combine (&other_pat, undobuf.other_insn, other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
&new_other_notes); &new_other_notes);
...@@ -9875,7 +9889,8 @@ reg_dead_at_p_1 (dest, x) ...@@ -9875,7 +9889,8 @@ reg_dead_at_p_1 (dest, x)
We scan backwards from INSN. If we hit a REG_DEAD note or a CLOBBER We scan backwards from INSN. If we hit a REG_DEAD note or a CLOBBER
referencing REG, it is dead. If we hit a SET referencing REG, it is referencing REG, it is dead. If we hit a SET referencing REG, it is
live. Otherwise, see if it is live or dead at the start of the basic live. Otherwise, see if it is live or dead at the start of the basic
block we are in. */ block we are in. Hard regs marked as being live in NEWPAT_USED_REGS
must be assumed to be always live. */
static int static int
reg_dead_at_p (reg, insn) reg_dead_at_p (reg, insn)
...@@ -9893,6 +9908,14 @@ reg_dead_at_p (reg, insn) ...@@ -9893,6 +9908,14 @@ reg_dead_at_p (reg, insn)
reg_dead_flag = 0; reg_dead_flag = 0;
/* Check that reg isn't mentioned in NEWPAT_USED_REGS. */
if (reg_dead_regno < FIRST_PSEUDO_REGISTER)
{
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
if (TEST_HARD_REG_BIT (newpat_used_regs, i))
return 0;
}
/* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, label, or /* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, label, or
beginning of function. */ beginning of function. */
for (; insn && GET_CODE (insn) != CODE_LABEL; for (; insn && GET_CODE (insn) != CODE_LABEL;
...@@ -9927,6 +9950,106 @@ reg_dead_at_p (reg, insn) ...@@ -9927,6 +9950,106 @@ reg_dead_at_p (reg, insn)
return 1; return 1;
} }
/* Note hard registers in X that are used. This code is similar to
that in flow.c, but much simpler since we don't care about pseudos. */
static void
mark_used_regs_combine (x)
rtx x;
{
register RTX_CODE code = GET_CODE (x);
register int regno;
int i;
switch (code)
{
case LABEL_REF:
case SYMBOL_REF:
case CONST_INT:
case CONST:
case CONST_DOUBLE:
case PC:
case ADDR_VEC:
case ADDR_DIFF_VEC:
case ASM_INPUT:
#ifdef HAVE_cc0
/* CC0 must die in the insn after it is set, so we don't need to take
special note of it here. */
case CC0:
#endif
return;
case CLOBBER:
/* If we are clobbering a MEM, mark any hard registers inside the
address as used. */
if (GET_CODE (XEXP (x, 0)) == MEM)
mark_used_regs_combine (XEXP (XEXP (x, 0), 0));
return;
case REG:
regno = REGNO (x);
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
if (regno < FIRST_PSEUDO_REGISTER)
{
/* None of this applies to the stack, frame or arg pointers */
if (regno == STACK_POINTER_REGNUM
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|| regno == HARD_FRAME_POINTER_REGNUM
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
|| regno == FRAME_POINTER_REGNUM)
return;
i = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (i-- > 0)
SET_HARD_REG_BIT (newpat_used_regs, regno + i);
}
return;
case SET:
{
/* If setting a MEM, or a SUBREG of a MEM, then note any hard regs in
the address. */
register rtx testreg = SET_DEST (x);
while (GET_CODE (x) == SUBREG
|| GET_CODE (x) == ZERO_EXTRACT
|| GET_CODE (x) == SIGN_EXTRACT
|| GET_CODE (x) == STRICT_LOW_PART)
testreg = XEXP (testreg, 0);
if (GET_CODE (testreg) == MEM)
mark_used_regs_combine (XEXP (testreg, 0));
mark_used_regs_combine (SET_SRC (x));
return;
}
}
/* Recursively scan the operands of this expression. */
{
register char *fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
mark_used_regs_combine (XEXP (x, i));
else if (fmt[i] == 'E')
{
register int j;
for (j = 0; j < XVECLEN (x, i); j++)
mark_used_regs_combine (XVECEXP (x, i, j));
}
}
}
}
/* Remove register number REGNO from the dead registers list of INSN. /* Remove register number REGNO from the dead registers list of INSN.
Return the note used to record the death, if there was one. */ Return the note used to record the death, if there was one. */
......
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