/* 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))
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. */