/* 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)
/* Do changes needed to keep rtx consistent. Don't do any other
simplifications, as it is not our job. */
- if ((GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == 'c')
+ if (SWAPPABLE_OPERANDS_P (x)
&& swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
{
validate_change (object, loc,
- gen_rtx_fmt_ee (GET_RTX_CLASS (code) == 'c' ? code
+ gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
: swap_condition (code),
GET_MODE (x), XEXP (x, 1),
XEXP (x, 0)), 1);
d.insn = insn;
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
}
-
-/* Same as validate_replace_src_group, but validate by seeing if
- INSN is still valid. */
-int
-validate_replace_src (rtx from, rtx to, rtx insn)
-{
- validate_replace_src_group (from, to, insn);
- return apply_change_group ();
-}
\f
#ifdef HAVE_cc0
/* Return 1 if the insn using CC0 set by INSN does not contain
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
- /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
- result in 0/1. It seems a safe assumption that this is
- in range for everyone. */
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
-
return (CONSTANT_P (op)
&& (GET_MODE (op) == mode || mode == VOIDmode
|| GET_MODE (op) == VOIDmode)
comparison_operator (rtx op, enum machine_mode mode)
{
return ((mode == VOIDmode || GET_MODE (op) == mode)
- && GET_RTX_CLASS (GET_CODE (op)) == '<');
+ && COMPARISON_P (op));
}
\f
/* If BODY is an insn body that uses ASM_OPERANDS,
return template;
}
-/* Check if an asm_operand matches it's constraints.
+/* Check if an asm_operand matches its constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
|| (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode))
break;
- /* FALLTHRU */
+ /* Fall through. */
case 'i':
if (CONSTANT_P (op)
return good;
}
- if (GET_RTX_CLASS (ycode) == 'a')
+ if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
return 0;
/* The offset added here is chosen as the maximum offset that
/* A unary operator may be accepted by the predicate, but it
is irrelevant for matching constraints. */
- if (GET_RTX_CLASS (GET_CODE (op)) == '1')
+ if (UNARY_P (op))
op = XEXP (op, 0);
if (GET_CODE (op) == SUBREG)
/* A unary operator may be accepted by the predicate,
but it is irrelevant for matching constraints. */
- if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
+ if (UNARY_P (op1))
op1 = XEXP (op1, 0);
- if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
+ if (UNARY_P (op2))
op2 = XEXP (op2, 0);
val = operands_match_p (op1, op2);
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;
}