/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
return;
}
- /* Call ourself recursively to perform the replacements. */
+ /* Call ourself recursively to perform the replacements.
+ We must not replace inside already replaced expression, otherwise we
+ get infinite recursion for replacements like (reg X)->(subreg (reg X))
+ done by regmove, so we must special case shared ASM_OPERANDS. */
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (GET_CODE (x) == PARALLEL)
{
- if (fmt[i] == 'e')
- validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
- else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
+ for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
+ {
+ if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
+ && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
+ {
+ /* Verify that operands are really shared. */
+ if (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0))) !=
+ ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, j))))
+ abort ();
+ validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
+ from, to, object);
+ }
+ else
+ validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
+ }
}
+ else
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
+ else if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
+ }
/* If we didn't substitute, there is nothing more to do. */
if (num_changes == prev_changes)
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
break;
- /* FALLTHRU */
+ /* Fall through. */
case 'i':
if (CONSTANT_P (op)
break;
case 'm':
- if (GET_CODE (op) == MEM
- /* Before reload, accept what reload can turn into mem. */
- || (strict < 0 && CONSTANT_P (op))
- /* During reload, accept a pseudo */
- || (reload_in_progress && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER))
+ /* Memory operands must be valid, to the extent
+ required by STRICT. */
+ if (GET_CODE (op) == MEM)
+ {
+ if (strict > 0
+ && !strict_memory_address_p (GET_MODE (op),
+ XEXP (op, 0)))
+ break;
+ if (strict == 0
+ && !memory_address_p (GET_MODE (op), XEXP (op, 0)))
+ break;
+ win = 1;
+ }
+ /* Before reload, accept what reload can turn into mem. */
+ else if (strict < 0 && CONSTANT_P (op))
+ win = 1;
+ /* During reload, accept a pseudo */
+ else if (reload_in_progress && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)
win = 1;
break;
{
int sr;
regno += offset;
- for (sr = HARD_REGNO_NREGS (regno, mode) - 1;
+ for (sr = hard_regno_nregs[regno][mode] - 1;
sr > 0; sr--)
if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
regno + sr))
rtx insn, next;
bool finish = false;
- for (insn = bb->head; !finish ; insn = next)
+ for (insn = BB_HEAD (bb); !finish ; insn = next)
{
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
- finish = (insn == bb->end);
+ finish = (insn == BB_END (bb));
if (INSN_P (insn))
{
rtx set = single_set (insn);
if (changed && upd_life)
update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES | PROP_REG_INFO);
+ PROP_DEATH_NOTES);
#ifdef ENABLE_CHECKING
verify_flow_info ();
abort ();
regno = REGNO (reg);
- n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ n = hard_regno_nregs[regno][GET_MODE (reg)];
while (--n >= 0)
if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
return 0;
continue;
success = 1;
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
{
if (TEST_HARD_REG_BIT (*reg_set, regno + j)
|| TEST_HARD_REG_BIT (live, regno + j))
}
if (success)
{
- for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
+ for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
SET_HARD_REG_BIT (*reg_set, regno + j);
/* Start the next search with the next register. */
pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES);
#endif
- for (insn = bb->end; ; insn = prev)
+ for (insn = BB_END (bb); ; insn = prev)
{
prev = PREV_INSN (insn);
if (INSN_P (insn))
XEXP (note, 0),
REG_NOTES (x));
- if (x != bb->end && eh_edge)
+ if (x != BB_END (bb) && eh_edge)
{
edge nfte, nehe;
int flags;
}
}
- if (insn == bb->head)
+ if (insn == BB_HEAD (bb))
break;
}