/* Allocate registers for pseudo-registers that span basic blocks.
- Copyright (C) 1987, 88, 91, 94, 96-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
static HARD_REG_SET eliminable_regset;
-static int allocno_compare PROTO((const PTR, const PTR));
-static void global_conflicts PROTO((void));
-static void mirror_conflicts PROTO((void));
-static void expand_preferences PROTO((void));
-static void prune_preferences PROTO((void));
-static void find_reg PROTO((int, HARD_REG_SET, int, int, int));
-static void record_one_conflict PROTO((int));
-static void record_conflicts PROTO((int *, int));
-static void mark_reg_store PROTO((rtx, rtx, void *));
-static void mark_reg_clobber PROTO((rtx, rtx, void *));
-static void mark_reg_conflicts PROTO((rtx));
-static void mark_reg_death PROTO((rtx));
-static void mark_reg_live_nc PROTO((int, enum machine_mode));
-static void set_preference PROTO((rtx, rtx));
-static void dump_conflicts PROTO((FILE *));
-static void reg_becomes_live PROTO((rtx, rtx, void *));
-static void reg_dies PROTO((int, enum machine_mode));
-static void build_insn_chain PROTO((rtx));
+static int allocno_compare PARAMS ((const PTR, const PTR));
+static void global_conflicts PARAMS ((void));
+static void mirror_conflicts PARAMS ((void));
+static void expand_preferences PARAMS ((void));
+static void prune_preferences PARAMS ((void));
+static void find_reg PARAMS ((int, HARD_REG_SET, int, int, int));
+static void record_one_conflict PARAMS ((int));
+static void record_conflicts PARAMS ((int *, int));
+static void mark_reg_store PARAMS ((rtx, rtx, void *));
+static void mark_reg_clobber PARAMS ((rtx, rtx, void *));
+static void mark_reg_conflicts PARAMS ((rtx));
+static void mark_reg_death PARAMS ((rtx));
+static void mark_reg_live_nc PARAMS ((int, enum machine_mode));
+static void set_preference PARAMS ((rtx, rtx));
+static void dump_conflicts PARAMS ((FILE *));
+static void reg_becomes_live PARAMS ((rtx, rtx, void *));
+static void reg_dies PARAMS ((int, enum machine_mode,
+ struct insn_chain *));
\f
/* Perform allocation of pseudo-registers not allocated by local_alloc.
FILE is a file to output debugging information on,
a leaf function. */
{
char *cheap_regs;
- static char leaf_regs[] = LEAF_REGISTERS;
+ char *leaf_regs = LEAF_REGISTERS;
if (only_leaf_regs_used () && leaf_function_p ())
cheap_regs = leaf_regs;
IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
-#ifdef CLASS_CANNOT_CHANGE_SIZE
- if (REG_CHANGES_SIZE (allocno[num].reg))
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (REG_CHANGES_MODE (allocno[num].reg))
IOR_HARD_REG_SET (used1,
- reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
+ reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
#endif
/* Try each hard reg to see if it fits. Do this in two passes.
/* Don't use a reg no good for this pseudo. */
&& ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
-#ifdef CLASS_CANNOT_CHANGE_SIZE
- && ! (REG_CHANGES_SIZE (allocno[num].reg)
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ && ! (REG_CHANGES_MODE (allocno[num].reg)
&& (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
+ (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
regno)))
#endif
)
register int len;
{
register int num;
- register int j;
register int ialloc_prod;
while (--len >= 0)
set_preference (dest, src)
rtx dest, src;
{
- int src_regno, dest_regno;
+ unsigned int src_regno, dest_regno;
/* Amount to add to the hard regno for SRC, or subtract from that for DEST,
to compensate for subregs in SRC or DEST. */
int offset = 0;
- int i;
+ unsigned int i;
int copy = 1;
if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e')
&& reg_allocno[src_regno] >= 0)
{
dest_regno -= offset;
- if (dest_regno >= 0 && dest_regno < FIRST_PSEUDO_REGISTER)
+ if (dest_regno < FIRST_PSEUDO_REGISTER)
{
if (copy)
SET_REGBIT (hard_reg_copy_preferences,
&& reg_allocno[dest_regno] >= 0)
{
src_regno += offset;
- if (src_regno >= 0 && src_regno < FIRST_PSEUDO_REGISTER)
+ if (src_regno < FIRST_PSEUDO_REGISTER)
{
if (copy)
SET_REGBIT (hard_reg_copy_preferences,
current life information. */
static regset live_relevant_regs;
-/* Record in live_relevant_regs that register REG became live. This
- is called via note_stores. */
+/* Record in live_relevant_regs and REGS_SET that register REG became live.
+ This is called via note_stores. */
static void
-reg_becomes_live (reg, setter, data)
+reg_becomes_live (reg, setter, regs_set)
rtx reg;
rtx setter ATTRIBUTE_UNUSED;
- void *data ATTRIBUTE_UNUSED;
+ void *regs_set;
{
int regno;
{
int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (nregs-- > 0)
- SET_REGNO_REG_SET (live_relevant_regs, regno++);
+ {
+ SET_REGNO_REG_SET (live_relevant_regs, regno);
+ if (! fixed_regs[regno])
+ SET_REGNO_REG_SET ((regset) regs_set, regno);
+ regno++;
+ }
}
else if (reg_renumber[regno] >= 0)
- SET_REGNO_REG_SET (live_relevant_regs, regno);
+ {
+ SET_REGNO_REG_SET (live_relevant_regs, regno);
+ SET_REGNO_REG_SET ((regset) regs_set, regno);
+ }
}
/* Record in live_relevant_regs that register REGNO died. */
static void
-reg_dies (regno, mode)
+reg_dies (regno, mode, chain)
int regno;
enum machine_mode mode;
+ struct insn_chain *chain;
{
if (regno < FIRST_PSEUDO_REGISTER)
{
int nregs = HARD_REGNO_NREGS (regno, mode);
while (nregs-- > 0)
- CLEAR_REGNO_REG_SET (live_relevant_regs, regno++);
+ {
+ CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+ if (! fixed_regs[regno])
+ SET_REGNO_REG_SET (&chain->dead_or_set, regno);
+ regno++;
+ }
}
else
- CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+ {
+ CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+ if (reg_renumber[regno] >= 0)
+ SET_REGNO_REG_SET (&chain->dead_or_set, regno);
+ }
}
/* Walk the insns of the current function and build reload_insn_chain,
and record register life information. */
-static void
+void
build_insn_chain (first)
rtx first;
{
struct insn_chain **p = &reload_insn_chain;
struct insn_chain *prev = 0;
int b = 0;
+ regset_head live_relevant_regs_head;
- live_relevant_regs = ALLOCA_REG_SET ();
+ live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
for (; first; first = NEXT_INSN (first))
{
c->insn = first;
c->block = b;
- COPY_REG_SET (c->live_before, live_relevant_regs);
-
if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
{
rtx link;
for (link = REG_NOTES (first); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD
&& GET_CODE (XEXP (link, 0)) == REG)
- reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+ reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
+ c);
+
+ COPY_REG_SET (&c->live_throughout, live_relevant_regs);
/* Mark everything born in this instruction as live. */
- note_stores (PATTERN (first), reg_becomes_live, NULL);
+ note_stores (PATTERN (first), reg_becomes_live,
+ &c->dead_or_set);
}
-
- /* Remember which registers are live at the end of the insn, before
- killing those with REG_UNUSED notes. */
- COPY_REG_SET (c->live_after, live_relevant_regs);
+ else
+ COPY_REG_SET (&c->live_throughout, live_relevant_regs);
if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
{
for (link = REG_NOTES (first); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_UNUSED
&& GET_CODE (XEXP (link, 0)) == REG)
- reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+ reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
+ c);
}
}