/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This file contains subroutines used only from the file reload1.c.
It knows how to scan one insn for operands and values
#include "params.h"
#include "target.h"
-#ifndef REGNO_MODE_OK_FOR_BASE_P
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
-#endif
-
-#ifndef REG_MODE_OK_FOR_BASE_P
-#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
-#endif
-
/* True if X is a constant that can be forced into the constant pool. */
#define CONST_POOL_OK_P(X) \
(CONSTANT_P (X) \
&& GET_CODE (X) != HIGH \
&& !targetm.cannot_force_const_mem (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)))
+
\f
/* All reloads of the current insn are recorded here. See reload.h for
comments. */
enum machine_mode, enum reload_type,
enum insn_code *);
#endif
-static enum reg_class find_valid_class (enum machine_mode, int, unsigned int);
+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 *);
int, rtx);
static void copy_replacements_1 (rtx *, rtx *, int);
static int find_inc_amount (rtx, rtx);
+static int refers_to_mem_for_reload_p (rtx);
+static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
+ rtx, rtx *);
\f
#ifdef HAVE_SECONDARY_RELOADS
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
insn_constraint));
- if (insn_class == NO_REGS)
- abort ();
- if (in_p
- && insn_data[(int) icode].operand[!in_p].constraint[0] != '=')
- abort ();
+ gcc_assert (insn_class != NO_REGS);
+ gcc_assert (!in_p
+ || insn_data[(int) icode].operand[!in_p].constraint[0]
+ == '=');
}
/* The scratch register's constraint must start with "=&". */
- if (insn_data[(int) icode].operand[2].constraint[0] != '='
- || insn_data[(int) icode].operand[2].constraint[1] != '&')
- abort ();
+ gcc_assert (insn_data[(int) icode].operand[2].constraint[0] == '='
+ && insn_data[(int) icode].operand[2].constraint[1] == '&');
if (reg_class_subset_p (reload_class, insn_class))
mode = insn_data[(int) icode].operand[2].mode;
Allow this when a reload_in/out pattern is being used. I.e. assume
that the generated code handles this case. */
- if (in_p && class == reload_class && icode == CODE_FOR_nothing
- && t_icode == CODE_FOR_nothing)
- abort ();
+ gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
+ || t_icode != CODE_FOR_nothing);
/* If we need a tertiary reload, see if we have one we can reuse or else
make a new one. */
== CODE_FOR_nothing))
|| (! in_p &&(rld[t_reload].secondary_out_icode
== CODE_FOR_nothing)))
- && (reg_class_size[(int) t_class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (t_class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (secondary_type,
rld[t_reload].when_needed,
opnum, rld[t_reload].opnum))
|| (! 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))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
opnum, rld[s_reload].opnum))
{
}
#endif /* SECONDARY_MEMORY_NEEDED */
\f
-/* Find the largest class for which every register number plus N is valid in
- M1 (if in range) and is cheap to move into REGNO.
- Abort if no such class exists. */
+
+/* Find the largest class which has at least one register valid in
+ mode INNER, and which for every such register, that register number
+ plus N is also valid in OUTER (if in range) and is cheap to move
+ into REGNO. Such a class must exist. */
static enum reg_class
-find_valid_class (enum machine_mode m1 ATTRIBUTE_UNUSED, int n,
+find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
+ enum machine_mode inner ATTRIBUTE_UNUSED, int n,
unsigned int dest_regno ATTRIBUTE_UNUSED)
{
int best_cost = -1;
for (class = 1; class < N_REG_CLASSES; class++)
{
int bad = 0;
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)
- if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
- && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
- && ! HARD_REGNO_MODE_OK (regno + n, m1))
- bad = 1;
+ int good = 0;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+ {
+ if (HARD_REGNO_MODE_OK (regno, inner))
+ {
+ good = 1;
+ if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+ || ! HARD_REGNO_MODE_OK (regno + n, outer))
+ bad = 1;
+ }
+ }
- if (bad)
+ if (bad || !good)
continue;
- cost = REGISTER_MOVE_COST (m1, class, dest_class);
+ cost = REGISTER_MOVE_COST (outer, class, dest_class);
if ((reg_class_size[class] > best_size
&& (best_cost < 0 || best_cost >= cost))
{
best_class = class;
best_size = reg_class_size[class];
- best_cost = REGISTER_MOVE_COST (m1, class, dest_class);
+ best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
}
}
- if (best_size == 0)
- abort ();
+ gcc_assert (best_size != 0);
return best_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))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& 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))
- && (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed,
opnum, rld[i].opnum))
{
if (MEM_P (in))
/* This is supposed to happen only for paradoxical subregs made by
combine.c. (SUBREG (MEM)) isn't supposed to occur other ways. */
- if (GET_MODE_SIZE (GET_MODE (in)) > GET_MODE_SIZE (inmode))
- abort ();
+ gcc_assert (GET_MODE_SIZE (GET_MODE (in)) <= GET_MODE_SIZE (inmode));
#endif
inmode = GET_MODE (in);
}
if (REG_P (SUBREG_REG (in)))
in_class
- = find_valid_class (inmode,
+ = find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
subreg_regno_offset (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)),
SUBREG_BYTE (in),
outloc = &SUBREG_REG (out);
out = *outloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
- if (MEM_P (out)
- && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode))
- abort ();
+ gcc_assert (!MEM_P (out)
+ || GET_MODE_SIZE (GET_MODE (out))
+ <= GET_MODE_SIZE (outmode));
#endif
outmode = GET_MODE (out);
}
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
&SUBREG_REG (out),
- find_valid_class (outmode,
+ find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
subreg_regno_offset (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
SUBREG_BYTE (out),
mode = outmode;
if (mode == VOIDmode)
{
- error_for_asm (this_insn, "cannot reload integer constant operand in `asm'");
+ error_for_asm (this_insn, "cannot reload integer constant "
+ "operand in %<asm%>");
mode = word_mode;
if (in != 0)
inmode = word_mode;
}
if (i == FIRST_PSEUDO_REGISTER)
{
- error_for_asm (this_insn, "impossible register constraint in `asm'");
+ error_for_asm (this_insn, "impossible register constraint "
+ "in %<asm%>");
class = ALL_REGS;
}
}
/* Optional output reloads are always OK even if we have no register class,
since the function of these reloads is only to have spill_reg_store etc.
set, so that the storing insn can be deleted later. */
- if (class == NO_REGS
- && (optional == 0 || type != RELOAD_FOR_OUTPUT))
- abort ();
+ gcc_assert (class != NO_REGS
+ || (optional != 0 && type == RELOAD_FOR_OUTPUT));
i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
/* If we did not find a nonzero amount-to-increment-by,
that contradicts the belief that IN is being incremented
in an address in this insn. */
- if (rld[i].inc == 0)
- abort ();
+ gcc_assert (rld[i].inc != 0);
}
#endif
But if there is no spilling in this block, that is OK.
An explicitly used hard reg cannot be a spill reg. */
- if (rld[i].reg_rtx == 0 && in != 0)
+ if (rld[i].reg_rtx == 0 && in != 0 && hard_regs_live_known)
{
rtx note;
int regno;
&& REG_P (XEXP (note, 0))
&& (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
&& reg_mentioned_p (XEXP (note, 0), in)
+ /* Check that we don't use a hardreg for an uninitialized
+ pseudo. See also find_dummy_reload(). */
+ && (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
+ || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+ ORIGINAL_REGNO (XEXP (note, 0))))
&& ! refers_to_regno_for_reload_p (regno,
(regno
+ hard_regno_nregs[regno]
is a subreg, and in that case, out
has a real mode. */
(GET_MODE (out) != VOIDmode
- ? GET_MODE (out) : outmode)))
+ ? GET_MODE (out) : outmode))
+ /* But only do all this if we can be sure, that this input
+ operand doesn't correspond with an uninitialized pseudoreg.
+ global can assign some hardreg to it, which is the same as
+ a different pseudo also currently live (as it can ignore the
+ conflict). So we never must introduce writes to such hardregs,
+ as they would clobber the other live pseudo using the same.
+ See also PR20973. */
+ && (ORIGINAL_REGNO (in) < FIRST_PSEUDO_REGISTER
+ || ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
+ ORIGINAL_REGNO (in))))
{
unsigned int regno = REGNO (in) + in_offset;
unsigned int nwords = hard_regno_nregs[regno][inmode];
j = REGNO (y);
/* On a WORDS_BIG_ENDIAN machine, point to the last register of a
- multiple hard register group, so that for example (reg:DI 0) and
- (reg:SI 1) will be considered the same register. */
+ 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
+ && 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
+ && SCALAR_INT_MODE_P (GET_MODE (y))
&& j < FIRST_PSEUDO_REGISTER)
j += hard_regno_nregs[j][GET_MODE (y)] - 1;
slow:
- /* Now we have disposed of all the cases
- in which different rtx codes can match. */
+ /* Now we have disposed of all the cases in which different rtx codes
+ can match. */
if (code != GET_CODE (y))
return 0;
- if (code == LABEL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- if (code == SYMBOL_REF)
- return XSTR (x, 0) == XSTR (y, 0);
/* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
-
if (GET_MODE (x) != GET_MODE (y))
return 0;
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return 0;
+
+ case LABEL_REF:
+ return XEXP (x, 0) == XEXP (y, 0);
+ case SYMBOL_REF:
+ return XSTR (x, 0) == XSTR (y, 0);
+
+ default:
+ break;
+ }
+
/* Compare the elements. If any pair of corresponding elements
fail to match, return 0 for the whole things. */
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1 + success_2;
memset (&val, 0, sizeof (val));
- if (MEM_P (x))
- {
- 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.base = XEXP (addr, 0);
- val.start = -GET_MODE_SIZE (GET_MODE (x));
- val.end = GET_MODE_SIZE (GET_MODE (x));
- 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
- && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
- && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
- {
- val.base = XEXP (addr, 0);
- val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
- val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
- val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
- return val;
- }
- }
-
- if (GET_CODE (addr) == CONST)
- {
- addr = XEXP (addr, 0);
- all_const = 1;
- }
- if (GET_CODE (addr) == PLUS)
- {
- if (CONSTANT_P (XEXP (addr, 0)))
- {
- base = XEXP (addr, 1);
- offset = XEXP (addr, 0);
- }
- else if (CONSTANT_P (XEXP (addr, 1)))
- {
- base = XEXP (addr, 0);
- offset = XEXP (addr, 1);
- }
- }
-
- if (offset == 0)
- {
- base = addr;
- offset = const0_rtx;
- }
- if (GET_CODE (offset) == CONST)
- offset = XEXP (offset, 0);
- if (GET_CODE (offset) == PLUS)
- {
- if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
- offset = XEXP (offset, 0);
- }
- else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
- offset = XEXP (offset, 1);
- }
- else
- {
- base = gen_rtx_PLUS (GET_MODE (base), base, offset);
- offset = const0_rtx;
- }
- }
- else if (GET_CODE (offset) != CONST_INT)
- {
- 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);
-
- if (GET_CODE (offset) != CONST_INT)
- abort ();
-
- val.start = INTVAL (offset);
- val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
- val.base = base;
- return val;
- }
- else if (REG_P (x))
+ switch (GET_CODE (x))
{
+ case MEM:
+ {
+ 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.base = XEXP (addr, 0);
+ val.start = -GET_MODE_SIZE (GET_MODE (x));
+ val.end = GET_MODE_SIZE (GET_MODE (x));
+ 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
+ && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+ && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+ {
+ val.base = XEXP (addr, 0);
+ val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
+ return val;
+ }
+ }
+
+ if (GET_CODE (addr) == CONST)
+ {
+ addr = XEXP (addr, 0);
+ all_const = 1;
+ }
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (CONSTANT_P (XEXP (addr, 0)))
+ {
+ base = XEXP (addr, 1);
+ offset = XEXP (addr, 0);
+ }
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ {
+ base = XEXP (addr, 0);
+ offset = XEXP (addr, 1);
+ }
+ }
+
+ if (offset == 0)
+ {
+ base = addr;
+ offset = const0_rtx;
+ }
+ if (GET_CODE (offset) == CONST)
+ offset = XEXP (offset, 0);
+ if (GET_CODE (offset) == PLUS)
+ {
+ if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
+ offset = XEXP (offset, 0);
+ }
+ else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
+ offset = XEXP (offset, 1);
+ }
+ else
+ {
+ base = gen_rtx_PLUS (GET_MODE (base), base, offset);
+ offset = const0_rtx;
+ }
+ }
+ else if (GET_CODE (offset) != CONST_INT)
+ {
+ 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);
+
+ 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);
- if (val.start < 0)
+ if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
{
/* A pseudo with no hard reg. */
val.start = REGNO (x);
else
/* A hard reg. */
val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
- }
- else if (GET_CODE (x) == SUBREG)
- {
+ break;
+
+ case SUBREG:
if (!REG_P (SUBREG_REG (x)))
/* This could be more precise, but it's good enough. */
return decompose (SUBREG_REG (x));
val.reg_flag = 1;
val.start = true_regnum (x);
- if (val.start < 0)
+ if (val.start < 0 || val.start >= FIRST_PSEUDO_REGISTER)
return decompose (SUBREG_REG (x));
else
/* A hard reg. */
val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+ break;
+
+ case SCRATCH:
+ /* This hasn't been assigned yet, so it can't conflict yet. */
+ val.safe = 1;
+ break;
+
+ default:
+ gcc_assert (CONSTANT_P (x));
+ val.safe = 1;
+ break;
}
- else if (CONSTANT_P (x)
- /* This hasn't been assigned yet, so it can't conflict yet. */
- || GET_CODE (x) == SCRATCH)
- val.safe = 1;
- else
- abort ();
return val;
}
if (ydata.safe)
return 1;
- if (!MEM_P (y))
- abort ();
+ gcc_assert (MEM_P (y));
/* If Y is memory and X is not, Y can't affect X. */
if (!MEM_P (x))
return 1;
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. */
+ /* Nonzero for an address operand that needs to be completely reloaded.
+ May be -1 to indicate the entire operand may or may not need a reload. */
int address_operand_reloaded[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use for operand. */
enum reload_type operand_type[MAX_RECOG_OPERANDS];
case '%':
{
/* The last operand should not be marked commutative. */
- if (i == noperands - 1)
- abort ();
+ gcc_assert (i != noperands - 1);
/* We currently only support one commutative pair of
operands. Some existing asm code currently uses more
future we may handle it correctly. */
if (commutative < 0)
commutative = i;
- else if (!this_insn_is_asm)
- abort ();
+ else
+ gcc_assert (this_insn_is_asm);
}
break;
/* Use of ISDIGIT is tempting here, but it may get expensive because
recog_data.operand[i]);
/* An operand may not match itself. */
- if (c == i)
- abort ();
+ gcc_assert (c != i);
/* If C can be commuted with C+1, and C might need to match I,
then C+1 might also need to match I. */
{
/* Operands don't match. */
rtx value;
+ int loc1, loc2;
/* Retroactively mark the operand we had to match
as a loser, if it wasn't already. */
if (this_alternative_win[m])
if (this_alternative[m] == (int) NO_REGS)
bad = 1;
/* But count the pair only once in the total badness of
- this alternative, if the pair can be a dummy reload. */
+ this alternative, if the pair can be a dummy reload.
+ The pointers in operand_loc are not swapped; swap
+ them by hand if necessary. */
+ if (swapped && i == commutative)
+ loc1 = commutative + 1;
+ else if (swapped && i == commutative + 1)
+ loc1 = commutative;
+ else
+ loc1 = i;
+ if (swapped && m == commutative)
+ loc2 = commutative + 1;
+ else if (swapped && m == commutative + 1)
+ loc2 = commutative;
+ else
+ loc2 = m;
value
= find_dummy_reload (recog_data.operand[i],
recog_data.operand[m],
- recog_data.operand_loc[i],
- recog_data.operand_loc[m],
+ recog_data.operand_loc[loc1],
+ recog_data.operand_loc[loc2],
operand_mode[i], operand_mode[m],
this_alternative[m], -1,
this_alternative_earlyclobber[m]);
: offsettable_nonstrict_memref_p (operand))
/* A reloaded address is offsettable because it is now
just a simple register indirect. */
- || address_reloaded[i]))
+ || address_reloaded[i] == 1))
|| (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
/* If the address was already reloaded,
we win as well. */
else if (MEM_P (operand)
- && address_reloaded[i])
+ && address_reloaded[i] == 1)
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
if (! win && ! did_match
&& this_alternative[i] != (int) NO_REGS
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && reg_class_size[(int) preferred_class[i]] > 1)
+ && reg_class_size [(int) preferred_class[i]] > 0
+ && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
{
if (! reg_class_subset_p (this_alternative[i],
preferred_class[i]))
early_data = decompose (recog_data.operand[i]);
- if (modified[i] == RELOAD_READ)
- abort ();
+ gcc_assert (modified[i] != RELOAD_READ);
if (this_alternative[i] == NO_REGS)
{
this_alternative_earlyclobber[i] = 0;
- if (this_insn_is_asm)
- error_for_asm (this_insn,
- "`&' constraint used with no register class");
- else
- abort ();
+ gcc_assert (this_insn_is_asm);
+ error_for_asm (this_insn,
+ "%<&%> constraint used with no register class");
}
for (j = 0; j < noperands; j++)
&& !immune_p (recog_data.operand[j], recog_data.operand[i],
early_data))
{
- /* If the output is in a single-reg class,
+ /* If the output is in a non-empty few-regs class,
it's costly to reload it, so reload the input instead. */
- if (reg_class_size[this_alternative[i]] == 1
+ if (SMALL_REGISTER_CLASS_P (this_alternative[i])
&& (REG_P (recog_data.operand[j])
|| GET_CODE (recog_data.operand[j]) == SUBREG))
{
pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
pref_or_nothing[commutative + 1] = t;
+ t = address_reloaded[commutative];
+ address_reloaded[commutative] = address_reloaded[commutative + 1];
+ address_reloaded[commutative + 1] = t;
+
memcpy (constraints, recog_data.constraints,
noperands * sizeof (char *));
goto try_swapped;
/* No alternative works with reloads?? */
if (insn_code_number >= 0)
fatal_insn ("unable to generate reloads for:", insn);
- error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+ error_for_asm (insn, "inconsistent operand constraints in an %<asm%>");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
goal_alternative_win[i] = 1;
}
+ /* Likewise any invalid constants appearing as operand of a PLUS
+ that is to be reloaded. */
+ for (i = 0; i < noperands; i++)
+ if (! goal_alternative_win[i]
+ && GET_CODE (recog_data.operand[i]) == PLUS
+ && CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
+ && (PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
+ (enum reg_class) goal_alternative[i])
+ == NO_REGS)
+ && operand_mode[i] != VOIDmode)
+ {
+ rtx tem = force_const_mem (operand_mode[i],
+ XEXP (recog_data.operand[i], 1));
+ tem = gen_rtx_PLUS (operand_mode[i],
+ XEXP (recog_data.operand[i], 0), tem);
+
+ substed_operand[i] = recog_data.operand[i]
+ = find_reloads_toplev (tem, i, address_type[i],
+ ind_levels, 0, insn, NULL);
+ }
+
/* Record the values of the earlyclobber operands for the caller. */
if (goal_earlyclobber)
for (i = 0; i < noperands; i++)
0, 0, i, RELOAD_OTHER);
operand_reloadnum[i] = output_reloadnum;
}
- else if (insn_code_number >= 0)
- abort ();
else
{
- error_for_asm (insn, "inconsistent operand constraints in an `asm'");
+ gcc_assert (insn_code_number < 0);
+ error_for_asm (insn, "inconsistent operand constraints "
+ "in an %<asm%>");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
n_reloads = 0;
}
else if (goal_alternative_matched[i] < 0
&& goal_alternative_matches[i] < 0
- && !address_operand_reloaded[i]
+ && address_operand_reloaded[i] != 1
&& optimize)
{
/* For each non-matching operand that's a MEM or a pseudo-register
do after the insn (such as for output addresses) are fine. */
if (no_input_reloads)
for (i = 0; i < n_reloads; i++)
- if (rld[i].in != 0
- && rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
- && rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS)
- abort ();
+ gcc_assert (rld[i].in == 0
+ || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
+ || rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
#endif
/* Compute reload_mode and reload_nregs. */
if (code == SUBREG && REG_P (SUBREG_REG (x)))
{
- /* Check for SUBREG containing a REG that's equivalent to a constant.
- If the constant has a known value, truncate it right now.
- Similarly if we are extracting a single-word of a multi-word
- constant. If the constant is symbolic, allow it to be substituted
- normally. push_reload will strip the subreg later. If the
- constant is VOIDmode, abort because we will lose the mode of
- the register (this should never happen because one of the cases
- above should handle it). */
+ /* Check for SUBREG containing a REG that's equivalent to a
+ constant. If the constant has a known value, truncate it
+ right now. Similarly if we are extracting a single-word of a
+ multi-word constant. If the constant is symbolic, allow it
+ to be substituted normally. push_reload will strip the
+ subreg later. The constant must not be VOIDmode, because we
+ will lose the mode of the register (this should never happen
+ because one of the cases above should handle it). */
int regno = REGNO (SUBREG_REG (x));
rtx tem;
tem =
simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
- if (!tem)
- abort ();
+ gcc_assert (tem);
return tem;
}
to determine if we may generate output reloads, and where to put USEs
for pseudos that we have to replace with stack slots.
- Value is nonzero if this address is reloaded or replaced as a whole.
- This is interesting to the caller if the address is an autoincrement.
+ Value is one if this address is reloaded or replaced as a whole; it is
+ zero if the top level of this address was not reloaded or replaced, and
+ it is -1 if it may or may not have been reloaded or replaced.
Note that there is no verification that the address will be valid after
this routine does its work. Instead, we rely on the fact that the address
{
int regno;
int removed_and = 0;
+ int op_index;
rtx tem;
/* If the address is a register, see if it is a legitimate address and
*memrefloc = copy_rtx (*memrefloc);
XEXP (*memrefloc, 0) = ad;
move_replacements (&ad, &XEXP (*memrefloc, 0));
- return 1;
+ return -1;
}
while (0);
#endif
Handle all base registers here, not just fp/ap/sp, because on some
targets (namely SPARC) we can also get invalid addresses from preventive
- subreg big-endian corrections made by find_reloads_toplev.
+ subreg big-endian corrections made by find_reloads_toplev. We
+ can also get expressions involving LO_SUM (rather than PLUS) from
+ find_reloads_subreg_address.
If we decide to do something, it must be that `double_reg_address_ok'
is true. We generate a reload of the base register + constant and
This is safe because we know the address isn't shared.
We check for the base register as both the first and second operand of
- the innermost PLUS. */
-
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && REG_P (XEXP (XEXP (ad, 0), 0))
- && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
- || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
- || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
+ the innermost PLUS and/or LO_SUM. */
+
+ for (op_index = 0; op_index < 2; ++op_index)
{
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- plus_constant (XEXP (XEXP (ad, 0), 0),
- INTVAL (XEXP (ad, 1))),
- XEXP (XEXP (ad, 0), 1));
- find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
- type, 0, insn);
+ rtx operand;
- return 0;
- }
+ if (!(GET_CODE (ad) == PLUS
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && (GET_CODE (XEXP (ad, 0)) == PLUS
+ || GET_CODE (XEXP (ad, 0)) == LO_SUM)))
+ continue;
+
+ operand = XEXP (XEXP (ad, 0), op_index);
+ if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+ continue;
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && REG_P (XEXP (XEXP (ad, 0), 1))
- && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
- || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+ if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
+ || operand == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+ || operand == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+ || operand == arg_pointer_rtx
#endif
- || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
- {
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- XEXP (XEXP (ad, 0), 0),
- plus_constant (XEXP (XEXP (ad, 0), 1),
- INTVAL (XEXP (ad, 1))));
- find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
- type, 0, insn);
+ || operand == stack_pointer_rtx)
+ && ! maybe_memory_address_p (mode, ad,
+ &XEXP (XEXP (ad, 0), 1 - op_index)))
+ {
+ rtx offset_reg;
+ rtx addend;
+
+ offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
+ addend = XEXP (XEXP (ad, 0), 1 - op_index);
+
+ /* Form the adjusted address. */
+ if (GET_CODE (XEXP (ad, 0)) == PLUS)
+ 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,
+ op_index == 0 ? addend : offset_reg);
+ *loc = ad;
+
+ find_reloads_address_part (XEXP (ad, op_index),
+ &XEXP (ad, op_index),
+ MODE_BASE_REG_CLASS (mode),
+ GET_MODE (ad), opnum, type, ind_levels);
+ find_reloads_address_1 (mode,
+ XEXP (ad, 1 - op_index), 1,
+ &XEXP (ad, 1 - op_index), opnum,
+ type, 0, insn);
- return 0;
+ return 0;
+ }
}
/* See if address becomes valid when an eliminable register
is strictly valid.)
CONTEXT = 1 means we are considering regs as index regs,
- = 0 means we are considering them as base regs.
+ = 0 means we are considering them as base regs, = 2 means we
+ are considering them as base regs for REG + REG.
OPNUM and TYPE specify the purpose of any reloads made.
rtx *loc, int opnum, enum reload_type type,
int ind_levels, rtx insn)
{
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE) \
+ ((CONTEXT) == 2 \
+ ? REGNO_MODE_OK_FOR_REG_BASE_P (REGNO, MODE) \
+ : (CONTEXT) == 1 \
+ ? REGNO_OK_FOR_INDEX_P (REGNO) \
+ : REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE))
+
+ enum reg_class context_reg_class;
RTX_CODE code = GET_CODE (x);
+ if (context == 2)
+ context_reg_class = MODE_BASE_REG_REG_CLASS (mode);
+ else if (context == 1)
+ context_reg_class = INDEX_REG_CLASS;
+ else
+ context_reg_class = MODE_BASE_REG_CLASS (mode);
+
switch (code)
{
case PLUS:
register remateralization for expression like &localvar*4. Reload it.
It may be possible to combine the displacement on the outer level,
but it is probably not worthwhile to do so. */
- if (context)
+ if (context == 1)
{
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
else if (code0 == REG && code1 == REG)
{
if (REG_OK_FOR_INDEX_P (op0)
- && REG_MODE_OK_FOR_BASE_P (op1, mode))
+ && REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
return 0;
else if (REG_OK_FOR_INDEX_P (op1)
- && REG_MODE_OK_FOR_BASE_P (op0, mode))
+ && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
return 0;
- else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
+ else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
type, ind_levels, insn);
- else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
+ else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
type, ind_levels, insn);
else if (REG_OK_FOR_INDEX_P (op1))
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
+ find_reloads_address_1 (mode, orig_op0, 2, &XEXP (x, 0), opnum,
type, ind_levels, insn);
else if (REG_OK_FOR_INDEX_P (op0))
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
+ find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), opnum,
type, ind_levels, insn);
else
{
{
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
+ int regno;
+ int reloadnum;
if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
return 0;
where a base register is {inc,dec}remented by the contents
of another register or by a constant value. Thus, these
operands must match. */
- if (op0 != XEXP (op1, 0))
- abort ();
+ gcc_assert (op0 == XEXP (op1, 0));
/* Require index register (or constant). Let's just handle the
register case in the meantime... If the target allows
find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
opnum, type, ind_levels, insn);
- if (REG_P (XEXP (op1, 0)))
- {
- int regno = REGNO (XEXP (op1, 0));
- int reloadnum;
-
- /* A register that is incremented cannot be constant! */
- if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_constant[regno] != 0)
- abort ();
-
- /* 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))
- {
- rtx tem = make_memloc (XEXP (x, 0), regno);
+ gcc_assert (REG_P (XEXP (op1, 0)));
- if (reg_equiv_address[regno]
- || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
- {
- /* First reload the memory location's address.
- We can't use ADDR_TYPE (type) here, because we need to
- write back the value after reading it, hence we actually
- need two registers. */
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum,
- RELOAD_OTHER,
- ind_levels, insn);
-
- /* Then reload the memory location into a base
- register. */
- reloadnum = push_reload (tem, tem, &XEXP (x, 0),
- &XEXP (op1, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (x), GET_MODE (x), 0,
- 0, opnum, RELOAD_OTHER);
-
- update_auto_inc_notes (this_insn, regno, reloadnum);
- return 0;
- }
- }
+ regno = REGNO (XEXP (op1, 0));
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
+ /* A register that is incremented cannot be constant! */
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER
+ || reg_equiv_constant[regno] == 0);
- /* We require a base register here... */
- if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ /* 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))
+ {
+ rtx tem = make_memloc (XEXP (x, 0), regno);
+
+ if (reg_equiv_address[regno]
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
- reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
- &XEXP (op1, 0), &XEXP (x, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (x), GET_MODE (x), 0, 0,
- opnum, RELOAD_OTHER);
+ /* First reload the memory location's address.
+ We can't use ADDR_TYPE (type) here, because we need to
+ write back the value after reading it, hence we actually
+ need two registers. */
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum,
+ RELOAD_OTHER,
+ ind_levels, insn);
+
+ /* Then reload the memory location into a base
+ register. */
+ reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+ &XEXP (op1, 0),
+ MODE_BASE_REG_CLASS (mode),
+ GET_MODE (x), GET_MODE (x), 0,
+ 0, opnum, RELOAD_OTHER);
update_auto_inc_notes (this_insn, regno, reloadnum);
return 0;
}
}
- else
- abort ();
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
+ /* We require a base register here... */
+ if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ {
+ reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+ &XEXP (op1, 0), &XEXP (x, 0),
+ MODE_BASE_REG_CLASS (mode),
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
+
+ update_auto_inc_notes (this_insn, regno, reloadnum);
+ return 0;
+ }
}
return 0;
rtx x_orig = x;
/* A register that is incremented cannot be constant! */
- if (regno >= FIRST_PSEUDO_REGISTER
- && reg_equiv_constant[regno] != 0)
- abort ();
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER
+ || reg_equiv_constant[regno] == 0);
/* Handle a register that is equivalent to a memory location
which cannot be addressed directly. */
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
- if ((regno >= FIRST_PSEUDO_REGISTER
- || !(context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+ if (regno >= FIRST_PSEUDO_REGISTER
+ || !REG_OK_FOR_CONTEXT (context, regno, mode))
{
int reloadnum;
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
}
{
reloadnum
= push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, type);
rld[reloadnum].inc
opnum, type, ind_levels, insn);
reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
rld[reloadnum].inc
= find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
}
return 0;
+ case TRUNCATE:
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ /* Look for parts to reload in the inner expression and reload them
+ too, in addition to this operation. Reloading all inner parts in
+ addition to this one shouldn't be necessary, but at this point,
+ we don't know if we can possibly omit any part that *can* be
+ 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),
+ context, &XEXP (x, 0), opnum,
+ type, ind_levels, insn);
+ push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ context_reg_class,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+
case MEM:
/* This is probably the result of a substitution, by eliminate_regs, of
an equivalent address for a pseudo that was not allocated to a hard
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
if (reg_equiv_constant[regno] != 0)
{
find_reloads_address_part (reg_equiv_constant[regno], loc,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), opnum, type, ind_levels);
return 1;
}
if (reg_equiv_mem[regno] != 0)
{
push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
- if ((regno >= FIRST_PSEUDO_REGISTER
- || !(context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
+ if (regno >= FIRST_PSEUDO_REGISTER
+ || !REG_OK_FOR_CONTEXT (context, regno, mode))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
{
int regno ATTRIBUTE_UNUSED = subreg_regno (x);
- if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
+ if (! REG_OK_FOR_CONTEXT (context, regno, mode))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
- (context ? INDEX_REG_CLASS :
- MODE_BASE_REG_CLASS (mode)),
+ context_reg_class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
is larger than the class size, then reload the whole SUBREG. */
else
{
- enum reg_class class = (context ? INDEX_REG_CLASS
- : MODE_BASE_REG_CLASS (mode));
+ enum reg_class class = context_reg_class;
if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
- x = find_reloads_subreg_address (x, 0, opnum, type,
+ x = find_reloads_subreg_address (x, 0, opnum,
+ ADDR_TYPE (type),
ind_levels, insn);
push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
}
}
+#undef REG_OK_FOR_CONTEXT
return 0;
}
\f
}
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+ &XEXP (tem, 0), opnum, type,
ind_levels, insn);
/* If this is not a toplevel operand, find_reloads doesn't see
for (check_regno = 0; check_regno < max_regno; check_regno++)
{
#define CHECK_MODF(ARRAY) \
- if (ARRAY[check_regno] \
- && loc_mentioned_in_p (r->where, \
- ARRAY[check_regno])) \
- abort ()
+ gcc_assert (!ARRAY[check_regno] \
+ || !loc_mentioned_in_p (r->where, \
+ ARRAY[check_regno]))
CHECK_MODF (reg_equiv_constant);
CHECK_MODF (reg_equiv_memory_loc);
register refers to. */
if (GET_CODE (*r->where) == LABEL_REF
&& JUMP_P (insn))
- REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
- XEXP (*r->where, 0),
- REG_NOTES (insn));
+ {
+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
+ XEXP (*r->where, 0),
+ REG_NOTES (insn));
+ JUMP_LABEL (insn) = XEXP (*r->where, 0);
+ }
/* Encapsulate RELOADREG so its machine mode matches what
used to be there. Note that gen_lowpart_common will
*r->where = reloadreg;
}
/* If reload got no reg and isn't optional, something's wrong. */
- else if (! rld[r->what].optional)
- abort ();
+ else
+ gcc_assert (rld[r->what].optional);
}
}
\f
{
/* We can't support X being a SUBREG because we might then need to know its
location if something inside it was replaced. */
- if (GET_CODE (x) == SUBREG)
- abort ();
+ gcc_assert (GET_CODE (x) != SUBREG);
copy_replacements_1 (&x, &y, n_replacements);
}
This is similar to refers_to_regno_p in rtlanal.c except that we
look at equivalences for pseudos that didn't get hard registers. */
-int
+static int
refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
rtx x, rtx *loc)
{
reg_equiv_memory_loc[r],
(rtx*) 0);
- if (reg_equiv_constant[r])
- return 0;
-
- abort ();
+ gcc_assert (reg_equiv_constant[r]);
+ return 0;
}
return (endregno > r
{
if (reg_equiv_memory_loc[regno])
return refers_to_mem_for_reload_p (in);
- else if (reg_equiv_constant[regno])
- return 0;
- abort ();
+ gcc_assert (reg_equiv_constant[regno]);
+ return 0;
}
}
else if (MEM_P (x))
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|| GET_CODE (x) == CC0)
return reg_mentioned_p (x, in);
- else if (GET_CODE (x) == PLUS)
+ else
{
+ gcc_assert (GET_CODE (x) == PLUS);
+
/* We actually want to know if X is mentioned somewhere inside IN.
We must not say that (plus (sp) (const_int 124)) is in
(plus (sp) (const_int 64)), since that can lead to incorrect reload
else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
}
- else
- abort ();
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
? hard_regno_nregs[regno][GET_MODE (x)] : 1);
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
registers. */
-int
+static int
refers_to_mem_for_reload_p (rtx x)
{
const char *fmt;
different from what they were when calculating the need for
spills. If we notice an input-reload insn here, we will
reject it below, but it might hide a usable equivalent.
- That makes bad code. It may even abort: perhaps no reg was
+ That makes bad code. It may even fail: perhaps no reg was
spilled for this insn because it was assumed we would find
that equivalent. */
|| INSN_UID (p) < reload_first_uid))
if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER)
for (i = 0; i < nregs; ++i)
- if (call_used_regs[regno + i])
+ if (call_used_regs[regno + i]
+ || HARD_REGNO_CALL_PART_CLOBBERED (regno + i, mode))
return 0;
if (valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER)
for (i = 0; i < valuenregs; ++i)
- if (call_used_regs[valueno + i])
+ if (call_used_regs[valueno + i]
+ || HARD_REGNO_CALL_PART_CLOBBERED (valueno + i, mode))
return 0;
-#ifdef NON_SAVING_SETJMP
- if (NON_SAVING_SETJMP && find_reg_note (p, REG_SETJMP, NULL))
- return 0;
-#endif
}
if (INSN_P (p))
rtx dest = SET_DEST (pat);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
rtx dest = SET_DEST (v1);
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
if (REG_P (dest))
}
\f
/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
- If SETS is nonzero, also consider SETs. */
+ If SETS is nonzero, also consider SETs. REGNO must refer to a hard
+ register. */
int
regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
int sets)
{
- unsigned int nregs = hard_regno_nregs[regno][mode];
- unsigned int endregno = regno + nregs;
+ unsigned int nregs, endregno;
+
+ /* regno must be a hard register. */
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER);
+
+ nregs = hard_regno_nregs[regno][mode];
+ endregno = regno + nregs;
if ((GET_CODE (PATTERN (insn)) == CLOBBER
|| (sets && GET_CODE (PATTERN (insn)) == SET))
"RELOAD_FOR_OTHER_ADDRESS"
};
-static const char * const reg_class_names[] = REG_CLASS_NAMES;
-
/* These functions are used to print the variables set by 'find_reloads' */
void