static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
static int n_memlocs;
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Save MEMs needed to copy from one class of registers to another. One MEM
+ is used per mode, but normally only one or two modes are ever used.
+
+ We keep two versions, before and after register elimination. */
+
+static rtx secondary_memlocs[NUM_MACHINE_MODES];
+static rtx secondary_memlocs_elim[NUM_MACHINE_MODES];
+#endif
+
/* The instruction we are doing reloads for;
so we can test whether a register dies in it. */
static rtx this_insn;
}
#endif /* HAVE_SECONDARY_RELOADS */
\f
+#ifdef SECONDARY_MEMORY_NEEDED
+
+/* Return a memory location that will be used to copy X in mode MODE.
+ If we haven't already made a location for this mode in this insn,
+ call find_reloads_address on the location being returned. */
+
+rtx
+get_secondary_mem (x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ rtx loc;
+ int mem_valid;
+
+ /* If MODE is narrower than a word, widen it. This is required because
+ most machines that require these memory locations do not support
+ short load and stores from all registers (e.g., FP registers). We could
+ possibly conditionalize this, but we lose nothing by doing the wider
+ mode. */
+
+ if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
+ mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
+
+ /* If we already have made a MEM for this insn, return it. */
+ if (secondary_memlocs_elim[(int) mode] != 0)
+ return secondary_memlocs_elim[(int) mode];
+
+ /* If this is the first time we've tried to get a MEM for this mode,
+ allocate a new one. `something_changed' in reload will get set
+ by noticing that the frame size has changed. */
+
+ if (secondary_memlocs[(int) mode] == 0)
+ secondary_memlocs[(int) mode]
+ = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+
+ /* Get a version of the address doing any eliminations needed. If that
+ didn't give us a new MEM, make a new one if it isn't valid. */
+
+ loc = eliminate_regs (secondary_memlocs[(int) mode], 0, NULL_RTX);
+ mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+
+ if (! mem_valid && loc == secondary_memlocs[(int) mode])
+ loc = copy_rtx (loc);
+
+ /* The only time the call below will do anything is if the stack
+ offset is too large. In that case IND_LEVELS doesn't matter, so we
+ can just pass a zero. */
+ if (! mem_valid)
+ find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0), x, 0);
+
+ secondary_memlocs_elim[(int) mode] = loc;
+
+ return loc;
+}
+
+/* Clear any secondary memory locations we've made. */
+
+void
+clear_secondary_mem ()
+{
+ int i;
+
+ for (i = 0; i < NUM_MACHINE_MODES; i++)
+ secondary_memlocs[i] = 0;
+}
+#endif /* SECONDARY_MEMORY_NEEDED */
+\f
/* Record one (sometimes two) reload that needs to be performed.
IN is an rtx saying where the data are to be found before this instruction.
OUT says where they must be stored after the instruction.
we can't handle it here because CONST_INT does not indicate a mode.
Similarly, we must reload the inside expression if we have a
- STRICT_LOW_PART (presumably, in == out in the cas). */
+ STRICT_LOW_PART (presumably, in == out in the cas).
+
+ Also reload the inner expression if it does not require a secondary
+ reload but the SUBREG does. */
if (in != 0 && GET_CODE (in) == SUBREG
&& (GET_CODE (SUBREG_REG (in)) != REG
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
- GET_MODE (SUBREG_REG (in)))))))))
+ GET_MODE (SUBREG_REG (in)))))))
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+ || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
+ && (SECONDARY_INPUT_RELOAD_CLASS (class,
+ GET_MODE (SUBREG_REG (in)),
+ SUBREG_REG (in))
+ == NO_REGS))
+#endif
+ ))
{
in_subreg_loc = inloc;
inloc = &SUBREG_REG (in);
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)))))))))
+ GET_MODE (SUBREG_REG (out)))))))
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+ || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
+ && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_REG (out))
+ == NO_REGS))
+#endif
+ ))
{
out_subreg_loc = outloc;
outloc = &SUBREG_REG (out);
/* If IN appears in OUT, we can't share any input-only reload for IN. */
if (in != 0 && out != 0 && GET_CODE (out) == MEM
&& (GET_CODE (in) == REG || GET_CODE (in) == MEM)
- && reg_overlap_mentioned_p (in, XEXP (out, 0)))
+ && reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
dont_share = 1;
+ /* If IN is a SUBREG of a hard register, make a new REG. This
+ simplifies some of the cases below. */
+
+ if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
+ in = gen_rtx (REG, GET_MODE (in),
+ REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+
+ /* Similarly for OUT. */
+ if (out != 0 && GET_CODE (out) == SUBREG
+ && GET_CODE (SUBREG_REG (out)) == REG
+ && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
+ out = gen_rtx (REG, GET_MODE (out),
+ REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
+
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
if (in != 0)
class = PREFERRED_RELOAD_CLASS (in, class);
+ /* Output reloads may need analagous treatment, different in detail. */
+#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+ if (out != 0)
+ class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
+#endif
+
/* Make sure we use a class that can handle the actual pseudo
inside any subreg. For example, on the 386, QImode regs
can appear within SImode subregs. Although GENERAL_REGS
|| secondary_icode != CODE_FOR_nothing
|| secondary_out_icode != CODE_FOR_nothing))
{
- push_reload (0, out, 0, outloc, class, VOIDmode, outmode,
- strict_low, optional, needed_for);
+ push_reload (NULL_RTX, out, NULL_PTR, outloc, class,
+ VOIDmode, outmode, strict_low, optional, needed_for);
out = 0;
outloc = 0;
outmode = VOIDmode;
n_reloads++;
i = n_reloads;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+ /* If we need a memory location to copy between the two
+ reload regs, set it up now. */
+
+ if (in != 0 && secondary_icode == CODE_FOR_nothing
+ && SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode))
+ get_secondary_mem (in, inmode);
+
+ if (out != 0 && secondary_icode == CODE_FOR_nothing
+ && SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode))
+ get_secondary_mem (out, outmode);
+#endif
}
}
#endif
reload_secondary_p[i] = 0;
n_reloads++;
+
+#ifdef SECONDARY_MEMORY_NEEDED
+ /* If a memory location is needed for the copy, make one. */
+ if (in != 0 && GET_CODE (in) == REG
+ && REGNO (in) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
+ class, inmode))
+ get_secondary_mem (in, inmode);
+
+ if (out != 0 && GET_CODE (out) == REG
+ && REGNO (out) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
+ outmode))
+ get_secondary_mem (out, outmode);
+#endif
}
else
{
/* Args reversed because the first arg seems to be
the one that we imagine being modified
while the second is the one that might be affected. */
- || (! reg_overlap_mentioned_p (reload_out[output_reload],
- reload_in[i])
+ || (! reg_overlap_mentioned_for_reload_p (reload_out[output_reload],
+ reload_in[i])
/* However, if the input is a register that appears inside
the output, then we also can't share.
Imagine (set (mem (reg 69)) (plus (reg 69) ...)).
result to be stored in memory, then that result
will clobber the address of the memory ref. */
&& ! (GET_CODE (reload_in[i]) == REG
- && reg_overlap_mentioned_p (reload_in[i],
- reload_out[output_reload])))))
+ && reg_overlap_mentioned_for_reload_p (reload_in[i],
+ reload_out[output_reload])))))
{
int j;
for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_DEAD
&& GET_CODE (XEXP (note, 0)) == REG
- && ! reg_overlap_mentioned_p (XEXP (note, 0),
- reload_out[output_reload])
+ && ! reg_overlap_mentioned_for_reload_p (XEXP (note, 0),
+ reload_out[output_reload])
&& REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_MODE_OK (REGNO (XEXP (note, 0)), reload_outmode[output_reload])
&& TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[output_reload]],
register int regno = REGNO (in) + in_offset;
int nwords = HARD_REGNO_NREGS (regno, GET_MODE (real_in));
- if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, 0)
+ if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, NULL_PTR)
&& ! hard_reg_set_here_p (regno, regno + nwords,
PATTERN (this_insn)))
{
int val;
switch (fmt[i])
{
+ case 'w':
+ if (XWINT (x, i) != XWINT (y, i))
+ return 0;
+ break;
+
case 'i':
if (XINT (x, i) != XINT (y, i))
return 0;
\f
/* Return the number of times character C occurs in string S. */
-static int
+int
n_occurrences (c, s)
char c;
char *s;
int reg_flag;
int safe;
rtx base;
- int start;
- int end;
+ HOST_WIDE_INT start;
+ HOST_WIDE_INT end;
};
/* Describe the range of registers or memory referenced by X.
struct decomposition xdata;
if (ydata.reg_flag)
- return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, 0);
+ return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, NULL_PTR);
if (ydata.safe)
return 1;
return (xdata.start >= ydata.end || ydata.start >= xdata.end);
}
-/* Similiar, but calls decompose. */
+/* Similar, but calls decompose. */
int
safe_from_earlyclobber (op, clobber)
no_output_reloads = 1;
#endif
+#ifdef SECONDARY_MEMORY_NEEDED
+ /* The eliminated forms of any secondary memory locations are per-insn, so
+ clear them out here. */
+
+ bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+#endif
+
/* Find what kind of insn this is. NOPERANDS gets number of operands.
Make OPERANDS point to a vector of operand values.
Make OPERAND_LOCS point to a vector of pointers to
while (c = *p++)
if (c == '%')
{
- /* The last operand should not be marked commutative. This
- problem is hard to detect, so make it obvious by calling
- abort here. */
+ /* The last operand should not be marked commutative. */
if (i == noperands - 1)
- abort ();
-
- commutative = i;
+ {
+ if (this_insn_is_asm)
+ warning_for_asm (this_insn,
+ "`%%' constraint used with last operand");
+ else
+ abort ();
+ }
+ else
+ commutative = i;
}
else if (c >= '0' && c <= '9')
{
if (constraints[i][0] == 'p')
{
- find_reloads_address (VOIDmode, 0,
+ find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
recog_operand[i], ind_levels);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
? reg_preferred_class (REGNO (recog_operand[i])) : NO_REGS);
pref_or_nothing[i]
= (code == REG && REGNO (recog_operand[i]) > FIRST_PSEUDO_REGISTER
- && reg_preferred_or_nothing (REGNO (recog_operand[i])));
+ && reg_alternate_class (REGNO (recog_operand[i])) == NO_REGS);
}
/* If this is simply a copy from operand 1 to operand 0, merge the
/* Match any floating double constant, but only if
we can examine the bits of it reliably. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_INT != BITS_PER_WORD)
+ || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& GET_MODE (operand) != VOIDmode && ! flag_pretend_float)
break;
if (GET_CODE (operand) == CONST_DOUBLE)
&& GET_CODE (recog_operand[i]) == MEM)
{
operand_reloadnum[i]
- = push_reload (XEXP (recog_operand[i], 0), 0,
- &XEXP (recog_operand[i], 0), 0,
+ = push_reload (XEXP (recog_operand[i], 0), NULL_RTX,
+ &XEXP (recog_operand[i], 0), NULL_PTR,
BASE_REG_CLASS, GET_MODE (XEXP (recog_operand[i], 0)),
- VOIDmode, 0, 0, 0);
+ VOIDmode, 0, 0, NULL_RTX);
reload_inc[operand_reloadnum[i]]
= GET_MODE_SIZE (GET_MODE (recog_operand[i]));
}
(modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
(insn_code_number < 0 ? 0
: insn_operand_strict_low[insn_code_number][i]),
- 0, 0);
+ 0, NULL_RTX);
/* In a matching pair of operands, one must be input only
and the other must be output only.
Pass the input operand as IN and the other as OUT. */
(enum reg_class) goal_alternative[i],
operand_mode[i],
operand_mode[goal_alternative_matched[i]],
- 0, 0, 0);
+ 0, 0, NULL_RTX);
operand_reloadnum[goal_alternative_matched[i]] = output_reloadnum;
}
else if (modified[i] == RELOAD_WRITE
(enum reg_class) goal_alternative[i],
operand_mode[goal_alternative_matched[i]],
operand_mode[i],
- 0, 0, 0);
+ 0, 0, NULL_RTX);
operand_reloadnum[i] = output_reloadnum;
}
else if (insn_code_number >= 0)
(modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
(insn_code_number < 0 ? 0
: insn_operand_strict_low[insn_code_number][i]),
- 1, 0);
+ 1, NULL_RTX);
/* Make an optional reload for an explicit mem ref. */
else if (GET_CODE (operand) == MEM
&& (enum reg_class) goal_alternative[i] != NO_REGS
(modified[i] == RELOAD_READ ? VOIDmode : operand_mode[i]),
(insn_code_number < 0 ? 0
: insn_operand_strict_low[insn_code_number][i]),
- 1, 0);
+ 1, NULL_RTX);
else
non_reloaded_operands[n_non_reloaded_operands++] = recog_operand[i];
}
/* Now get the operand values out of the insn. */
- decode_asm_operands (body, recog_operand, recog_operand_loc, 0, 0);
+ decode_asm_operands (body, recog_operand, recog_operand_loc,
+ NULL_PTR, NULL_PTR);
break;
}
if (insn_code_number >= 0)
if (insn_operand_address_p[insn_code_number][i])
- find_reloads_address (VOIDmode, 0,
+ find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
recog_operand[i], ind_levels);
if (code == MEM)
x = gen_rtx (MEM, GET_MODE (x), addr);
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- find_reloads_address (GET_MODE (x), 0,
+ find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
&XEXP (x, 0), x, ind_levels);
}
addr = plus_constant (addr, offset);
x = gen_rtx (MEM, GET_MODE (x), addr);
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
- find_reloads_address (GET_MODE (x), 0,
+ find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
&XEXP (x, 0), x, ind_levels);
}
else if (reg_equiv_address[regno] != 0)
{
tem = make_memloc (ad, regno);
- find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
+ find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
&XEXP (tem, 0), operand, ind_levels);
- push_reload (tem, 0, loc, 0, BASE_REG_CLASS,
+ push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
GET_MODE (ad), VOIDmode, 0, 0,
operand);
return 1;
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, 0, loc, 0, BASE_REG_CLASS,
+ push_reload (ad, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
GET_MODE (ad), VOIDmode, 0, 0, operand);
return 1;
}
{
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
- push_reload (tem, 0, loc, 0,
+ push_reload (tem, NULL_RTX, loc, NULL_PTR,
BASE_REG_CLASS, GET_MODE (tem), VOIDmode, 0,
0, operand);
return 1;
register rtx link;
int reloadnum
- = push_reload (x, 0, loc, 0,
+ = push_reload (x, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), GET_MODE (x), VOIDmode, 0, operand);
reload_inc[reloadnum]
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
operand, ind_levels);
- reloadnum = push_reload (x, 0, loc, 0,
+ reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
reload_inc[reloadnum]
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
operand, ind_levels);
- push_reload (*loc, 0, loc, 0,
+ push_reload (*loc, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
return 1;
if (reg_equiv_constant[regno] != 0)
{
- push_reload (reg_equiv_constant[regno], 0, loc, 0,
+ push_reload (reg_equiv_constant[regno], NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
return 1;
that feeds this insn. */
if (reg_equiv_mem[regno] != 0)
{
- push_reload (reg_equiv_mem[regno], 0, loc, 0,
+ push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
return 1;
|| !(context ? REGNO_OK_FOR_INDEX_P (regno)
: REGNO_OK_FOR_BASE_P (regno))))
{
- push_reload (x, 0, loc, 0,
+ push_reload (x, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
return 1;
from before this insn to after it. */
if (regno_clobbered_p (regno, this_insn))
{
- push_reload (x, 0, loc, 0,
+ push_reload (x, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, operand);
return 1;
needed_for, ind_levels);
}
- push_reload (x, 0, loc, 0, class, mode, VOIDmode, 0, 0, needed_for);
+ push_reload (x, NULL_RTX, loc, NULL_PTR, class,
+ mode, VOIDmode, 0, 0, needed_for);
}
\f
/* Substitute into X the registers into which we have reloaded
case REG:
i = REGNO (x);
- if (i >= FIRST_PSEUDO_REGISTER && reg_renumber[i] == -1
- && ((reg_equiv_address[i]
- && refers_to_regno_for_reload_p (regno, endregno,
- reg_equiv_address[i], 0))
- || (reg_equiv_mem[i]
- && refers_to_regno_for_reload_p (regno, endregno,
- XEXP (reg_equiv_mem[i], 0),
- 0))))
- return 1;
+ /* If this is a pseudo, a hard register must not have been allocated.
+ X must therefore either be a constant or be in memory. */
+ if (i >= FIRST_PSEUDO_REGISTER)
+ {
+ if (reg_equiv_memory_loc[i])
+ return refers_to_regno_for_reload_p (regno, endregno,
+ reg_equiv_memory_loc[i],
+ NULL_PTR);
+
+ if (reg_equiv_constant[i])
+ return 0;
+
+ abort ();
+ }
return (endregno > i
&& regno < i + (i < FIRST_PSEUDO_REGISTER
}
return 0;
}
+
+/* Nonzero if modifying X will affect IN. If X is a register or a SUBREG,
+ we check if any register number in X conflicts with the relevant register
+ numbers. If X is a constant, return 0. If X is a MEM, return 1 iff IN
+ contains a MEM (we don't bother checking for memory addresses that can't
+ conflict because we expect this to be a rare case.
+
+ This function is similar to reg_overlap_mention_p in rtlanal.c except
+ that we look at equivalences for pseudos that didn't get hard registers. */
+
+int
+reg_overlap_mentioned_for_reload_p (x, in)
+ rtx x, in;
+{
+ int regno, endregno;
+
+ if (GET_CODE (x) == SUBREG)
+ {
+ regno = REGNO (SUBREG_REG (x));
+ if (regno < FIRST_PSEUDO_REGISTER)
+ regno += SUBREG_WORD (x);
+ }
+ else if (GET_CODE (x) == REG)
+ {
+ regno = REGNO (x);
+
+ /* If this is a pseudo, it must not have been assigned a hard register.
+ Therefore, it must either be in memory or be a constant. */
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ if (reg_equiv_memory_loc[regno])
+ return refers_to_mem_for_reload_p (in);
+ else if (reg_equiv_constant[regno])
+ return 0;
+ abort ();
+ }
+ }
+ else if (CONSTANT_P (x))
+ return 0;
+ else if (GET_CODE (x) == MEM)
+ return refers_to_mem_for_reload_p (in);
+ else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
+ || GET_CODE (x) == CC0)
+ return reg_mentioned_p (x, in);
+ else
+ abort ();
+
+ endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+ ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+
+ return refers_to_regno_for_reload_p (regno, endregno, in, NULL_PTR);
+}
+
+/* Return nonzero if anything in X contains a MEM. Look also for pseudo
+ registers. */
+
+int
+refers_to_mem_for_reload_p (x)
+ rtx x;
+{
+ char *fmt;
+ int i;
+
+ if (GET_CODE (x) == MEM)
+ return 1;
+
+ if (GET_CODE (x) == REG)
+ return (REGNO (x) >= FIRST_PSEUDO_REGISTER
+ && reg_equiv_memory_loc[REGNO (x)]);
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ if (fmt[i] == 'e'
+ && (GET_CODE (XEXP (x, i)) == MEM
+ || refers_to_mem_for_reload_p (XEXP (x, i))))
+ return 1;
+
+ return 0;
+}
\f
#if 0
/* If we are looking for a constant,
and something equivalent to that constant was copied
into a reg, we can use that reg. */
- || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+ || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+ NULL_RTX))
&& rtx_equal_p (XEXP (tem, 0), goal)
&& (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0)
- || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+ || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+ NULL_RTX))
&& GET_CODE (SET_DEST (pat)) == REG
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (XEXP (tem, 0))) == MODE_FLOAT
&& (valtry = operand_subword (SET_DEST (pat), 0, 0,
VOIDmode))
&& (valueno = true_regnum (valtry)) >= 0)
- || (goal_const && (tem = find_reg_note (p, REG_EQUIV, 0))
+ || (goal_const && (tem = find_reg_note (p, REG_EQUIV,
+ NULL_RTX))
&& GET_CODE (SET_DEST (pat)) == REG
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (XEXP (tem, 0))) == MODE_FLOAT
/* If we propose to get the value from the stack pointer or if GOAL is
a MEM based on the stack pointer, we need a stable SP. */
if (valueno == STACK_POINTER_REGNUM
- || (goal_mem && reg_overlap_mentioned_p (stack_pointer_rtx, goal)))
+ || (goal_mem && reg_overlap_mentioned_for_reload_p (stack_pointer_rtx,
+ goal)))
need_stable_sp = 1;
/* Reject VALUE if the copy-insn moved the wrong sort of datum. */
and is also a register that appears in the address of GOAL. */
if (goal_mem && value == SET_DEST (PATTERN (where))
- && refers_to_regno_p (valueno,
- valueno + HARD_REGNO_NREGS (valueno, mode),
- goal, 0))
+ && refers_to_regno_for_reload_p (valueno,
+ (valueno
+ + HARD_REGNO_NREGS (valueno, mode)),
+ goal, NULL_PTR))
return 0;
/* Reject registers that overlap GOAL. */
&& xregno + xnregs > valueno)
return 0;
if (goal_mem_addr_varies
- && reg_overlap_mentioned_p (dest, goal))
+ && reg_overlap_mentioned_for_reload_p (dest, goal))
return 0;
}
else if (goal_mem && GET_CODE (dest) == MEM
&& xregno + xnregs > valueno)
return 0;
if (goal_mem_addr_varies
- && reg_overlap_mentioned_p (dest, goal))
+ && reg_overlap_mentioned_for_reload_p (dest,
+ goal))
return 0;
}
else if (goal_mem && GET_CODE (dest) == MEM
if (incno < valueno + valuenregs && incno >= valueno)
return 0;
if (goal_mem_addr_varies
- && reg_overlap_mentioned_p (XEXP (link, 0), goal))
+ && reg_overlap_mentioned_for_reload_p (XEXP (link, 0),
+ goal))
return 0;
}
}