/* 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"
+#include "toplev.h" /* exact_log2 may be used by targets */
/* True if X is a constant that can be forced into the constant pool. */
#define CONST_POOL_OK_P(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
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 find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
int *);
static rtx make_memloc (rtx, int);
-static int maybe_memory_address_p (enum machine_mode, rtx, rtx *);
+static int maybe_memory_address_addr_space_p (enum machine_mode, rtx,
+ addr_space_t, rtx *);
static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
int, enum reload_type, int, rtx);
static rtx subst_reg_equivs (rtx, rtx);
sri.icode = CODE_FOR_nothing;
sri.prev_sri = prev_sri;
- rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
- icode = sri.icode;
+ 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. */
if (rclass == NO_REGS && icode == CODE_FOR_nothing)
|| (! 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_CLASSES)
+ && (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);
- icode = sri.icode;
+ 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 an intermediate register is needed, we return its class. */
didn't give us a new MEM, make a new one if it isn't valid. */
loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
- mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+ mem_valid = strict_memory_address_addr_space_p (mode, XEXP (loc, 0),
+ MEM_ADDR_SPACE (loc));
if (! mem_valid && loc == secondary_memlocs[(int) mode])
loc = copy_rtx (loc);
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_cost > cost)
{
- best_class = rclass;
+ 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);
}
}
and the other is at worst neutral.
(A zero compared against anything is neutral.)
- If SMALL_REGISTER_CLASSES, don't use existing reloads unless they are
- for the same thing since that can cause us to need more reload registers
- than we otherwise would. */
+ For targets with small register classes, don't use existing reloads
+ unless they are for the same thing since that can cause us to need
+ more reload registers than we otherwise would. */
for (i = 0; i < n_reloads; i++)
if ((reg_class_subset_p (rclass, rld[i].rclass)
|| (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_CLASSES)
+ && (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_CLASSES)
+ && (small_register_class_p (rclass)
+ || targetm.small_register_classes_for_mode_p (VOIDmode))
&& MERGABLE_RELOADS (type, rld[i].when_needed,
opnum, rld[i].opnum))
{
/* 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
Returning zero here ought to be safe as we take care in
find_reloads to not process the reloads when instruction was
replaced by USE. */
-
+
return 0;
}
}
|| rtx_equal_p (secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[i].opnum],
secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
#endif
- && (SMALL_REGISTER_CLASSES
+ && (targetm.small_register_classes_for_mode_p (VOIDmode)
? (rld[i].rclass == rld[output_reload].rclass)
: (reg_class_subset_p (rld[i].rclass,
rld[output_reload].rclass)
&& ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
rld[i].when_needed != RELOAD_FOR_INPUT)
&& (reg_class_size[(int) rld[i].rclass]
- || SMALL_REGISTER_CLASSES)
+ || targetm.small_register_classes_for_mode_p (VOIDmode))
/* We will allow making things slightly worse by combining an
input and an output, but no worse than that. */
&& (rld[i].when_needed == RELOAD_FOR_INPUT
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. */
return 0;
}
-/* Return 1 if ADDR is a valid memory address for mode MODE,
- and check that each pseudo reg has the proper kind of
- hard reg. */
+/* Return 1 if ADDR is a valid memory address for mode MODE
+ in address space AS, and check that each pseudo reg has the
+ proper kind of hard reg. */
int
-strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
+strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx addr, addr_space_t as)
{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+ gcc_assert (ADDR_SPACE_GENERIC_P (as));
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
win:
return 1;
+#else
+ return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
+#endif
}
\f
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
if (GET_MODE (x) != GET_MODE (y))
return 0;
+ /* MEMs refering to different address space are not equivalent. */
+ if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
+ return 0;
+
switch (code)
{
case CONST_INT:
{
rtx base = NULL_RTX, offset = 0;
rtx addr = XEXP (x, 0);
-
+
if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
|| GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
{
val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
return val;
}
-
+
if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
{
if (GET_CODE (XEXP (addr, 1)) == PLUS
return val;
}
}
-
+
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
offset = XEXP (addr, 1);
}
}
-
+
if (offset == 0)
{
base = addr;
offset = XEXP (offset, 0);
if (GET_CODE (offset) == PLUS)
{
- if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+ if (CONST_INT_P (XEXP (offset, 0)))
{
base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
offset = XEXP (offset, 0);
}
- else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+ else if (CONST_INT_P (XEXP (offset, 1)))
{
base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
offset = XEXP (offset, 1);
offset = const0_rtx;
}
}
- else if (GET_CODE (offset) != CONST_INT)
+ else if (!CONST_INT_P (offset))
{
base = gen_rtx_PLUS (GET_MODE (base), base, offset);
offset = const0_rtx;
}
-
+
if (all_const && GET_CODE (base) == PLUS)
base = gen_rtx_CONST (GET_MODE (base), base);
-
- gcc_assert (GET_CODE (offset) == CONST_INT);
-
+
+ gcc_assert (CONST_INT_P (offset));
+
val.start = INTVAL (offset);
val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
val.base = base;
}
break;
-
+
case REG:
val.reg_flag = 1;
val.start = true_regnum (x);
a register. */
enum reg_class preferred_class[MAX_RECOG_OPERANDS];
char pref_or_nothing[MAX_RECOG_OPERANDS];
- /* Nonzero for a MEM operand whose entire address needs a reload.
+ /* Nonzero for a MEM operand whose entire address needs a reload.
May be -1 to indicate the entire address may or may not need a reload. */
int address_reloaded[MAX_RECOG_OPERANDS];
/* Nonzero for an address operand that needs to be completely reloaded.
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];
&& 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;
break;
case 's':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
|| (GET_CODE (operand) == CONST_DOUBLE
&& GET_MODE (operand) == VOIDmode))
break;
break;
case 'n':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
|| (GET_CODE (operand) == CONST_DOUBLE
&& GET_MODE (operand) == VOIDmode))
win = 1;
case 'N':
case 'O':
case 'P':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
win = 1;
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. */
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])
+ && ((targetm.preferred_reload_class (operand,
+ this_alternative[i])
== NO_REGS)
|| no_input_reloads)
&& operand_mode[i] != VOIDmode)
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]))
|| modified[j] != RELOAD_WRITE)
&& j != i
/* Ignore things like match_operator operands. */
- && *recog_data.constraints[j] != 0
+ && !recog_data.is_operator[j]
/* Don't count an input operand that is constrained to match
the early clobber operand. */
&& ! (this_alternative_matches[j] == 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))
{
/* If this alternative can be made to work by reloading,
and it needs less reloading than the others checked so far,
record it as the chosen goal for reloading. */
- if (! bad && best > losers)
+ if (! bad)
{
- for (i = 0; i < noperands; i++)
+ if (best > losers)
{
- goal_alternative[i] = this_alternative[i];
- goal_alternative_win[i] = this_alternative_win[i];
- goal_alternative_match_win[i] = this_alternative_match_win[i];
- goal_alternative_offmemok[i] = this_alternative_offmemok[i];
- goal_alternative_matches[i] = this_alternative_matches[i];
- goal_alternative_earlyclobber[i]
- = this_alternative_earlyclobber[i];
+ for (i = 0; i < noperands; i++)
+ {
+ goal_alternative[i] = this_alternative[i];
+ goal_alternative_win[i] = this_alternative_win[i];
+ goal_alternative_match_win[i]
+ = this_alternative_match_win[i];
+ goal_alternative_offmemok[i]
+ = this_alternative_offmemok[i];
+ goal_alternative_matches[i] = this_alternative_matches[i];
+ goal_alternative_earlyclobber[i]
+ = this_alternative_earlyclobber[i];
+ }
+ goal_alternative_swapped = swapped;
+ best = losers;
+ goal_alternative_number = this_alternative_number;
+ goal_earlyclobber = this_earlyclobber;
}
- goal_alternative_swapped = swapped;
- best = losers;
- goal_alternative_number = this_alternative_number;
- goal_earlyclobber = this_earlyclobber;
}
}
}
if (CONST_POOL_OK_P (op)
- && ((PREFERRED_RELOAD_CLASS (op,
- (enum reg_class) goal_alternative[i])
+ && ((targetm.preferred_reload_class (op, goal_alternative[i])
== NO_REGS)
|| no_input_reloads)
&& mode != VOIDmode)
&& MEM_P (recog_data.operand[i]))
{
/* If the address to be reloaded is a VOIDmode constant,
- use Pmode as mode of the reload register, as would have
- been done by find_reloads_address. */
+ use the default address mode as mode of the reload register,
+ as would have been done by find_reloads_address. */
enum machine_mode address_mode;
address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
if (address_mode == VOIDmode)
- address_mode = Pmode;
+ {
+ addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
+ address_mode = targetm.addr_space.address_mode (as);
+ }
operand_reloadnum[i]
= push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
/* 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],
/* If we detected error and replaced asm instruction by USE, forget about the
reloads. */
if (GET_CODE (PATTERN (insn)) == USE
- && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+ && CONST_INT_P (XEXP (PATTERN (insn), 0)))
n_reloads = 0;
/* Perhaps an output reload can be combined with another
is null. */
static bool
-alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+ const char *constraint, int altnum)
{
int c;
#endif
&& (reg_equiv_address[regno] != 0
|| (reg_equiv_mem[regno] != 0
- && (! strict_memory_address_p (GET_MODE (x),
- XEXP (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,
}
/* Returns true if AD could be turned into a valid memory reference
- to mode MODE by reloading the part pointed to by PART into a
- register. */
+ to mode MODE in address space AS by reloading the part pointed to
+ by PART into a register. */
static int
-maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
+maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
+ addr_space_t as, rtx *part)
{
int retv;
rtx tem = *part;
rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
*part = reg;
- retv = memory_address_p (mode, ad);
+ retv = memory_address_addr_space_p (mode, ad, as);
*part = tem;
return retv;
rtx *loc, int opnum, enum reload_type type,
int ind_levels, rtx insn)
{
+ addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc)
+ : ADDR_SPACE_GENERIC;
int regno;
int removed_and = 0;
int op_index;
if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
{
tem = make_memloc (ad, regno);
- if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
+ if (! strict_memory_address_addr_space_p (GET_MODE (tem),
+ XEXP (tem, 0),
+ MEM_ADDR_SPACE (tem)))
{
rtx orig = tem;
address: only reg or reg+constant. */
if (ind_levels > 0
- && strict_memory_address_p (mode, tem)
+ && strict_memory_address_addr_space_p (mode, tem, as)
&& (REG_P (XEXP (tem, 0))
|| (GET_CODE (XEXP (tem, 0)) == PLUS
&& REG_P (XEXP (XEXP (tem, 0), 0))
return 1;
}
- if (strict_memory_address_p (mode, ad))
+ if (strict_memory_address_addr_space_p (mode, ad, as))
{
/* The address appears valid, so reloads are not needed.
But the address may contain an eliminable register.
/* But first quickly dispose of a common case. */
if (GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (ad, 1))
&& REG_P (XEXP (ad, 0))
&& reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
return 0;
return 0;
/* Check result for validity after substitution. */
- if (strict_memory_address_p (mode, ad))
+ if (strict_memory_address_addr_space_p (mode, ad, as))
return 0;
}
#ifdef LEGITIMIZE_RELOAD_ADDRESS
do
{
- if (memrefloc)
+ if (memrefloc && ADDR_SPACE_GENERIC_P (as))
{
LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
ind_levels, win);
|| ! (REG_P (XEXP (tem, 0))
|| (GET_CODE (XEXP (tem, 0)) == PLUS
&& REG_P (XEXP (XEXP (tem, 0), 0))
- && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
+ && CONST_INT_P (XEXP (XEXP (tem, 0), 1)))))
{
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
else if (GET_CODE (ad) == PLUS
&& REG_P (XEXP (ad, 0))
&& REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (ad, 1))
&& regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
CONST_INT))
That will at least work. */
find_reloads_address_part (ad, loc,
base_reg_class (mode, MEM, SCRATCH),
- Pmode, opnum, type, ind_levels);
+ GET_MODE (ad), opnum, type, ind_levels);
}
return ! removed_and;
}
continue;
inner_code = GET_CODE (XEXP (ad, 0));
- if (!(GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ if (!(GET_CODE (ad) == PLUS
+ && CONST_INT_P (XEXP (ad, 1))
&& (inner_code == PLUS || inner_code == LO_SUM)))
continue;
if ((regno_ok_for_base_p (REGNO (operand), mode, 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
|| operand == arg_pointer_rtx
#endif
|| operand == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad,
- &XEXP (XEXP (ad, 0), 1 - op_index)))
+ && ! maybe_memory_address_addr_space_p
+ (mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
{
rtx offset_reg;
enum reg_class cls;
/* Form the adjusted address. */
if (GET_CODE (XEXP (ad, 0)) == PLUS)
- ad = gen_rtx_PLUS (GET_MODE (ad),
- op_index == 0 ? offset_reg : addend,
+ ad = gen_rtx_PLUS (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
op_index == 0 ? addend : offset_reg);
else
- ad = gen_rtx_LO_SUM (GET_MODE (ad),
- op_index == 0 ? offset_reg : addend,
+ ad = gen_rtx_LO_SUM (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
op_index == 0 ? addend : offset_reg);
*loc = ad;
cls = base_reg_class (mode, MEM, GET_CODE (addend));
- find_reloads_address_part (XEXP (ad, op_index),
+ 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,
tem = ad;
if (GET_CODE (ad) == PLUS)
tem = subst_indexed_address (ad);
- if (tem != ad && strict_memory_address_p (mode, tem))
+ if (tem != ad && strict_memory_address_addr_space_p (mode, tem, as))
{
/* Ok, we win that way. Replace any additional eliminable
registers. */
/* Make sure that didn't make the address invalid again. */
- if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem))
+ if (! subst_reg_equivs_changed
+ || strict_memory_address_addr_space_p (mode, tem, as))
{
*loc = tem;
return 0;
/* If constants aren't valid addresses, reload the constant address
into a register. */
- if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
+ if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
{
+ enum machine_mode address_mode = GET_MODE (ad);
+ if (address_mode == VOIDmode)
+ address_mode = targetm.addr_space.address_mode (as);
+
/* If AD is an address in the constant pool, the MEM rtx may be shared.
Unshare it so we can safely alter it. */
if (memrefloc && GET_CODE (ad) == SYMBOL_REF
}
find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
- Pmode, opnum, type, ind_levels);
+ address_mode, opnum, type, ind_levels);
return ! removed_and;
}
case PLUS:
/* Quickly dispose of a common case. */
if (XEXP (ad, 0) == frame_pointer_rtx
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (ad, 1)))
return ad;
break;
This routine assumes both inputs are already in canonical form. */
rtx
-form_sum (rtx x, rtx y)
+form_sum (enum machine_mode mode, rtx x, rtx y)
{
rtx tem;
- enum machine_mode mode = GET_MODE (x);
- if (mode == VOIDmode)
- mode = GET_MODE (y);
+ gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
+ gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode);
- if (mode == VOIDmode)
- mode = Pmode;
-
- if (GET_CODE (x) == CONST_INT)
+ if (CONST_INT_P (x))
return plus_constant (y, INTVAL (x));
- else if (GET_CODE (y) == CONST_INT)
+ else if (CONST_INT_P (y))
return plus_constant (x, INTVAL (y));
else if (CONSTANT_P (x))
tem = x, x = y, y = tem;
if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
- return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
+ return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y));
/* Note that if the operands of Y are specified in the opposite
order in the recursive calls below, infinite recursion will occur. */
if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
- return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
+ return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1));
/* If both constant, encapsulate sum. Otherwise, just form sum. A
constant will have been placed second. */
/* Compute the sum. */
if (op2 != 0)
- op1 = form_sum (op1, op2);
+ op1 = form_sum (GET_MODE (addr), op1, op2);
if (op1 != 0)
- op0 = form_sum (op0, op1);
+ op0 = form_sum (GET_MODE (addr), op0, op1);
return op0;
}
#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX) \
((CONTEXT) == 0 \
? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX) \
- : REGNO_OK_FOR_INDEX_P (REGNO))
+ : REGNO_OK_FOR_INDEX_P (REGNO))
enum reg_class context_reg_class;
RTX_CODE code = GET_CODE (x);
rtx equiv = (MEM_P (XEXP (x, 0))
? XEXP (x, 0)
: reg_equiv_mem[regno]);
- int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
+ int icode = (int) optab_handler (add_optab, GET_MODE (x));
if (insn && NONJUMP_INSN_P (insn) && equiv
&& memory_operand (equiv, GET_MODE (equiv))
#ifdef HAVE_cc0
#endif
&& ! (icode != CODE_FOR_nothing
&& ((*insn_data[icode].operand[0].predicate)
- (equiv, Pmode))
+ (equiv, GET_MODE (x)))
&& ((*insn_data[icode].operand[1].predicate)
- (equiv, Pmode))))
+ (equiv, GET_MODE (x)))))
{
/* We use the original pseudo for loc, so that
emit_reload_insns() knows which pseudo this
if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
> reg_class_size[rclass])
{
- x = find_reloads_subreg_address (x, 0, opnum,
+ x = find_reloads_subreg_address (x, 0, opnum,
ADDR_TYPE (type),
ind_levels, insn);
push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
{
if (CONSTANT_P (x)
&& (! LEGITIMATE_CONSTANT_P (x)
- || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS))
+ || 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.preferred_reload_class (XEXP (x, 1), rclass)
+ == NO_REGS))
{
rtx tem;
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 this was a paradoxical subreg that we replaced, the
resulting memory must be sufficiently aligned to allow
base = XEXP (tem, 0);
if (GET_CODE (base) == PLUS)
{
- if (GET_CODE (XEXP (base, 1)) == CONST_INT
+ if (CONST_INT_P (XEXP (base, 1))
&& INTVAL (XEXP (base, 1)) % outer_size != 0)
return x;
base = XEXP (base, 0);
/* For some processors an address may be valid in the
original mode but not in a smaller mode. For
example, ARM accepts a scaled index register in
- SImode but not in HImode. Similarly, the address may
- have been valid before the subreg offset was added,
- but not afterwards. find_reloads_address
- assumes that we pass it a valid address, and doesn't
- force a reload. This will probably be fine if
- find_reloads_address finds some reloads. But if it
- doesn't find any, then we may have just converted a
- valid address into an invalid one. Check for that
- here. */
+ SImode but not in HImode. Note that this is only
+ a problem if the address in reg_equiv_mem is already
+ invalid in the new mode; other cases would be fixed
+ by find_reloads_address as usual.
+
+ ??? We attempt to handle such cases here by doing an
+ additional reload of the full address after the
+ usual processing by find_reloads_address. Note that
+ this may not work in the general case, but it seems
+ to cover the cases where this situation currently
+ occurs. A more general fix might be to reload the
+ *value* instead of the address, but this would not
+ be expected by the callers of this routine as-is.
+
+ If find_reloads_address already completed replaced
+ the address, there is nothing further to do. */
if (reloaded == 0
- && !strict_memory_address_p (GET_MODE (tem),
- XEXP (tem, 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,
/* If either argument is a constant, then modifying X can not affect IN. */
if (CONSTANT_P (x) || CONSTANT_P (in))
return 0;
- else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
+ else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
return refers_to_mem_for_reload_p (in);
else if (GET_CODE (x) == SUBREG)
{
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|| GET_CODE (x) == CC0)
return reg_mentioned_p (x, in);
- else
+ else
{
gcc_assert (GET_CODE (x) == PLUS);
while (1)
{
p = PREV_INSN (p);
+ if (p && DEBUG_INSN_P (p))
+ continue;
num++;
if (p == 0 || LABEL_P (p)
|| num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
|| (REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
- && GET_CODE (goal) == CONST_INT
+ && CONST_INT_P (goal)
&& 0 != (goaltry
= operand_subword (XEXP (tem, 0), 0, 0,
VOIDmode))
&& REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
- && GET_CODE (goal) == CONST_INT
+ && CONST_INT_P (goal)
&& 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
VOIDmode))
&& rtx_equal_p (goal, goaltry)
&& GET_CODE (XEXP (addr, 1)) == PLUS
&& XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
&& XEXP (addr, 0) == inced
- && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (XEXP (addr, 1), 1)))
{
i = INTVAL (XEXP (XEXP (addr, 1), 1));
return i < 0 ? -i : i;
REG_INC note in insn INSN. REGNO must refer to a hard register. */
#ifdef AUTO_INC_DEC
-static int
+static int
reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
rtx insn)
{
if (! INSN_P (insn))
return 0;
-
+
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_INC)
{
unsigned int test = (int) REGNO (XEXP (link, 0));
if (test >= regno && test < endregno)
- return 1;
+ return 1;
}
return 0;
}
#define reg_inc_found_and_valid_p(regno,endregno,insn) 0
-#endif
+#endif
/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
If SETS is 1, also consider SETs. If SETS is 2, enable checking
}
if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
- return 1;
-
+ return 1;
+
if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
int i = XVECLEN (PATTERN (insn), 0) - 1;
}
if (sets == 2
&& reg_inc_found_and_valid_p (regno, endregno, elt))
- return 1;
+ return 1;
}
}
/* 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);