/* Allocate registers within a basic block, for GNU compiler.
Copyright (C) 1987, 1988, 1991, 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.
/* Number of words needed to hold the data in given quantity.
This depends on its machine mode. It is used for these purposes:
- 1. It is used in computing the relative importances of qtys,
+ 1. It is used in computing the relative importance of qtys,
which determines the order in which we look for regs for them.
2. It is used in rules that prevent tying several registers of
different sizes in a way that is geometrically impossible
validate_equiv_mem_from_store (rtx dest, rtx set ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
- if ((GET_CODE (dest) == REG
+ if ((REG_P (dest)
&& reg_overlap_mentioned_p (dest, equiv_mem))
- || (GET_CODE (dest) == MEM
+ || (MEM_P (dest)
&& true_dependence (dest, VOIDmode, equiv_mem, rtx_varies_p)))
equiv_mem_modified = 1;
}
if (find_reg_note (insn, REG_DEAD, reg))
return 1;
- if (GET_CODE (insn) == CALL_INSN && ! RTX_UNCHANGING_P (memref)
+ if (CALL_P (insn) && ! MEM_READONLY_P (memref)
&& ! CONST_OR_PURE_CALL_P (insn))
return 0;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if ((REG_NOTE_KIND (note) == REG_INC
|| REG_NOTE_KIND (note) == REG_DEAD)
- && GET_CODE (XEXP (note, 0)) == REG
+ && REG_P (XEXP (note, 0))
&& reg_overlap_mentioned_p (XEXP (note, 0), memref))
return 0;
}
switch (code)
{
case MEM:
- return ! RTX_UNCHANGING_P (x) || equiv_init_varies_p (XEXP (x, 0));
-
- case QUEUED:
- return 1;
+ return !MEM_READONLY_P (x) || equiv_init_varies_p (XEXP (x, 0));
case CONST:
case CONST_INT:
if (MEM_VOLATILE_P (x))
return 1;
- /* FALLTHROUGH */
+ /* Fall through. */
default:
break;
if (MEM_VOLATILE_P (x))
return 0;
- /* FALLTHROUGH */
+ /* Fall through. */
default:
break;
case SET:
/* If we are setting a MEM, it doesn't count (its address does), but any
other SET_DEST that has a MEM in it is referencing the MEM. */
- if (GET_CODE (SET_DEST (x)) == MEM)
+ if (MEM_P (SET_DEST (x)))
{
if (memref_referenced_p (memref, XEXP (SET_DEST (x), 0)))
return 1;
return 0;
}
\f
-/* Return nonzero if the rtx X is invariant over the current function. */
-/* ??? Actually, the places this is used in reload expect exactly what
- is tested here, and not everything that is function invariant. In
- particular, the frame pointer and arg pointer are special cased;
- pic_offset_table_rtx is not, and this will cause aborts when we
- go to spill these things to memory. */
-
-int
-function_invariant_p (rtx x)
-{
- if (CONSTANT_P (x))
- return 1;
- if (x == frame_pointer_rtx || x == arg_pointer_rtx)
- return 1;
- if (GET_CODE (x) == PLUS
- && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
- && CONSTANT_P (XEXP (x, 1)))
- return 1;
- return 0;
-}
-
/* Find registers that are equivalent to a single value throughout the
compilation (either because they can be referenced in memory or are set once
from a single constant). Lower their priority for a register.
{
loop_depth = bb->loop_depth;
- for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
+ for (insn = BB_HEAD (bb);
+ insn != NEXT_INSN (BB_END (bb));
+ insn = NEXT_INSN (insn))
{
rtx note;
rtx set;
Equivalences to MEMs should be made in another pass, after the
reg_equiv[].replace information has been gathered. */
- if (GET_CODE (dest) == MEM && GET_CODE (src) == REG
+ if (MEM_P (dest) && REG_P (src)
&& (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
&& REG_BASIC_BLOCK (regno) >= 0
&& REG_N_SETS (regno) == 1
preferred class of a pseudo depends on all instructions that set
or use it. */
- if (GET_CODE (dest) != REG
+ if (!REG_P (dest)
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
|| reg_equiv[regno].init_insns == const0_rtx
|| (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
- && GET_CODE (src) == MEM))
+ && MEM_P (src)))
{
/* This might be setting a SUBREG of a pseudo, a pseudo that is
also set somewhere else to a constant. */
note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
if (note == 0 && REG_BASIC_BLOCK (regno) >= 0
- && GET_CODE (SET_SRC (set)) == MEM
+ && MEM_P (SET_SRC (set))
&& validate_equiv_mem (insn, dest, SET_SRC (set)))
REG_NOTES (insn) = note = gen_rtx_EXPR_LIST (REG_EQUIV, SET_SRC (set),
REG_NOTES (insn));
if (REG_N_REFS (regno) == 2
&& (rtx_equal_p (XEXP (note, 0), src)
|| ! equiv_init_varies_p (src))
- && GET_CODE (insn) == INSN
+ && NONJUMP_INSN_P (insn)
&& equiv_init_movable_p (PATTERN (insn), regno))
reg_equiv[regno].replace = 1;
}
FOR_EACH_BB_REVERSE (bb)
{
loop_depth = bb->loop_depth;
- for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
+ for (insn = BB_END (bb);
+ insn != PREV_INSN (BB_HEAD (bb));
+ insn = PREV_INSN (insn))
{
rtx link;
if (! INSN_P (insn))
continue;
+ /* Don't substitute into a non-local goto, this confuses CFG. */
+ if (JUMP_P (insn)
+ && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+ continue;
+
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
{
if (REG_NOTE_KIND (link) == REG_DEAD
REG_N_CALLS_CROSSED (regno) = 0;
REG_LIVE_LENGTH (regno) = 2;
- if (insn == bb->head)
- bb->head = PREV_INSN (insn);
+ if (insn == BB_HEAD (bb))
+ BB_HEAD (bb) = PREV_INSN (insn);
/* Remember to clear REGNO from all basic block's live
info. */
}
}
else
- EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
- {
- FOR_EACH_BB (bb)
- {
- CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
- CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
- }
- });
+ {
+ reg_set_iterator rsi;
+ EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j, rsi)
+ {
+ FOR_EACH_BB (bb)
+ {
+ CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
+ CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
+ }
+ }
+ }
}
/* Clean up. */
int regno;
rtx list;
- if (GET_CODE (reg) != REG)
+ if (!REG_P (reg))
return;
regno = REGNO (reg);
list = reg_equiv[regno].init_insns;
/* Count the instructions in the basic block. */
- insn = BLOCK_END (b);
+ insn = BB_END (BASIC_BLOCK (b));
while (1)
{
- if (GET_CODE (insn) != NOTE)
+ if (!NOTE_P (insn))
if (++insn_count > max_uid)
abort ();
- if (insn == BLOCK_HEAD (b))
+ if (insn == BB_HEAD (BASIC_BLOCK (b)))
break;
insn = PREV_INSN (insn);
}
and assigns quantities to registers.
It computes which registers to tie. */
- insn = BLOCK_HEAD (b);
+ insn = BB_HEAD (BASIC_BLOCK (b));
while (1)
{
- if (GET_CODE (insn) != NOTE)
+ if (!NOTE_P (insn))
insn_number++;
if (INSN_P (insn))
hard_reg = get_hard_reg_initial_reg (cfun, r1);
if (hard_reg != NULL_RTX)
{
- if (GET_CODE (hard_reg) == REG
+ if (REG_P (hard_reg)
&& IN_RANGE (REGNO (hard_reg),
0, FIRST_PSEUDO_REGISTER - 1)
&& ! call_used_regs[REGNO (hard_reg)])
continue;
}
- if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
+ if (REG_P (r0) || GET_CODE (r0) == SUBREG)
{
/* We have two priorities for hard register preferences.
If we have a move insn or an insn whose first input
int may_save_copy
= (r1 == recog_data.operand[i] && must_match_0 >= 0);
- if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
+ if (REG_P (r1) || GET_CODE (r1) == SUBREG)
win = combine_regs (r1, r0, may_save_copy,
insn_number, insn, 0);
}
if (optimize
&& GET_CODE (PATTERN (insn)) == CLOBBER
&& (r0 = XEXP (PATTERN (insn), 0),
- GET_CODE (r0) == REG)
+ REG_P (r0))
&& (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
&& XEXP (link, 0) != 0
- && GET_CODE (XEXP (link, 0)) == INSN
+ && NONJUMP_INSN_P (XEXP (link, 0))
&& (set = single_set (XEXP (link, 0))) != 0
&& SET_DEST (set) == r0 && SET_SRC (set) == r0
&& (note = find_reg_note (XEXP (link, 0), REG_EQUAL,
NULL_RTX)) != 0)
{
- if (r1 = XEXP (note, 0), GET_CODE (r1) == REG
+ if (r1 = XEXP (note, 0), REG_P (r1)
/* Check that we have such a sequence. */
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 1, insn_number, insn, 1);
else if (GET_RTX_FORMAT (GET_CODE (XEXP (note, 0)))[0] == 'e'
&& (r1 = XEXP (XEXP (note, 0), 0),
- GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
+ REG_P (r1) || GET_CODE (r1) == SUBREG)
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 0, insn_number, insn, 1);
/* Here we care if the operation to be computed is
commutative. */
- else if ((GET_CODE (XEXP (note, 0)) == EQ
- || GET_CODE (XEXP (note, 0)) == NE
- || GET_RTX_CLASS (GET_CODE (XEXP (note, 0))) == 'c')
+ else if (COMMUTATIVE_P (XEXP (note, 0))
&& (r1 = XEXP (XEXP (note, 0), 1),
- (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
+ (REG_P (r1) || GET_CODE (r1) == SUBREG))
&& no_conflict_p (insn, r0, r1))
win = combine_regs (r1, r0, 0, insn_number, insn, 1);
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD
- && GET_CODE (XEXP (link, 0)) == REG
+ && REG_P (XEXP (link, 0))
&& combined_regno != (int) REGNO (XEXP (link, 0))
&& (no_conflict_combined_regno != (int) REGNO (XEXP (link, 0))
|| ! find_reg_note (insn, REG_NO_CONFLICT,
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_UNUSED
- && GET_CODE (XEXP (link, 0)) == REG)
+ && REG_P (XEXP (link, 0)))
wipe_dead_reg (XEXP (link, 0), 1);
/* If this is an insn that has a REG_RETVAL note pointing at a
CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
block, so clear any register number that combined within it. */
if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0
- && GET_CODE (XEXP (note, 0)) == INSN
+ && NONJUMP_INSN_P (XEXP (note, 0))
&& GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER)
no_conflict_combined_regno = -1;
}
IOR_HARD_REG_SET (regs_live_at[2 * insn_number], regs_live);
IOR_HARD_REG_SET (regs_live_at[2 * insn_number + 1], regs_live);
- if (insn == BLOCK_END (b))
+ if (insn == BB_END (BASIC_BLOCK (b)))
break;
insn = NEXT_INSN (insn);
Combining registers means marking them as having the same quantity
and adjusting the offsets within the quantity if either of
- them is a SUBREG).
+ them is a SUBREG.
We don't actually combine a hard reg with a pseudo; instead
we just record the hard reg as the suggestion for the pseudo's quantity.
If we really combined them, we could lose if the pseudo lives
- across an insn that clobbers the hard reg (eg, movstr).
+ across an insn that clobbers the hard reg (eg, movmem).
ALREADY_DEAD is nonzero if USEDREG is known to be dead even though
there is no REG_DEAD note on INSN. This occurs during the processing
of REG_NO_CONFLICT blocks.
- MAY_SAVE_COPYCOPY is nonzero if this insn is simply copying USEDREG to
+ MAY_SAVE_COPY is nonzero if this insn is simply copying USEDREG to
SETREG or if the input and output must share a register.
In that case, we record a hard reg suggestion in QTY_PHYS_COPY_SUGG.
{
rtx subreg = SUBREG_REG (usedreg);
- if (GET_CODE (subreg) == REG)
+ if (REG_P (subreg))
{
if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
may_save_copy = 0;
usedreg = subreg;
}
- if (GET_CODE (usedreg) != REG)
+ if (!REG_P (usedreg))
return 0;
ureg = REGNO (usedreg);
if (ureg < FIRST_PSEUDO_REGISTER)
- usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
+ usize = hard_regno_nregs[ureg][GET_MODE (usedreg)];
else
usize = ((GET_MODE_SIZE (GET_MODE (usedreg))
+ (REGMODE_NATURAL_SIZE (GET_MODE (usedreg)) - 1))
{
rtx subreg = SUBREG_REG (setreg);
- if (GET_CODE (subreg) == REG)
+ if (REG_P (subreg))
{
if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
may_save_copy = 0;
setreg = subreg;
}
- if (GET_CODE (setreg) != REG)
+ if (!REG_P (setreg))
return 0;
sreg = REGNO (setreg);
if (sreg < FIRST_PSEUDO_REGISTER)
- ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
+ ssize = hard_regno_nregs[sreg][GET_MODE (setreg)];
else
ssize = ((GET_MODE_SIZE (GET_MODE (setreg))
+ (REGMODE_NATURAL_SIZE (GET_MODE (setreg)) - 1))
a hard register. These may actually not exist any more. */
if (GET_CODE (reg) != SUBREG
- && GET_CODE (reg) != REG)
+ && !REG_P (reg))
return;
/* Mark this register as being born. If it is used in a CLOBBER, mark
{
rtx set = XVECEXP (PATTERN (this_insn), 0, i);
if (GET_CODE (set) == SET
- && GET_CODE (SET_DEST (set)) != REG
+ && !REG_P (SET_DEST (set))
&& !rtx_equal_p (reg, SET_DEST (set))
&& reg_overlap_mentioned_p (reg, SET_DEST (set)))
output_p = 1;
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
{
int j;
- int size1 = HARD_REGNO_NREGS (regno, mode);
+ int size1 = hard_regno_nregs[regno][mode];
for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
if (j == size1)
{
static void
mark_life (int regno, enum machine_mode mode, int life)
{
- int j = HARD_REGNO_NREGS (regno, mode);
+ int j = hard_regno_nregs[regno][mode];
if (life)
while (--j >= 0)
SET_HARD_REG_BIT (regs_live, regno + j);
post_mark_life (int regno, enum machine_mode mode, int life, int birth,
int death)
{
- int j = HARD_REGNO_NREGS (regno, mode);
-#ifdef HARD_REG_SET
- /* Declare it register if it's a scalar. */
- register
-#endif
- HARD_REG_SET this_reg;
+ int j = hard_regno_nregs[regno][mode];
+ HARD_REG_SET this_reg;
CLEAR_HARD_REG_SET (this_reg);
while (--j >= 0)
when we scan the insns that actually use it. */
if (note == 0
- || (GET_CODE (r1) == REG && REGNO (r1) < FIRST_PSEUDO_REGISTER)
- || (GET_CODE (r1) == SUBREG && GET_CODE (SUBREG_REG (r1)) == REG
+ || (REG_P (r1) && REGNO (r1) < FIRST_PSEUDO_REGISTER)
+ || (GET_CODE (r1) == SUBREG && REG_P (SUBREG_REG (r1))
&& REGNO (SUBREG_REG (r1)) < FIRST_PSEUDO_REGISTER))
return 0;
if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS
&& !EXTRA_ADDRESS_CONSTRAINT (c, p))
break;
- /* FALLTHRU */
+ /* Fall through. */
case 'p':
case 'g': case 'r':
reg_allowed = 1;