static char *regs_live;
+/* Indexed by reg number, nonzero if reg was used in a SUBREG that changes
+ its size. */
+
+static char *regs_change_size;
+
/* Indexed by insn's suid, the set of hard regs live after that insn. */
static HARD_REG_SET *after_insn_hard_regs;
static int stupid_reg_compare PROTO((int *, int *));
static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode,
- int, int));
+ int, int, int));
static void stupid_mark_refs PROTO((rtx, rtx));
\f
/* Stupid life analysis is for the case where only variables declared
/* Allocate tables to record info about regs. */
reg_where_dead = (int *) alloca (nregs * sizeof (int));
- bzero (reg_where_dead, nregs * sizeof (int));
+ bzero ((char *) reg_where_dead, nregs * sizeof (int));
reg_where_born = (int *) alloca (nregs * sizeof (int));
- bzero (reg_where_born, nregs * sizeof (int));
+ bzero ((char *) reg_where_born, nregs * sizeof (int));
reg_order = (int *) alloca (nregs * sizeof (int));
- bzero (reg_order, nregs * sizeof (int));
+ bzero ((char *) reg_order, nregs * sizeof (int));
+
+ regs_change_size = (char *) alloca (nregs * sizeof (char));
+ bzero ((char *) regs_change_size, nregs * sizeof (char));
reg_renumber = (short *) oballoc (nregs * sizeof (short));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
after_insn_hard_regs
= (HARD_REG_SET *) alloca (max_suid * sizeof (HARD_REG_SET));
- bzero (after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
+ bzero ((char *) after_insn_hard_regs, max_suid * sizeof (HARD_REG_SET));
/* Allocate and zero out many data structures
that will record the data from lifetime analysis. */
if (regs_live[i])
SET_HARD_REG_BIT (*p, i);
+ /* Update which hard regs are currently live
+ and also the birth and death suids of pseudo regs
+ based on the pattern of this insn. */
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ stupid_mark_refs (PATTERN (insn), insn);
+
/* Mark all call-clobbered regs as live after each call insn
so that a pseudo whose life span includes this insn
will not go in one of them.
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (call_used_regs[i])
regs_live[i] = 0;
- }
-
- /* Update which hard regs are currently live
- and also the birth and death suids of pseudo regs
- based on the pattern of this insn. */
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- stupid_mark_refs (PATTERN (insn), insn);
+ /* It is important that this be done after processing the insn's
+ pattern because we want the function result register to still
+ be live if it's also used to pass arguments. */
+ stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
+ }
}
/* Now decide the order in which to allocate the pseudo registers. */
reg_preferred_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
- reg_where_dead[r]);
+ reg_where_dead[r],
+ regs_change_size[r]);
/* If no reg available in that class, try alternate class. */
if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS)
reg_alternate_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
- reg_where_dead[r]);
+ reg_where_dead[r],
+ regs_change_size[r]);
}
if (file)
Return -1 if such a block cannot be found.
If CALL_PRESERVED is nonzero, insist on registers preserved
- over subroutine calls, and return -1 if cannot find such. */
+ over subroutine calls, and return -1 if cannot find such.
+
+ If CHANGES_SIZE is nonzero, it means this register was used as the
+ operand of a SUBREG that changes its size. */
static int
-stupid_find_reg (call_preserved, class, mode, born_insn, dead_insn)
+stupid_find_reg (call_preserved, class, mode,
+ born_insn, dead_insn, changes_size)
int call_preserved;
enum reg_class class;
enum machine_mode mode;
int born_insn, dead_insn;
+ int changes_size;
{
register int i, ins;
#ifdef HARD_REG_SET
IOR_COMPL_HARD_REG_SET (used, reg_class_contents[(int) class]);
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+ if (changes_size)
+ IOR_HARD_REG_SET (used,
+ reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
+#endif
+
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
#ifdef REG_ALLOC_ORDER
stupid_mark_refs (x, insn)
rtx x, insn;
{
- register RTX_CODE code = GET_CODE (x);
+ register RTX_CODE code;
register char *fmt;
register int regno, i;
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
if (code == SET || code == CLOBBER)
{
if (SET_DEST (x) != 0 && GET_CODE (SET_DEST (x)) == REG)
return;
}
+ else if (code == SUBREG
+ && GET_CODE (SUBREG_REG (x)) == REG
+ && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
+ && (GET_MODE_SIZE (GET_MODE (x))
+ != GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && (INTEGRAL_MODE_P (GET_MODE (x))
+ || INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (x)))))
+ regs_change_size[REGNO (SUBREG_REG (x))] = 1;
+
/* Register value being used, not set. */
- if (code == REG)
+ else if (code == REG)
{
regno = REGNO (x);
if (regno < FIRST_PSEUDO_REGISTER)