as part of a group, even if it seems to be otherwise ok. */
static HARD_REG_SET counted_for_nongroups;
+/* Indexed by pseudo reg number N,
+ says may not delete stores into the real (memory) home of pseudo N.
+ This is set if we already substituted a memory equivalent in some uses,
+ which happens when we have to eliminate the fp from it. */
+static char *cannot_omit_stores;
+
/* Nonzero if indirect addressing is supported on the machine; this means
that spilling (REG n) does not require reloading it into a register in
order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))). The
FILE *));
static void delete_dead_insn PROTO((rtx));
static void alter_reg PROTO((int, int));
+static void mark_scratch_live PROTO((rtx));
static void set_label_offsets PROTO((rtx, rtx, int));
static int eliminate_regs_in_insn PROTO((rtx, int));
static void mark_not_eliminable PROTO((rtx, rtx));
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
mark_home_live (i);
+ for (i = 0; i < scratch_list_length; i++)
+ if (scratch_list[i])
+ mark_scratch_live (scratch_list[i]);
+
/* Make sure that the last insn in the chain
is not something that needs reloading. */
emit_note (NULL_PTR, NOTE_INSN_DELETED);
bzero (reg_equiv_address, max_regno * sizeof (rtx));
reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
bzero (reg_max_ref_width, max_regno * sizeof (int));
+ cannot_omit_stores = (char *) alloca (max_regno);
+ bzero (cannot_omit_stores, max_regno);
/* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
Also find all paradoxical subregs
and constant, it is probably not addressable because the constant is
out of range, in that case record the address; we will generate
hairy code to compute the address in a register each time it is
- needed.
+ needed. Similarly if it is a hard register, but one that is not
+ valid as an address register.
If the location is not addressable, but does not have one of the
above forms, assign a stack slot. We have to do this to avoid the
XEXP (x, 0)))
reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
else if (CONSTANT_P (XEXP (x, 0))
+ || (GET_CODE (XEXP (x, 0)) == REG
+ && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
|| (GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
&& (REGNO (XEXP (XEXP (x, 0), 0))
&& TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
&& HARD_REGNO_MODE_OK (j, group_mode[class])
&& ! TEST_HARD_REG_BIT (counted_for_nongroups,
- j + 1))
+ j + 1)
+ && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
break;
}
while (max_needs[class] > 0 || max_nongroups[class] > 0)
{
+#ifdef SMALL_REGISTER_CLASSES
+ /* This should be right for all machines, but only the 386
+ is known to need it, so this conditional plays safe.
+ ??? For 2.5, try making this unconditional. */
+ /* If we spilled enough regs, but they weren't counted
+ against the non-group need, see if we can count them now.
+ If so, we can avoid some actual spilling. */
+ if (max_needs[class] <= 0 && max_nongroups[class] > 0)
+ for (i = 0; i < n_spills; i++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class],
+ spill_regs[i])
+ && !TEST_HARD_REG_BIT (counted_for_groups,
+ spill_regs[i])
+ && !TEST_HARD_REG_BIT (counted_for_nongroups,
+ spill_regs[i])
+ && max_nongroups[class] > 0)
+ {
+ register enum reg_class *p;
+
+ SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]);
+ max_nongroups[class]--;
+ p = reg_class_superclasses[class];
+ while (*p != LIM_REG_CLASSES)
+ max_nongroups[(int) *p++]--;
+ }
+ if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
+ break;
+#endif
+
/* Consider the potential reload regs that aren't
yet in use as reload regs, in order of preference.
Find the most preferred one that's in this class. */
reg_equiv_constant = 0;
reg_equiv_memory_loc = 0;
+ free (scratch_list);
+ scratch_list = 0;
+ free (scratch_block);
+ scratch_block = 0;
+
return failure;
}
\f
while (i < lim)
regs_ever_live[i++] = 1;
}
+
+/* Mark the registers used in SCRATCH as being live. */
+
+static void
+mark_scratch_live (scratch)
+ rtx scratch;
+{
+ register int i;
+ int regno = REGNO (scratch);
+ int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch));
+
+ for (i = regno; i < lim; i++)
+ regs_ever_live[i] = 1;
+}
\f
/* This function handles the tracking of elimination offsets around branches.
new = eliminate_regs (reg_equiv_memory_loc[regno],
mem_mode, NULL_RTX);
if (new != reg_equiv_memory_loc[regno])
- return copy_rtx (new);
+ {
+ cannot_omit_stores[regno] = 1;
+ return copy_rtx (new);
+ }
}
return x;
if (GET_CODE (new) == MEM
&& (GET_MODE_SIZE (GET_MODE (x))
<= GET_MODE_SIZE (GET_MODE (new)))
-#if defined(BYTES_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
+#if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
/* On these machines we will be reloading what is
inside the SUBREG if it originally was a pseudo and
the inner and outer modes are both a word or
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS];
ep++)
if (ep->from_rtx == XEXP (SET_SRC (old_body), 0)
- && ep->can_eliminate
- && ep->offset == - INTVAL (XEXP (SET_SRC (old_body), 1)))
+ && ep->can_eliminate)
{
- PATTERN (insn) = gen_rtx (SET, VOIDmode,
- SET_DEST (old_body), ep->to_rtx);
- INSN_CODE (insn) = -1;
- val = 1;
- goto done;
+ /* We must stop at the first elimination that will be used.
+ If this one would replace the PLUS with a REG, do it
+ now. Otherwise, quit the loop and let eliminate_regs
+ do its normal replacement. */
+ if (ep->offset == - INTVAL (XEXP (SET_SRC (old_body), 1)))
+ {
+ PATTERN (insn) = gen_rtx (SET, VOIDmode,
+ SET_DEST (old_body), ep->to_rtx);
+ INSN_CODE (insn) = -1;
+ val = 1;
+ goto done;
+ }
+
+ break;
}
}
FILE *dumpfile;
int cant_eliminate;
{
+ enum reg_class class = REGNO_REG_CLASS (regno);
int something_changed = 0;
register int i;
PSEUDO_REGNO_MODE (i))
> regno))
{
- enum reg_class class = REGNO_REG_CLASS (regno);
-
/* If this register belongs solely to a basic block which needed no
spilling of any class that this register is contained in,
leave it be, unless we are spilling this register because
i, reg_renumber[i]);
}
}
+ for (i = 0; i < scratch_list_length; i++)
+ {
+ if (scratch_list[i] && REGNO (scratch_list[i]) == regno)
+ {
+ if (! cant_eliminate && basic_block_needs[0]
+ && ! basic_block_needs[(int) class][scratch_block[i]])
+ {
+ enum reg_class *p;
+
+ for (p = reg_class_superclasses[(int) class];
+ *p != LIM_REG_CLASSES; p++)
+ if (basic_block_needs[(int) *p][scratch_block[i]] > 0)
+ break;
+
+ if (*p == LIM_REG_CLASSES)
+ continue;
+ }
+ PUT_CODE (scratch_list[i], SCRATCH);
+ scratch_list[i] = 0;
+ something_changed = 1;
+ continue;
+ }
+ }
return something_changed;
}
if (k == nr)
{
- /* Mark the register as in use for this part of
- the insn. */
- mark_reload_reg_in_use (spill_regs[i],
- reload_opnum[r],
- reload_when_needed[r],
- reload_mode[r]);
- reload_reg_rtx[r] = reg_last_reload_reg[regno];
- reload_inherited[r] = 1;
- reload_inheritance_insn[r] = reg_reloaded_insn[i];
- reload_spill_index[r] = i;
- SET_HARD_REG_BIT (reload_reg_used_for_inherit,
- spill_regs[i]);
+ int i1;
+
+ /* We found a register that contains the
+ value we need. If this register is the
+ same as an `earlyclobber' operand of the
+ current insn, just mark it as a place to
+ reload from since we can't use it as the
+ reload register itself. */
+
+ for (i1 = 0; i1 < n_earlyclobbers; i1++)
+ if (reg_overlap_mentioned_for_reload_p
+ (reg_last_reload_reg[regno],
+ reload_earlyclobbers[i1]))
+ break;
+
+ if (i1 != n_earlyclobbers
+ /* Don't really use the inherited spill reg
+ if we need it wider than we've got it. */
+ || (GET_MODE_SIZE (reload_mode[r])
+ > GET_MODE_SIZE (mode)))
+ reload_override_in[r] = reg_last_reload_reg[regno];
+ else
+ {
+ /* We can use this as a reload reg. */
+ /* Mark the register as in use for this part of
+ the insn. */
+ mark_reload_reg_in_use (spill_regs[i],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_mode[r]);
+ reload_reg_rtx[r] = reg_last_reload_reg[regno];
+ reload_inherited[r] = 1;
+ reload_inheritance_insn[r]
+ = reg_reloaded_insn[i];
+ reload_spill_index[r] = i;
+ SET_HARD_REG_BIT (reload_reg_used_for_inherit,
+ spill_regs[i]);
+ }
}
}
}
oldequiv_reg = SUBREG_REG (oldequiv);
/* Encapsulate both RELOADREG and OLDEQUIV into that mode,
- then load RELOADREG from OLDEQUIV. */
+ then load RELOADREG from OLDEQUIV. Note that we cannot use
+ gen_lowpart_common since it can do the wrong thing when
+ RELOADREG has a multi-word mode. Note that RELOADREG
+ must always be a REG here. */
if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_lowpart_common (mode, reloadreg);
+ reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
oldequiv = SUBREG_REG (oldequiv);
if (GET_MODE (oldequiv) != VOIDmode
}
if (GET_MODE (reloadreg) != mode)
- reloadreg = gen_lowpart_common (mode, reloadreg);
+ reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
return;
}
+ if (cannot_omit_stores[REGNO (reg)])
+ return;
+
/* If this insn will store in the pseudo again,
the previous store can be removed. */
if (reload_out[j] == reload_in[j])