/* Search an insn for pseudo regs that must be in hard regs and are not.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "rtl.h"
+#include "rtl-error.h"
#include "tm_p.h"
#include "insn-config.h"
#include "expr.h"
#include "optabs.h"
#include "recog.h"
+#include "df.h"
#include "reload.h"
#include "regs.h"
#include "addresses.h"
#include "hard-reg-set.h"
#include "flags.h"
-#include "real.h"
#include "output.h"
#include "function.h"
-#include "toplev.h"
#include "params.h"
#include "target.h"
-#include "df.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. */
-#define SMALL_REGISTER_CLASS_P(C) \
- (reg_class_size [(C)] == 1 \
- || (reg_class_size [(C)] >= 1 && CLASS_LIKELY_SPILLED_P (C)))
+
+static inline bool
+small_register_class_p (reg_class_t rclass)
+{
+ return (reg_class_size [(int) rclass] == 1
+ || (reg_class_size [(int) rclass] >= 1
+ && targetm.class_likely_spilled_p (rclass)));
+}
\f
/* All reloads of the current insn are recorded here. See reload.h for
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);
static int find_reusable_reload (rtx *, rtx, enum reg_class,
enum reload_type, int, int);
static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode,
- enum machine_mode, enum reg_class, int, int);
+ enum machine_mode, reg_class_t, int, int);
static int hard_reg_set_here_p (unsigned int, unsigned int, rtx);
static struct decomposition decompose (rtx);
static int immune_p (rtx, rtx, struct decomposition);
static rtx subst_reg_equivs (rtx, rtx);
static rtx subst_indexed_address (rtx);
static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, rtx, int,
+static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
enum rtx_code, enum rtx_code, rtx *,
int, enum reload_type,int, rtx);
static void find_reloads_address_part (rtx, rtx *, enum reg_class,
enum machine_mode, int,
enum reload_type, int);
static rtx find_reloads_subreg_address (rtx, int, int, enum reload_type,
- int, rtx);
+ int, rtx, int *);
static void copy_replacements_1 (rtx *, rtx *, int);
static int find_inc_amount (rtx, rtx);
static int refers_to_mem_for_reload_p (rtx);
{
rtx it;
- for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+ for (it = reg_equiv_alt_mem_list (regno); it; it = XEXP (it, 1))
if (rtx_equal_p (XEXP (it, 0), mem))
return;
- reg_equiv_alt_mem_list [regno]
+ reg_equiv_alt_mem_list (regno)
= alloc_EXPR_LIST (REG_EQUIV, mem,
- reg_equiv_alt_mem_list [regno]);
+ reg_equiv_alt_mem_list (regno));
}
\f
/* Determine if any secondary reloads are needed for loading (if IN_P is
/* 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);
might be sensitive to the form of the MEM. */
if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_mem[REGNO (x)] != 0)
- x = reg_equiv_mem[REGNO (x)];
+ && reg_equiv_mem (REGNO (x)))
+ x = reg_equiv_mem (REGNO (x));
sri.icode = CODE_FOR_nothing;
sri.prev_sri = prev_sri;
- rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+ rclass = (enum reg_class) targetm.secondary_reload (in_p, x, reload_class,
+ reload_mode, &sri);
icode = (enum insn_code) sri.icode;
/* If we don't need any secondary registers, done. */
|| (! in_p && rld[s_reload].secondary_out_reload == t_reload))
&& ((in_p && rld[s_reload].secondary_in_icode == t_icode)
|| (! in_p && rld[s_reload].secondary_out_icode == t_icode))
- && (SMALL_REGISTER_CLASS_P (rclass)
+ && (small_register_class_p (rclass)
|| targetm.small_register_classes_for_mode_p (VOIDmode))
&& MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
opnum, rld[s_reload].opnum))
/* If a secondary reload is needed, return its class. If both an intermediate
register and a scratch register is needed, we return the class of the
intermediate register. */
-enum reg_class
-secondary_reload_class (bool in_p, enum reg_class rclass,
- enum machine_mode mode, rtx x)
+reg_class_t
+secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode,
+ rtx x)
{
enum insn_code icode;
secondary_reload_info sri;
sri.icode = CODE_FOR_nothing;
sri.prev_sri = NULL;
- rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
+ rclass
+ = (enum reg_class) targetm.secondary_reload (in_p, x, rclass, mode, &sri);
icode = (enum insn_code) sri.icode;
/* If there are no secondary reloads at all, we return NO_REGS.
if (bad || !good)
continue;
- cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class);
+ cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
if ((reg_class_size[rclass] > best_size
&& (best_cost < 0 || best_cost >= cost))
{
best_class = (enum reg_class) rclass;
best_size = reg_class_size[rclass];
- best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass,
+ best_cost = register_move_cost (outer, (enum reg_class) rclass,
dest_class);
}
}
|| (out != 0 && MATCHES (rld[i].out, out)
&& (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (SMALL_REGISTER_CLASS_P (rclass)
+ && (small_register_class_p (rclass)
|| targetm.small_register_classes_for_mode_p (VOIDmode))
&& MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
return i;
&& GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
&& MATCHES (XEXP (in, 0), rld[i].in)))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (SMALL_REGISTER_CLASS_P (rclass)
+ && (small_register_class_p (rclass)
|| targetm.small_register_classes_for_mode_p (VOIDmode))
&& MERGABLE_RELOADS (type, rld[i].when_needed,
opnum, rld[i].opnum))
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;
gcc_assert (regno < FIRST_PSEUDO_REGISTER
|| reg_renumber[regno] >= 0
- || reg_equiv_constant[regno] == NULL_RTX);
+ || reg_equiv_constant (regno) == NULL_RTX);
}
/* reg_equiv_constant only contains constants which are obviously
gcc_assert (regno < FIRST_PSEUDO_REGISTER
|| reg_renumber[regno] >= 0
- || reg_equiv_constant[regno] == NULL_RTX);
+ || reg_equiv_constant (regno) == NULL_RTX);
}
/* If we have a read-write operand with an address side-effect,
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. */
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
{
- enum reg_class preferred_class = rclass;
+ reg_class_t preferred_class = rclass;
if (in != 0)
- preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
+ preferred_class = targetm.preferred_reload_class (in, rclass);
- /* Output reloads may need analogous treatment, different in detail. */
-#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+ /* Output reloads may need analogous treatment, different in detail. */
if (out != 0)
- preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
-#endif
+ preferred_class
+ = targetm.preferred_output_reload_class (out, preferred_class);
/* Discard what the target said if we cannot do it. */
if (preferred_class != NO_REGS
|| (optional && type == RELOAD_FOR_OUTPUT))
- rclass = preferred_class;
+ rclass = (enum reg_class) preferred_class;
}
/* Make sure we use a class that can handle the actual pseudo
{
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
static rtx
find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
enum machine_mode inmode, enum machine_mode outmode,
- enum reg_class rclass, int for_real, int earlyclobber)
+ reg_class_t rclass, int for_real, int earlyclobber)
{
rtx in = real_in;
rtx out = real_out;
/* Narrow down the reg class, the same way push_reload will;
otherwise we might find a dummy now, but push_reload won't. */
{
- enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
+ reg_class_t preferred_class = targetm.preferred_reload_class (in, rclass);
if (preferred_class != NO_REGS)
- rclass = preferred_class;
+ rclass = (enum reg_class) preferred_class;
}
/* See if OUT will do. */
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;
enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
int no_input_reloads = 0, no_output_reloads = 0;
int n_alternatives;
- enum reg_class this_alternative[MAX_RECOG_OPERANDS];
+ reg_class_t this_alternative[MAX_RECOG_OPERANDS];
char this_alternative_match_win[MAX_RECOG_OPERANDS];
char this_alternative_win[MAX_RECOG_OPERANDS];
char this_alternative_offmemok[MAX_RECOG_OPERANDS];
char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
int this_alternative_matches[MAX_RECOG_OPERANDS];
int swapped;
- int goal_alternative[MAX_RECOG_OPERANDS];
+ reg_class_t goal_alternative[MAX_RECOG_OPERANDS];
int this_alternative_number;
int goal_alternative_number = 0;
int operand_reloadnum[MAX_RECOG_OPERANDS];
char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
int goal_alternative_swapped;
int best;
- int best_small_class_operands_num;
int commutative;
char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
rtx substed_operand[MAX_RECOG_OPERANDS];
&& REGNO (SET_DEST (body)) < FIRST_PSEUDO_REGISTER
&& REG_P (SET_SRC (body))
&& REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
- && REGISTER_MOVE_COST (GET_MODE (SET_SRC (body)),
+ && register_move_cost (GET_MODE (SET_SRC (body)),
REGNO_REG_CLASS (REGNO (SET_SRC (body))),
REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
return 0;
/* 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)
{
&& REG_P (reg)
&& (GET_MODE_SIZE (GET_MODE (reg))
>= GET_MODE_SIZE (GET_MODE (op)))
- && reg_equiv_constant[REGNO (reg)] == 0)
+ && reg_equiv_constant (REGNO (reg)) == 0)
set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
insn),
- REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]);
+ REG_EQUAL, reg_equiv_memory_loc (REGNO (reg)));
substed_operand[i] = recog_data.operand[i] = op;
}
that we don't try to replace it in the insn in which it
is being set. */
int regno = REGNO (recog_data.operand[i]);
- if (reg_equiv_constant[regno] != 0
+ if (reg_equiv_constant (regno) != 0
&& (set == 0 || &SET_DEST (set) != recog_data.operand_loc[i]))
{
/* Record the existing mode so that the check if constants are
operand_mode[i] = GET_MODE (recog_data.operand[i]);
substed_operand[i] = recog_data.operand[i]
- = reg_equiv_constant[regno];
+ = reg_equiv_constant (regno);
}
- if (reg_equiv_memory_loc[regno] != 0
- && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+ if (reg_equiv_memory_loc (regno) != 0
+ && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
/* We need not give a valid is_set_dest argument since the case
of a constant equivalence was checked above. */
substed_operand[i] = recog_data.operand[i]
all the operands together against the register constraints. */
best = MAX_RECOG_OPERANDS * 2 + 600;
- best_small_class_operands_num = 0;
swapped = 0;
goal_alternative_swapped = 0;
case 'p':
/* All necessary reloads for an address_operand
were handled in find_reloads_address. */
- this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
- SCRATCH);
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
win = 1;
badop = 0;
break;
&& 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;
to override the handling of reg_equiv_address. */
&& !(REG_P (XEXP (operand, 0))
&& (ind_levels == 0
- || reg_equiv_address[REGNO (XEXP (operand, 0))] != 0)))
+ || reg_equiv_address (REGNO (XEXP (operand, 0))) != 0)))
win = 1;
break;
loading it into a register; hence it will be
offsettable, but we cannot say that reg_equiv_mem
is offsettable without checking. */
- && ((reg_equiv_mem[REGNO (operand)] != 0
- && offsettable_memref_p (reg_equiv_mem[REGNO (operand)]))
- || (reg_equiv_address[REGNO (operand)] != 0))))
+ && ((reg_equiv_mem (REGNO (operand)) != 0
+ && 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;
else if (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
- && ((reg_equiv_mem[REGNO (operand)] != 0
- && EXTRA_CONSTRAINT_STR (reg_equiv_mem[REGNO (operand)], c, p))
- || (reg_equiv_address[REGNO (operand)] != 0)))
+ && ((reg_equiv_mem (REGNO (operand)) != 0
+ && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
+ || (reg_equiv_address (REGNO (operand)) != 0)))
win = 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;
/* If we didn't already win, we can reload
the address into a base register. */
- this_alternative[i] = base_reg_class (VOIDmode,
- ADDRESS,
- SCRATCH);
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
badop = 0;
break;
}
/* If this operand could be handled with a reg,
and some reg is allowed, then this operand can be handled. */
- if (winreg && this_alternative[i] != NO_REGS)
+ if (winreg && this_alternative[i] != NO_REGS
+ && (win || !class_only_fixed_regs[this_alternative[i]]))
badop = 0;
/* Record which operands fit this alternative. */
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)
- && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
+ 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)
if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
{
- if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
+ if (targetm.preferred_reload_class (operand, this_alternative[i])
== NO_REGS)
reject = 600;
-#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
if (operand_type[i] == RELOAD_FOR_OUTPUT
- && (PREFERRED_OUTPUT_RELOAD_CLASS (operand,
- this_alternative[i])
+ && (targetm.preferred_output_reload_class (operand,
+ this_alternative[i])
== NO_REGS))
reject = 600;
-#endif
}
/* We prefer to reload pseudos over reloading other things,
&& this_alternative[i] != NO_REGS
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& reg_class_size [(int) preferred_class[i]] > 0
- && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
+ && ! small_register_class_p (preferred_class[i]))
{
if (! reg_class_subset_p (this_alternative[i],
preferred_class[i]))
{
/* If the output is in a non-empty few-regs class,
it's costly to reload it, so reload the input instead. */
- if (SMALL_REGISTER_CLASS_P (this_alternative[i])
+ if (small_register_class_p (this_alternative[i])
&& (REG_P (recog_data.operand[j])
|| GET_CODE (recog_data.operand[j]) == SUBREG))
{
record it as the chosen goal for reloading. */
if (! bad)
{
- bool change_p = false;
- int small_class_operands_num = 0;
-
- if (best >= losers)
- {
- for (i = 0; i < noperands; i++)
- small_class_operands_num
- += SMALL_REGISTER_CLASS_P (this_alternative[i]) ? 1 : 0;
- if (best > losers
- || (best == losers
- /* If the cost of the reloads is the same,
- prefer alternative which requires minimal
- number of small register classes for the
- operands. This improves chances of reloads
- for insn requiring small register
- classes. */
- && (small_class_operands_num
- < best_small_class_operands_num)))
- change_p = true;
- }
- if (change_p)
+ if (best > losers)
{
for (i = 0; i < noperands; i++)
{
}
goal_alternative_swapped = swapped;
best = losers;
- best_small_class_operands_num = small_class_operands_num;
goal_alternative_number = this_alternative_number;
goal_earlyclobber = this_earlyclobber;
}
op = XEXP (op, 1);
}
- if (CONST_POOL_OK_P (op)
- && ((PREFERRED_RELOAD_CLASS (op,
- (enum reg_class) goal_alternative[i])
+ 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);
/* If the address to be reloaded is a VOIDmode constant,
use the default address mode as mode of the reload register,
as would have been done by find_reloads_address. */
+ addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
enum machine_mode address_mode;
address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
if (address_mode == VOIDmode)
- {
- addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
- address_mode = targetm.addr_space.address_mode (as);
- }
+ address_mode = targetm.addr_space.address_mode (as);
operand_reloadnum[i]
= push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
&XEXP (recog_data.operand[i], 0), (rtx*) 0,
- base_reg_class (VOIDmode, MEM, SCRATCH),
+ base_reg_class (VOIDmode, as, MEM, SCRATCH),
address_mode,
VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
rld[operand_reloadnum[i]].inc
/* If this is only for an output, the optional reload would not
actually cause us to use a register now, just note that
something is stored here. */
- && ((enum reg_class) goal_alternative[i] != NO_REGS
+ && (goal_alternative[i] != NO_REGS
|| modified[i] == RELOAD_WRITE)
&& ! no_input_reloads
/* An optional output reload might allow to delete INSN later.
if ((MEM_P (operand)
|| (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
- && ((enum reg_class) goal_alternative[goal_alternative_matches[i]]
- != NO_REGS))
+ && (goal_alternative[goal_alternative_matches[i]] != NO_REGS))
operand_reloadnum[i] = operand_reloadnum[goal_alternative_matches[i]]
= push_reload (recog_data.operand[goal_alternative_matches[i]],
recog_data.operand[i],
&& (!JUMP_P (insn)
|| !label_is_jump_target_p (XEXP (substitution, 0),
insn)))
- add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
+ {
+ add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
+ if (LABEL_P (XEXP (substitution, 0)))
+ ++LABEL_NUSES (XEXP (substitution, 0));
+ }
+
}
else
retval |= (substed_operand[i] != *recog_data.operand_loc[i]);
> 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'.
{
/* This code is duplicated for speed in find_reloads. */
int regno = REGNO (x);
- if (reg_equiv_constant[regno] != 0 && !is_set_dest)
- x = reg_equiv_constant[regno];
+ if (reg_equiv_constant (regno) != 0 && !is_set_dest)
+ x = reg_equiv_constant (regno);
#if 0
/* This creates (subreg (mem...)) which would cause an unnecessary
reload of the mem. */
- else if (reg_equiv_mem[regno] != 0)
- x = reg_equiv_mem[regno];
+ else if (reg_equiv_mem (regno) != 0)
+ x = reg_equiv_mem (regno);
#endif
- else if (reg_equiv_memory_loc[regno]
- && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+ else if (reg_equiv_memory_loc (regno)
+ && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
{
rtx mem = make_memloc (x, regno);
- if (reg_equiv_address[regno]
- || ! rtx_equal_p (mem, reg_equiv_mem[regno]))
+ if (reg_equiv_address (regno)
+ || ! rtx_equal_p (mem, reg_equiv_mem (regno)))
{
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
if (regno >= FIRST_PSEUDO_REGISTER
&& reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0)
+ && reg_equiv_constant (regno) != 0)
{
tem =
- simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
+ 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);
+ insn, address_reloaded);
}
for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
/* We must rerun eliminate_regs, in case the elimination
offsets have changed. */
rtx tem
- = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX),
+ = XEXP (eliminate_regs (reg_equiv_memory_loc (regno), VOIDmode, NULL_RTX),
0);
/* If TEM might contain a pseudo, we must copy it to avoid
if (rtx_varies_p (tem, 0))
tem = copy_rtx (tem);
- tem = replace_equiv_address_nv (reg_equiv_memory_loc[regno], tem);
+ tem = replace_equiv_address_nv (reg_equiv_memory_loc (regno), tem);
tem = adjust_address_nv (tem, GET_MODE (ad), 0);
/* Copy the result if it's still the same as the equivalence, to avoid
modifying it when we do the substitution for the reload. */
- if (tem == reg_equiv_memory_loc[regno])
+ if (tem == reg_equiv_memory_loc (regno))
tem = copy_rtx (tem);
return tem;
}
{
regno = REGNO (ad);
- if (reg_equiv_constant[regno] != 0)
+ if (reg_equiv_constant (regno) != 0)
{
- find_reloads_address_part (reg_equiv_constant[regno], loc,
- base_reg_class (mode, MEM, SCRATCH),
+ find_reloads_address_part (reg_equiv_constant (regno), loc,
+ base_reg_class (mode, as, MEM, SCRATCH),
GET_MODE (ad), opnum, type, ind_levels);
return 1;
}
- tem = reg_equiv_memory_loc[regno];
+ tem = reg_equiv_memory_loc (regno);
if (tem != 0)
{
- if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
+ if (reg_equiv_address (regno) != 0 || num_not_at_initial_offset)
{
tem = make_memloc (ad, regno);
if (! strict_memory_address_addr_space_p (GET_MODE (tem),
in the final reload pass. */
if (replace_reloads
&& num_not_at_initial_offset
- && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ && ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
*loc = tem;
/* We mark the USE with QImode so that we
subject of a CLOBBER in this insn. */
else if (regno < FIRST_PSEUDO_REGISTER
- && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
+ && regno_ok_for_base_p (regno, mode, as, MEM, SCRATCH)
&& ! regno_clobbered_p (regno, this_insn, mode, 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
+ push_reload (ad, NULL_RTX, loc, (rtx*) 0,
+ base_reg_class (mode, as, MEM, SCRATCH),
GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (GET_CODE (ad) == PLUS
&& CONST_INT_P (XEXP (ad, 1))
&& REG_P (XEXP (ad, 0))
- && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
+ && reg_equiv_constant (REGNO (XEXP (ad, 0))) == 0)
return 0;
subst_reg_equivs_changed = 0;
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
push_reload (tem, NULL_RTX, loc, (rtx*) 0,
- base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
+ base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem),
VOIDmode, 0,
0, opnum, type);
return ! removed_and;
&& REG_P (XEXP (ad, 0))
&& REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
&& CONST_INT_P (XEXP (ad, 1))
- && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
- CONST_INT))
+ && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS,
+ CONST_INT)
+ /* Similarly, if we were to reload the base register and the
+ mem+offset address is still invalid, then we want to reload
+ the whole address, not just the base register. */
+ || ! maybe_memory_address_addr_space_p
+ (mode, ad, as, &(XEXP (ad, 0)))))
{
/* Unshare the MEM rtx so we can safely alter it. */
loc = &XEXP (*loc, 0);
}
- if (double_reg_address_ok)
+ if (double_reg_address_ok
+ && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as,
+ PLUS, CONST_INT))
{
/* Unshare the sum as well. */
*loc = ad = copy_rtx (ad);
reload the sum into a base reg.
That will at least work. */
find_reloads_address_part (ad, loc,
- base_reg_class (mode, MEM, SCRATCH),
+ base_reg_class (mode, as, MEM, SCRATCH),
GET_MODE (ad), opnum, type, ind_levels);
}
return ! removed_and;
addend = XEXP (XEXP (ad, 0), 1 - op_index);
- if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
+ if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code,
GET_CODE (addend))
|| operand == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| operand == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
op_index == 0 ? addend : offset_reg);
*loc = ad;
- cls = base_reg_class (mode, MEM, GET_CODE (addend));
+ cls = base_reg_class (mode, as, MEM, GET_CODE (addend));
find_reloads_address_part (XEXP (ad, op_index),
&XEXP (ad, op_index), cls,
GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode,
+ find_reloads_address_1 (mode, as,
XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
GET_CODE (XEXP (ad, op_index)),
&XEXP (ad, 1 - op_index), opnum,
loc = &XEXP (*loc, 0);
}
- find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
+ find_reloads_address_part (ad, loc,
+ base_reg_class (mode, as, MEM, SCRATCH),
address_mode, opnum, type, ind_levels);
return ! removed_and;
}
- return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
- ind_levels, insn);
+ return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc,
+ opnum, type, ind_levels, insn);
}
\f
/* Find all pseudo regs appearing in AD
{
int regno = REGNO (ad);
- if (reg_equiv_constant[regno] != 0)
+ if (reg_equiv_constant (regno) != 0)
{
subst_reg_equivs_changed = 1;
- return reg_equiv_constant[regno];
+ return reg_equiv_constant (regno);
}
- if (reg_equiv_memory_loc[regno] && num_not_at_initial_offset)
+ if (reg_equiv_memory_loc (regno) && num_not_at_initial_offset)
{
rtx mem = make_memloc (ad, regno);
- if (! rtx_equal_p (mem, reg_equiv_mem[regno]))
+ if (! rtx_equal_p (mem, reg_equiv_mem (regno)))
{
subst_reg_equivs_changed = 1;
/* We mark the USE with QImode so that we recognize it
if (REG_P (op0)
&& (regno = REGNO (op0)) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0)
- op0 = reg_equiv_constant[regno];
+ && reg_equiv_constant (regno) != 0)
+ op0 = reg_equiv_constant (regno);
else if (REG_P (op1)
&& (regno = REGNO (op1)) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0)
- op1 = reg_equiv_constant[regno];
+ && reg_equiv_constant (regno) != 0)
+ op1 = reg_equiv_constant (regno);
else if (GET_CODE (op0) == PLUS
&& (tem = subst_indexed_address (op0)) != op0)
op0 = tem;
handles those cases gracefully. */
static int
-find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
+find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
+ rtx x, int context,
enum rtx_code outer_code, enum rtx_code index_code,
rtx *loc, int opnum, enum reload_type type,
int ind_levels, rtx insn)
{
-#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX) \
((CONTEXT) == 0 \
- ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \
+ ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX) \
: REGNO_OK_FOR_INDEX_P (REGNO))
enum reg_class context_reg_class;
if (context == 1)
context_reg_class = INDEX_REG_CLASS;
else
- context_reg_class = base_reg_class (mode, outer_code, index_code);
+ context_reg_class = base_reg_class (mode, as, outer_code, index_code);
switch (code)
{
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
- find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
}
else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
|| code1 == ZERO_EXTEND || code0 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
- find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
}
else if (code0 == CONST_INT || code0 == CONST
|| code0 == SYMBOL_REF || code0 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
else if (code1 == CONST_INT || code1 == CONST
|| code1 == SYMBOL_REF || code1 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
else if (code0 == REG && code1 == REG)
{
if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
- && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+ && regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
return 0;
else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
- && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+ && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
return 0;
- else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
- find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
+ find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
- find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
- else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
- find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
+ find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
- find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
else
{
- find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
- find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
}
else if (code0 == REG)
{
- find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
- find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
}
else if (code1 == REG)
{
- find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
&XEXP (x, 1), opnum, type, ind_levels,
insn);
- find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
&XEXP (x, 0), opnum, type, ind_levels,
insn);
}
if ((REG_P (XEXP (op1, 1))
&& !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
|| GET_CODE (XEXP (op1, 1)) == PLUS)
- find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
+ find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH,
&XEXP (op1, 1), opnum, RELOAD_OTHER,
ind_levels, insn);
/* A register that is incremented cannot be constant! */
gcc_assert (regno < FIRST_PSEUDO_REGISTER
- || reg_equiv_constant[regno] == 0);
+ || reg_equiv_constant (regno) == 0);
/* Handle a register that is equivalent to a memory location
which cannot be addressed directly. */
- if (reg_equiv_memory_loc[regno] != 0
- && (reg_equiv_address[regno] != 0
+ if (reg_equiv_memory_loc (regno) != 0
+ && (reg_equiv_address (regno) != 0
|| num_not_at_initial_offset))
{
rtx tem = make_memloc (XEXP (x, 0), regno);
- if (reg_equiv_address[regno]
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ if (reg_equiv_address (regno)
+ || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
rtx orig = tem;
register. */
reloadnum = push_reload (tem, tem, &XEXP (x, 0),
&XEXP (op1, 0),
- base_reg_class (mode, code,
- index_code),
+ base_reg_class (mode, as,
+ code, index_code),
GET_MODE (x), GET_MODE (x), 0,
0, opnum, RELOAD_OTHER);
regno = reg_renumber[regno];
/* We require a base register here... */
- if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
+ if (!regno_ok_for_base_p (regno, GET_MODE (x), as, code, index_code))
{
reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
&XEXP (op1, 0), &XEXP (x, 0),
- base_reg_class (mode, code, index_code),
+ base_reg_class (mode, as,
+ code, index_code),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
/* A register that is incremented cannot be constant! */
gcc_assert (regno < FIRST_PSEUDO_REGISTER
- || reg_equiv_constant[regno] == 0);
+ || reg_equiv_constant (regno) == 0);
/* Handle a register that is equivalent to a memory location
which cannot be addressed directly. */
- if (reg_equiv_memory_loc[regno] != 0
- && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+ if (reg_equiv_memory_loc (regno) != 0
+ && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
{
rtx tem = make_memloc (XEXP (x, 0), regno);
- if (reg_equiv_address[regno]
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ if (reg_equiv_address (regno)
+ || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
rtx orig = tem;
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
if (regno >= FIRST_PSEUDO_REGISTER
- || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code,
index_code))
{
int reloadnum;
Also don't do this if we can probably update x directly. */
rtx equiv = (MEM_P (XEXP (x, 0))
? XEXP (x, 0)
- : reg_equiv_mem[regno]);
- int icode
- = (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
+ : reg_equiv_mem (regno));
+ enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
if (insn && NONJUMP_INSN_P (insn) && equiv
&& memory_operand (equiv, GET_MODE (equiv))
#ifdef HAVE_cc0
&& ! sets_cc0_p (PATTERN (insn))
#endif
&& ! (icode != CODE_FOR_nothing
- && ((*insn_data[icode].operand[0].predicate)
- (equiv, GET_MODE (x)))
- && ((*insn_data[icode].operand[1].predicate)
- (equiv, GET_MODE (x)))))
+ && insn_operand_matches (icode, 0, equiv)
+ && insn_operand_matches (icode, 1, equiv)))
{
/* We use the original pseudo for loc, so that
emit_reload_insns() knows which pseudo this
reloaded. Targets that are better off reloading just either part
(or perhaps even a different part of an outer expression), should
define LEGITIMIZE_RELOAD_ADDRESS. */
- find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+ find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0),
context, code, SCRATCH, &XEXP (x, 0), opnum,
type, ind_levels, insn);
push_reload (x, NULL_RTX, loc, (rtx*) 0,
{
int regno = REGNO (x);
- if (reg_equiv_constant[regno] != 0)
+ if (reg_equiv_constant (regno) != 0)
{
- find_reloads_address_part (reg_equiv_constant[regno], loc,
+ find_reloads_address_part (reg_equiv_constant (regno), loc,
context_reg_class,
GET_MODE (x), opnum, type, ind_levels);
return 1;
#if 0 /* This might screw code in reload1.c to delete prior output-reload
that feeds this insn. */
- if (reg_equiv_mem[regno] != 0)
+ if (reg_equiv_mem (regno) != 0)
{
- push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
+ push_reload (reg_equiv_mem (regno), NULL_RTX, loc, (rtx*) 0,
context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
#endif
- if (reg_equiv_memory_loc[regno]
- && (reg_equiv_address[regno] != 0 || num_not_at_initial_offset))
+ if (reg_equiv_memory_loc (regno)
+ && (reg_equiv_address (regno) != 0 || num_not_at_initial_offset))
{
rtx tem = make_memloc (x, regno);
- if (reg_equiv_address[regno] != 0
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ if (reg_equiv_address (regno) != 0
+ || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
x = tem;
find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
regno = reg_renumber[regno];
if (regno >= FIRST_PSEUDO_REGISTER
- || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
{
int regno ATTRIBUTE_UNUSED = subreg_regno (x);
- if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
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),
- ind_levels, insn);
+ ind_levels, insn, NULL);
push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
if (fmt[i] == 'e')
/* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
we get here. */
- find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
- &XEXP (x, i), opnum, type, ind_levels, insn);
+ find_reloads_address_1 (mode, as, XEXP (x, i), context,
+ code, SCRATCH, &XEXP (x, i),
+ opnum, type, ind_levels, insn);
}
}
enum reload_type type, int ind_levels)
{
if (CONSTANT_P (x)
- && (! LEGITIMATE_CONSTANT_P (x)
- || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS))
+ && (!targetm.legitimate_constant_p (mode, x)
+ || targetm.preferred_reload_class (x, rclass) == NO_REGS))
{
x = force_const_mem (mode, x);
find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
else if (GET_CODE (x) == PLUS
&& CONSTANT_P (XEXP (x, 1))
- && (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
- || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS))
+ && (!targetm.legitimate_constant_p (GET_MODE (x), XEXP (x, 1))
+ || targetm.preferred_reload_class (XEXP (x, 1), rclass)
+ == NO_REGS))
{
rtx tem;
static rtx
find_reloads_subreg_address (rtx x, int force_replace, int opnum,
- enum reload_type type, int ind_levels, rtx insn)
+ enum reload_type type, int ind_levels, rtx insn,
+ int *address_reloaded)
{
int regno = REGNO (SUBREG_REG (x));
+ int reloaded = 0;
- if (reg_equiv_memory_loc[regno])
+ if (reg_equiv_memory_loc (regno))
{
/* If the address is not directly addressable, or if the address is not
offsettable, then it must be replaced. */
if (! force_replace
- && (reg_equiv_address[regno]
- || ! offsettable_memref_p (reg_equiv_mem[regno])))
+ && (reg_equiv_address (regno)
+ || ! offsettable_memref_p (reg_equiv_mem (regno))))
force_replace = 1;
if (force_replace || num_not_at_initial_offset)
/* If the address changes because of register elimination, then
it must be replaced. */
if (force_replace
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ || ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
rtx orig = tem;
- int reloaded;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
hold the correct (negative) byte offset. */
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 find_reloads_address already completed replaced
the address, there is nothing further to do. */
if (reloaded == 0
- && reg_equiv_mem[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])))
- push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
- base_reg_class (GET_MODE (tem), MEM, SCRATCH),
- GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
- opnum, type);
-
+ (GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
+ MEM_ADDR_SPACE (reg_equiv_mem (regno))))
+ {
+ push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
+ base_reg_class (GET_MODE (tem),
+ MEM_ADDR_SPACE (tem),
+ MEM, SCRATCH),
+ GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
+ opnum, type);
+ reloaded = 1;
+ }
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
that delete_output_reload can see it. */
}
}
}
+ if (reloaded && address_reloaded)
+ *address_reloaded = 1;
+
return x;
}
\f
for (check_regno = 0; check_regno < max_regno; check_regno++)
{
#define CHECK_MODF(ARRAY) \
- gcc_assert (!ARRAY[check_regno] \
+ gcc_assert (!VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY \
|| !loc_mentioned_in_p (r->where, \
- ARRAY[check_regno]))
+ VEC_index (reg_equivs_t, reg_equivs, check_regno).ARRAY))
- CHECK_MODF (reg_equiv_constant);
- CHECK_MODF (reg_equiv_memory_loc);
- CHECK_MODF (reg_equiv_address);
- CHECK_MODF (reg_equiv_mem);
+ CHECK_MODF (equiv_constant);
+ CHECK_MODF (equiv_memory_loc);
+ CHECK_MODF (equiv_address);
+ CHECK_MODF (equiv_mem);
#undef CHECK_MODF
}
#endif /* DEBUG_RELOAD */
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));
}
}
X must therefore either be a constant or be in memory. */
if (r >= FIRST_PSEUDO_REGISTER)
{
- if (reg_equiv_memory_loc[r])
+ if (reg_equiv_memory_loc (r))
return refers_to_regno_for_reload_p (regno, endregno,
- reg_equiv_memory_loc[r],
+ reg_equiv_memory_loc (r),
(rtx*) 0);
- gcc_assert (reg_equiv_constant[r] || reg_equiv_invariant[r]);
+ gcc_assert (reg_equiv_constant (r) || reg_equiv_invariant (r));
return 0;
}
if (regno >= FIRST_PSEUDO_REGISTER)
{
- if (reg_equiv_memory_loc[regno])
+ if (reg_equiv_memory_loc (regno))
return refers_to_mem_for_reload_p (in);
- gcc_assert (reg_equiv_constant[regno]);
+ gcc_assert (reg_equiv_constant (regno));
return 0;
}
if (REG_P (x))
return (REGNO (x) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (x)]);
+ && 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--)
|| 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
&& ! push_operand (dest, GET_MODE (dest)))
return 0;
else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[regno] != 0)
+ && reg_equiv_memory_loc (regno) != 0)
return 0;
else if (need_stable_sp && push_operand (dest, GET_MODE (dest)))
return 0;
&& ! push_operand (dest, GET_MODE (dest)))
return 0;
else if (MEM_P (dest) && regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[regno] != 0)
+ && reg_equiv_memory_loc (regno) != 0)
return 0;
else if (need_stable_sp
&& push_operand (dest, GET_MODE (dest)))
{
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];
/* These functions are used to print the variables set by 'find_reloads' */
-void
+DEBUG_FUNCTION void
debug_reload_to_stream (FILE *f)
{
int r;
}
}
-void
+DEBUG_FUNCTION void
debug_reload (void)
{
debug_reload_to_stream (stderr);