#include "target.h"
#include "ira.h"
-/* True if X is a constant that can be forced into the constant pool. */
-#define CONST_POOL_OK_P(X) \
- (CONSTANT_P (X) \
+/* True if X is a constant that can be forced into the constant pool.
+ MODE is the mode of the operand, or VOIDmode if not known. */
+#define CONST_POOL_OK_P(MODE, X) \
+ ((MODE) != VOIDmode \
+ && CONSTANT_P (X) \
&& GET_CODE (X) != HIGH \
- && !targetm.cannot_force_const_mem (X))
+ && !targetm.cannot_force_const_mem (MODE, X))
/* True if C is a non-empty register class that has too few registers
to be safely used as a reload target class. */
struct replacement
{
rtx *where; /* Location to store in */
- rtx *subreg_loc; /* Location of SUBREG if WHERE is inside
- a SUBREG; 0 otherwise. */
int what; /* which reload this is for */
enum machine_mode mode; /* mode it must have */
};
enum insn_code *, secondary_reload_info *);
static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
int, unsigned int);
-static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
static void push_replacement (rtx *, int, enum machine_mode);
static void dup_replacements (rtx *, rtx *);
static void combine_reloads (void);
/* If X is a paradoxical SUBREG, use the inner value to determine both the
mode and object being reloaded. */
- if (GET_CODE (x) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
+ if (paradoxical_subreg_p (x))
{
x = SUBREG_REG (x);
reload_mode = GET_MODE (x);
return n_reloads;
}
-/* Return nonzero if X is a SUBREG which will require reloading of its
- SUBREG_REG expression. */
+/* Return true if X is a SUBREG that will need reloading of its SUBREG_REG
+ expression. MODE is the mode that X will be used in. OUTPUT is true if
+ the function is invoked for the output part of an enclosing reload. */
-static int
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
+static bool
+reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
{
rtx inner;
/* Only SUBREGs are problematical. */
if (GET_CODE (x) != SUBREG)
- return 0;
+ return false;
inner = SUBREG_REG (x);
- /* If INNER is a constant or PLUS, then INNER must be reloaded. */
+ /* If INNER is a constant or PLUS, then INNER will need reloading. */
if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS)
- return 1;
+ return true;
- /* If INNER is not a hard register, then INNER will not need to
- be reloaded. */
- if (!REG_P (inner)
- || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
- return 0;
+ /* If INNER is not a hard register, then INNER will not need reloading. */
+ if (!(REG_P (inner) && HARD_REGISTER_P (inner)))
+ return false;
/* If INNER is not ok for MODE, then INNER will need reloading. */
- if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
- return 1;
-
- /* If the outer part is a word or smaller, INNER larger than a
- word and the number of regs for INNER is not the same as the
- number of words in INNER, then INNER will need reloading. */
- return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
- && output
+ if (!HARD_REGNO_MODE_OK (subreg_regno (x), mode))
+ return true;
+
+ /* If this is for an output, and the outer part is a word or smaller,
+ INNER is larger than a word and the number of registers in INNER is
+ not the same as the number of words in INNER, then INNER will need
+ reloading (with an in-out reload). */
+ return (output
+ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
!= (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
int i;
int dont_share = 0;
int dont_remove_subreg = 0;
+#ifdef LIMIT_RELOAD_CLASS
rtx *in_subreg_loc = 0, *out_subreg_loc = 0;
+#endif
int secondary_in_reload = -1, secondary_out_reload = -1;
enum insn_code secondary_in_icode = CODE_FOR_nothing;
enum insn_code secondary_out_icode = CODE_FOR_nothing;
For machines that extend byte loads, do this for any SUBREG of a pseudo
where both M1 and M2 are a word or smaller, M1 is wider than M2, and
M2 is an integral mode that gets extended when loaded.
- Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
(However, if OUT is nonzero, we need to reload the reg *and*
the subreg, so do nothing here, and let following statement handle it.)
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
#endif
+ && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (in))]
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
|| strict_low
|| (((REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (in)))
- && ((GET_MODE_SIZE (inmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ && ((GET_MODE_PRECISION (inmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
#ifdef LOAD_EXTEND_OP
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
<= UNITS_PER_WORD)
- && (GET_MODE_SIZE (inmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ && (GET_MODE_PRECISION (inmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
#endif
#ifdef WORD_REGISTER_OPERATIONS
- || ((GET_MODE_SIZE (inmode)
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+ || ((GET_MODE_PRECISION (inmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
/ UNITS_PER_WORD)))
#endif
))
{
+#ifdef LIMIT_RELOAD_CLASS
in_subreg_loc = inloc;
+#endif
inloc = &SUBREG_REG (in);
in = *inloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
inmode = GET_MODE (in);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where M1 is not valid for R if it was not handled by the code above.
+
+ Similar issue for (SUBREG constant ...) if it was not handled by the
+ code above. This can happen if SUBREG_BYTE != 0.
However, we must reload the inner reg *as well as* the subreg in
that case. */
- /* Similar issue for (SUBREG constant ...) if it was not handled by the
- code above. This can happen if SUBREG_BYTE != 0. */
-
- if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
+ if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
{
enum reg_class in_class = rclass;
/* Similarly for paradoxical and problematical SUBREGs on the output.
Note that there is no reason we need worry about the previous value
- of SUBREG_REG (out); even if wider than out,
- storing in a subreg is entitled to clobber it all
- (except in the case of STRICT_LOW_PART,
- and in that case the constraint should label it input-output.) */
+ of SUBREG_REG (out); even if wider than out, storing in a subreg is
+ entitled to clobber it all (except in the case of a word mode subreg
+ or of a STRICT_LOW_PART, in that latter case the constraint should
+ label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
#endif
+ && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))]
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
|| (((REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (out)))
- && ((GET_MODE_SIZE (outmode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+ && ((GET_MODE_PRECISION (outmode)
+ > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
#ifdef WORD_REGISTER_OPERATIONS
- || ((GET_MODE_SIZE (outmode)
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+ || ((GET_MODE_PRECISION (outmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
&& ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
/ UNITS_PER_WORD)))
))
|| (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
- && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- > UNITS_PER_WORD)
- && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- / UNITS_PER_WORD)
- != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
- [GET_MODE (SUBREG_REG (out))]))
- || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
+ /* The case of a word mode subreg
+ is handled differently in the following statement. */
+ && ! (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
+ > UNITS_PER_WORD))
+ && ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))
|| (secondary_reload_class (0, rclass, outmode, out) != NO_REGS
&& (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
SUBREG_REG (out))
#endif
))
{
+#ifdef LIMIT_RELOAD_CLASS
out_subreg_loc = outloc;
+#endif
outloc = &SUBREG_REG (out);
out = *outloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
outmode = GET_MODE (out);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
However, we must reload the inner reg *as well as* the subreg in
- that case. In this case, the inner reg is an in-out reload. */
+ that case and the inner reg is an in-out reload. */
- if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1))
+ if (out != 0 && reload_inner_reg_of_subreg (out, outmode, true))
{
+ enum reg_class in_out_class
+ = find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
+ subreg_regno_offset (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
+ GET_MODE (out)),
+ REGNO (SUBREG_REG (out)));
+
/* This relies on the fact that emit_reload_insns outputs the
instructions for output reloads of type RELOAD_OTHER in reverse
order of the reloads. Thus if the outer reload is also of type
RELOAD_OTHER, we are guaranteed that this inner reload will be
output after the outer reload. */
- dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
- &SUBREG_REG (out),
- find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
- subreg_regno_offset (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)),
- SUBREG_BYTE (out),
- GET_MODE (out)),
- REGNO (SUBREG_REG (out))),
- VOIDmode, VOIDmode, 0, 0,
- opnum, RELOAD_OTHER);
+ &SUBREG_REG (out), in_out_class, VOIDmode, VOIDmode,
+ 0, 0, opnum, RELOAD_OTHER);
+ dont_remove_subreg = 1;
}
/* If IN appears in OUT, we can't share any input-only reload for IN. */
{
struct replacement *r = &replacements[n_replacements++];
r->what = i;
- r->subreg_loc = in_subreg_loc;
r->where = inloc;
r->mode = inmode;
}
struct replacement *r = &replacements[n_replacements++];
r->what = i;
r->where = outloc;
- r->subreg_loc = out_subreg_loc;
r->mode = outmode;
}
}
struct replacement *r = &replacements[n_replacements++];
r->what = reloadnum;
r->where = loc;
- r->subreg_loc = 0;
r->mode = mode;
}
}
&& rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
&& rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
&& rld[i].when_needed != RELOAD_OTHER
- && (CLASS_MAX_NREGS (rld[i].rclass, rld[i].inmode)
- == CLASS_MAX_NREGS (rld[output_reload].rclass,
- rld[output_reload].outmode))
+ && (ira_reg_class_max_nregs [(int)rld[i].rclass][(int) rld[i].inmode]
+ == ira_reg_class_max_nregs [(int) rld[output_reload].rclass]
+ [(int) rld[output_reload].outmode])
&& rld[i].inc == 0
&& rld[i].reg_rtx == 0
#ifdef SECONDARY_MEMORY_NEEDED
else
j = REGNO (y);
- /* On a WORDS_BIG_ENDIAN machine, point to the last register of a
+ /* On a REG_WORDS_BIG_ENDIAN machine, point to the last register of a
multiple hard register group of scalar integer registers, so that
for example (reg:DI 0) and (reg:SI 1) will be considered the same
register. */
- if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+ if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
&& SCALAR_INT_MODE_P (GET_MODE (x))
&& i < FIRST_PSEUDO_REGISTER)
i += hard_regno_nregs[i][GET_MODE (x)] - 1;
- if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
+ if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
&& SCALAR_INT_MODE_P (GET_MODE (y))
&& j < FIRST_PSEUDO_REGISTER)
j += hard_regno_nregs[j][GET_MODE (y)] - 1;
/* Address operands are reloaded in their existing mode,
no matter what is specified in the machine description. */
operand_mode[i] = GET_MODE (recog_data.operand[i]);
+
+ /* If the address is a single CONST_INT pick address mode
+ instead otherwise we will later not know in which mode
+ the reload should be performed. */
+ if (operand_mode[i] == VOIDmode)
+ operand_mode[i] = Pmode;
+
}
else if (code == MEM)
{
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0))
win = 1;
- if (CONST_POOL_OK_P (operand))
+ if (CONST_POOL_OK_P (operand_mode[i], operand))
badop = 0;
constmemok = 1;
break;
&& offsettable_memref_p (reg_equiv_mem (REGNO (operand))))
|| (reg_equiv_address (REGNO (operand)) != 0))))
win = 1;
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
an early reload pass. Note that the test here is
precisely the same as in the code below that calls
force_const_mem. */
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
&& ((targetm.preferred_reload_class (operand,
this_alternative[i])
== NO_REGS)
- || no_input_reloads)
- && operand_mode[i] != VOIDmode)
+ || no_input_reloads))
{
const_to_mem = 1;
if (this_alternative[i] != NO_REGS)
op = XEXP (op, 1);
}
- if (CONST_POOL_OK_P (op)
+ if (CONST_POOL_OK_P (mode, op)
&& ((targetm.preferred_reload_class (op, goal_alternative[i])
== NO_REGS)
- || no_input_reloads)
- && mode != VOIDmode)
+ || no_input_reloads))
{
int this_address_reloaded;
rtx tem = force_const_mem (mode, op);
> GET_MODE_SIZE (rld[i].inmode)))
? rld[i].outmode : rld[i].inmode;
- rld[i].nregs = CLASS_MAX_NREGS (rld[i].rclass, rld[i].mode);
+ rld[i].nregs = ira_reg_class_max_nregs [rld[i].rclass][rld[i].mode];
}
/* Special case a simple move with an input reload and a
/* Skip alternatives before the one requested. */
while (altnum > 0)
{
- while (*constraint++ != ',');
+ while (*constraint++ != ',')
+ ;
altnum--;
}
/* Scan the requested alternative for TARGET_MEM_CONSTRAINT or 'o'.
simplify_gen_subreg (GET_MODE (x), reg_equiv_constant (regno),
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
gcc_assert (tem);
- if (CONSTANT_P (tem) && !LEGITIMATE_CONSTANT_P (tem))
+ if (CONSTANT_P (tem)
+ && !targetm.legitimate_constant_p (GET_MODE (x), tem))
{
tem = force_const_mem (GET_MODE (x), tem);
i = find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
if (regno >= FIRST_PSEUDO_REGISTER
#ifdef LOAD_EXTEND_OP
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && !paradoxical_subreg_p (x)
#endif
- && (reg_equiv_address (regno) != 0
- || (reg_equiv_mem (regno) != 0
- && (! strict_memory_address_addr_space_p
- (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
- MEM_ADDR_SPACE (reg_equiv_mem (regno)))
- || ! offsettable_memref_p (reg_equiv_mem (regno))
- || num_not_at_initial_offset))))
+ && (reg_equiv_address (regno) != 0
+ || (reg_equiv_mem (regno) != 0
+ && (! strict_memory_address_addr_space_p
+ (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
+ MEM_ADDR_SPACE (reg_equiv_mem (regno)))
+ || ! offsettable_memref_p (reg_equiv_mem (regno))
+ || num_not_at_initial_offset))))
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
insn, address_reloaded);
}
else
{
enum reg_class rclass = context_reg_class;
- if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
- > reg_class_size[rclass])
+ if (ira_reg_class_max_nregs [rclass][GET_MODE (SUBREG_REG (x))]
+ > reg_class_size[(int) rclass])
{
x = find_reloads_subreg_address (x, 0, opnum,
ADDR_TYPE (type),
enum reload_type type, int ind_levels)
{
if (CONSTANT_P (x)
- && (! LEGITIMATE_CONSTANT_P (x)
+ && (!targetm.legitimate_constant_p (mode, x)
|| targetm.preferred_reload_class (x, rclass) == NO_REGS))
{
x = force_const_mem (mode, x);
else if (GET_CODE (x) == PLUS
&& CONSTANT_P (XEXP (x, 1))
- && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
+ && (!targetm.legitimate_constant_p (GET_MODE (x), XEXP (x, 1))
|| targetm.preferred_reload_class (XEXP (x, 1), rclass)
== NO_REGS))
{
XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
PUT_MODE (tem, GET_MODE (x));
- if (MEM_OFFSET (tem))
- set_mem_offset (tem, plus_constant (MEM_OFFSET (tem), offset));
- if (MEM_SIZE (tem)
- && INTVAL (MEM_SIZE (tem)) != (HOST_WIDE_INT) outer_size)
- set_mem_size (tem, GEN_INT (outer_size));
+ if (MEM_OFFSET_KNOWN_P (tem))
+ set_mem_offset (tem, MEM_OFFSET (tem) + offset);
+ if (MEM_SIZE_KNOWN_P (tem)
+ && MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
+ set_mem_size (tem, outer_size);
/* If this was a paradoxical subreg that we replaced, the
resulting memory must be sufficiently aligned to allow
if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode)
reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
- /* If we are putting this into a SUBREG and RELOADREG is a
- SUBREG, we would be making nested SUBREGs, so we have to fix
- this up. Note that r->where == &SUBREG_REG (*r->subreg_loc). */
-
- if (r->subreg_loc != 0 && GET_CODE (reloadreg) == SUBREG)
- {
- if (GET_MODE (*r->subreg_loc)
- == GET_MODE (SUBREG_REG (reloadreg)))
- *r->subreg_loc = SUBREG_REG (reloadreg);
- else
- {
- int final_offset =
- SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
-
- /* When working with SUBREGs the rule is that the byte
- offset must be a multiple of the SUBREG's mode. */
- final_offset = (final_offset /
- GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
- final_offset = (final_offset *
- GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
-
- *r->where = SUBREG_REG (reloadreg);
- SUBREG_BYTE (*r->subreg_loc) = final_offset;
- }
- }
- else
- *r->where = reloadreg;
+ *r->where = reloadreg;
}
/* If reload got no reg and isn't optional, something's wrong. */
else
void
copy_replacements (rtx x, rtx y)
{
- /* We can't support X being a SUBREG because we might then need to know its
- location if something inside it was replaced. */
- gcc_assert (GET_CODE (x) != SUBREG);
-
copy_replacements_1 (&x, &y, n_replacements);
}
const char *fmt;
for (j = 0; j < orig_replacements; j++)
- {
- if (replacements[j].subreg_loc == px)
- {
- r = &replacements[n_replacements++];
- r->where = replacements[j].where;
- r->subreg_loc = py;
- r->what = replacements[j].what;
- r->mode = replacements[j].mode;
- }
- else if (replacements[j].where == px)
- {
- r = &replacements[n_replacements++];
- r->where = py;
- r->subreg_loc = 0;
- r->what = replacements[j].what;
- r->mode = replacements[j].mode;
- }
- }
+ if (replacements[j].where == px)
+ {
+ r = &replacements[n_replacements++];
+ r->where = py;
+ r->what = replacements[j].what;
+ r->mode = replacements[j].mode;
+ }
x = *px;
y = *py;
int i;
for (i = 0; i < n_replacements; i++)
- if (replacements[i].subreg_loc == x)
- replacements[i].subreg_loc = y;
- else if (replacements[i].where == x)
- {
- replacements[i].where = y;
- replacements[i].subreg_loc = 0;
- }
+ if (replacements[i].where == x)
+ replacements[i].where = y;
}
\f
/* If LOC was scheduled to be replaced by something, return the replacement.
if (reloadreg && r->where == loc)
{
if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
- reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
return reloadreg;
}
- else if (reloadreg && r->subreg_loc == loc)
+ else if (reloadreg && GET_CODE (*loc) == SUBREG
+ && r->where == &SUBREG_REG (*loc))
{
- /* RELOADREG must be either a REG or a SUBREG.
-
- ??? Is it actually still ever a SUBREG? If so, why? */
-
- if (REG_P (reloadreg))
- return gen_rtx_REG (GET_MODE (*loc),
- (REGNO (reloadreg) +
- subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
- GET_MODE (SUBREG_REG (*loc)),
- SUBREG_BYTE (*loc),
- GET_MODE (*loc))));
- else if (GET_MODE (reloadreg) == GET_MODE (*loc))
- return reloadreg;
- else
- {
- int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
-
- /* When working with SUBREGs the rule is that the byte
- offset must be a multiple of the SUBREG's mode. */
- final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
- final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
- return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
- final_offset);
- }
+ if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
+ reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
+
+ return simplify_gen_subreg (GET_MODE (*loc), reloadreg,
+ GET_MODE (SUBREG_REG (*loc)),
+ SUBREG_BYTE (*loc));
}
}
|| num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
return 0;
+ /* Don't reuse register contents from before a setjmp-type
+ function call; on the second return (from the longjmp) it
+ might have been clobbered by a later reuse. It doesn't
+ seem worthwhile to actually go and see if it is actually
+ reused even if that information would be readily available;
+ just don't reuse it across the setjmp call. */
+ if (CALL_P (p) && find_reg_note (p, REG_SETJMP, NULL_RTX))
+ return 0;
+
if (NONJUMP_INSN_P (p)
/* If we don't want spill regs ... */
&& (! (reload_reg_p != 0
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
if ((GET_CODE (elt) == CLOBBER
- || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
+ || (sets == 1 && GET_CODE (elt) == SET))
&& REG_P (XEXP (elt, 0)))
{
unsigned int test = REGNO (XEXP (elt, 0));
regno = REGNO (reloadreg);
- if (WORDS_BIG_ENDIAN)
+ if (REG_WORDS_BIG_ENDIAN)
regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
- (int) hard_regno_nregs[regno][mode];