else if (regno < FIRST_PSEUDO_REGISTER
&& REGNO_MODE_OK_FOR_BASE_P (regno, mode)
- && ! regno_clobbered_p (regno, this_insn))
+ && ! regno_clobbered_p (regno, this_insn, GET_MODE (ad), 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
in this insn, reload it into some other register to be safe.
The CLOBBER is supposed to make the register unavailable
from before this insn to after it. */
- if (regno_clobbered_p (regno, this_insn))
+ if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
(context ? INDEX_REG_CLASS : BASE_REG_CLASS),
/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
int
-regno_clobbered_p (regno, insn)
+regno_clobbered_p (regno, insn, mode, sets)
int regno;
rtx insn;
+ enum machine_mode mode;
+ int sets;
{
- if (GET_CODE (PATTERN (insn)) == CLOBBER
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ int endregno = regno + nregs;
+
+ if ((GET_CODE (PATTERN (insn)) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
&& GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
- return REGNO (XEXP (PATTERN (insn), 0)) == regno;
+ {
+ int test = REGNO (XEXP (PATTERN (insn), 0));
+
+ return test >= regno && test < endregno;
+ }
if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
for (; i >= 0; i--)
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG
- && REGNO (XEXP (elt, 0)) == regno)
- return 1;
+ if ((GET_CODE (elt) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
+ && GET_CODE (XEXP (elt, 0)) == REG)
+ {
+ int test = REGNO (XEXP (elt, 0));
+
+ if (test >= regno && test < endregno)
+ return 1;
+ }
}
}
enum machine_mode));
static int reload_reg_free_p PROTO((int, int, enum reload_type));
static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int));
+static int free_for_value_p PROTO((int, enum machine_mode, int,
+ enum reload_type, rtx, rtx,
+ int, int));
static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type));
static int allocate_reload_reg PROTO((struct insn_chain *, int, int,
int));
or -1 if we did not need a register for this reload. */
int reload_spill_index[MAX_RELOADS];
-/* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by OPNUM and TYPE,
- may be used to load VALUE into it.
-
- Other read-only reloads with the same value do not conflict
- unless OUT is non-zero and these other reloads have to live while
- output reloads live.
- If OUT is CONST0_RTX, this is a special case: it means that the
- test should not be for using register REGNO as reload register, but
- for copying from register REGNO into the reload register.
+/* Subroutine of free_for_value_p, used to check a single register. */
- RELOADNUM is the number of the reload we want to load this value for;
- a reload does not conflict with itself.
-
- When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
- reloads that load an address for the very reload we are considering.
-
- The caller has to make sure that there is no conflict with the return
- register. */
static int
reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
ignore_address_reloads)
return 1;
}
+/* Return 1 if the value in reload reg REGNO, as used by a reload
+ needed for the part of the insn specified by OPNUM and TYPE,
+ may be used to load VALUE into it.
+
+ MODE is the mode in which the register is used, this is needed to
+ determine how many hard regs to test.
+
+ Other read-only reloads with the same value do not conflict
+ unless OUT is non-zero and these other reloads have to live while
+ output reloads live.
+ If OUT is CONST0_RTX, this is a special case: it means that the
+ test should not be for using register REGNO as reload register, but
+ for copying from register REGNO into the reload register.
+
+ RELOADNUM is the number of the reload we want to load this value for;
+ a reload does not conflict with itself.
+
+ When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
+ reloads that load an address for the very reload we are considering.
+
+ The caller has to make sure that there is no conflict with the return
+ register. */
+
+static int
+free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
+ ignore_address_reloads)
+ int regno;
+ enum machine_mode mode;
+ int opnum;
+ enum reload_type type;
+ rtx value, out;
+ int reloadnum;
+ int ignore_address_reloads;
+{
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ while (nregs-- > 0)
+ if (! reload_reg_free_for_value_p (regno, opnum, type, value, out,
+ reloadnum, ignore_address_reloads))
+ return 0;
+ return 1;
+}
+
/* Determine whether the reload reg X overlaps any rtx'es used for
overriding inheritance. Return nonzero if so. */
/* We check reload_reg_used to make sure we
don't clobber the return register. */
&& ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
- && reload_reg_free_for_value_p (regnum,
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1)))
+ && free_for_value_p (regnum, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r, 1)))
&& TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
&& HARD_REGNO_MODE_OK (regnum, reload_mode[r])
/* Look first for regs to share, then for unshared. But
&& (reload_nregs[r] == max_group_size
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
i))
- && reload_reg_free_for_value_p (i, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- const0_rtx, r, 1))
+ && free_for_value_p (i, reload_mode[r], reload_opnum[r],
+ reload_when_needed[r], reload_in[r],
+ const0_rtx, r, 1))
{
/* If a group is needed, verify that all the subsequent
registers still have their values intact. */
break;
if (i1 != n_earlyclobbers
- || ! (reload_reg_free_for_value_p
- (i, reload_opnum[r], reload_when_needed[r],
- reload_in[r], reload_out[r], r, 1))
+ || ! (free_for_value_p (i, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ reload_out[r], r, 1))
/* Don't use it if we'd clobber a pseudo reg. */
|| (TEST_HARD_REG_BIT (reg_used_in_insn, i)
&& reload_out[r]
&& rtx_equal_p (reload_out[r],
reload_reg_rtx[r])))
{
- reload_override_in[r] = last_reg;
- reload_inheritance_insn[r]
- = reg_reloaded_insn[i];
+ if (! reload_optional[r])
+ {
+ reload_override_in[r] = last_reg;
+ reload_inheritance_insn[r]
+ = reg_reloaded_insn[i];
+ }
}
else
{
and of the desired class. */
if (equiv != 0
&& ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
- && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1))
+ && ! free_for_value_p (regno, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r,
+ 1))
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
regno)))
equiv = 0;
if (reg_overlap_mentioned_for_reload_p (equiv,
reload_earlyclobbers[i]))
{
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
equiv = 0;
break;
}
In particular, we then can't use EQUIV for a
RELOAD_FOR_OUTPUT_ADDRESS reload. */
- if (equiv != 0 && regno_clobbered_p (regno, insn))
+ if (equiv != 0 && regno_clobbered_p (regno, insn,
+ reload_mode[r], 0))
{
switch (reload_when_needed[r])
{
case RELOAD_OTHER:
case RELOAD_FOR_INPUT:
case RELOAD_FOR_OPERAND_ADDRESS:
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
/* Fall through. */
default:
equiv = 0;
break;
}
}
+ else if (regno_clobbered_p (regno, insn, reload_mode[r], 1))
+ switch (reload_when_needed[r])
+ {
+ case RELOAD_FOR_OTHER_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ case RELOAD_FOR_INPUT:
+ break;
+ case RELOAD_OTHER:
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
+ /* Fall through. */
+ default:
+ equiv = 0;
+ break;
+ }
/* If we found an equivalent reg, say no code need be generated
to load it, and use it as our reload reg. */
check_reg = reload_override_in[r];
else
continue;
- if (! reload_reg_free_for_value_p (true_regnum (check_reg),
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- (reload_inherited[r]
- ? reload_out[r] : const0_rtx),
- r, 1))
+ if (! free_for_value_p (true_regnum (check_reg), reload_mode[r],
+ reload_opnum[r], reload_when_needed[r],
+ reload_in[r],
+ (reload_inherited[r]
+ ? reload_out[r] : const0_rtx),
+ r, 1))
{
if (pass)
continue;
/* Don't use OLDEQUIV if any other reload changes it at an
earlier stage of this insn or at this stage. */
- if (! reload_reg_free_for_value_p (regno, reload_opnum[j],
- reload_when_needed[j],
- reload_in[j], const0_rtx, j,
- 0))
+ if (! free_for_value_p (regno, reload_mode[j],
+ reload_opnum[j],
+ reload_when_needed[j],
+ reload_in[j], const0_rtx, j, 0))
oldequiv = 0;
/* If it is no cheaper to copy from OLDEQUIV into the
/* This is unsafe if some other reload
uses the same reg first. */
&& ! conflicts_with_override (reloadreg)
- && reload_reg_free_for_value_p (REGNO (reloadreg),
- reload_opnum[j],
- reload_when_needed[j],
- old, reload_out[j],
- j, 0))
+ && free_for_value_p (REGNO (reloadreg), reload_mode[j],
+ reload_opnum[j], reload_when_needed[j],
+ old, reload_out[j], j, 0))
{
rtx temp = PREV_INSN (insn);
while (temp && GET_CODE (temp) == NOTE)
|| !(set = single_set (insn))
|| rtx_equal_p (old, SET_DEST (set))
|| !reg_mentioned_p (old, SET_SRC (set))
- || !regno_clobbered_p (REGNO (old), insn))
+ || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0))
gen_reload (old, reloadreg, reload_opnum[j],
reload_when_needed[j]);
}