(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
This commit is contained in:
parent
1c78fc5220
commit
6e25d15912
125
gcc/combine.c
125
gcc/combine.c
@ -184,6 +184,11 @@ static rtx subst_prev_insn;
|
||||
|
||||
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
|
||||
insn is the earlier than I2 or I3, combine should rescan starting at
|
||||
that location. */
|
||||
@ -433,6 +438,7 @@ static void move_deaths PROTO((rtx, int, 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_links PROTO((rtx));
|
||||
static void mark_used_regs_combine PROTO((rtx));
|
||||
|
||||
/* Main entry point for combiner. F is the first insn of the function.
|
||||
NREGS is the first unused pseudo-reg number. */
|
||||
@ -1219,6 +1225,9 @@ try_combine (i3, i2, i1)
|
||||
accept this combination. */
|
||||
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
|
||||
code below, set I1 to be the earlier of the two insns. */
|
||||
if (i1 && INSN_CUID (i1) > INSN_CUID (i2))
|
||||
@ -1640,6 +1649,9 @@ try_combine (i3, i2, i1)
|
||||
destination of I3. */
|
||||
validate_replacement:
|
||||
|
||||
/* Note which hard regs this insn has as inputs. */
|
||||
mark_used_regs_combine (newpat);
|
||||
|
||||
/* Is the result of combination a valid instruction? */
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
|
||||
@ -1999,6 +2011,8 @@ try_combine (i3, i2, i1)
|
||||
rtx new_other_notes;
|
||||
rtx note, next;
|
||||
|
||||
CLEAR_HARD_REG_SET (newpat_used_regs);
|
||||
|
||||
other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
|
||||
&new_other_notes);
|
||||
|
||||
@ -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
|
||||
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
|
||||
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
|
||||
reg_dead_at_p (reg, insn)
|
||||
@ -9893,6 +9908,14 @@ reg_dead_at_p (reg, insn)
|
||||
|
||||
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
|
||||
beginning of function. */
|
||||
for (; insn && GET_CODE (insn) != CODE_LABEL;
|
||||
@ -9926,6 +9949,106 @@ reg_dead_at_p (reg, insn)
|
||||
|
||||
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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user