/* 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;
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]);
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;
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;
}
#endif
|| operand == stack_pointer_rtx)
&& ! maybe_memory_address_p (mode, ad,
- &XEXP (XEXP (ad, 0), op_index)))
+ &XEXP (XEXP (ad, 0), 1 - op_index)))
{
rtx offset_reg;
rtx addend;
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));
+
+ /* A register that is incremented cannot be constant! */
+ gcc_assert (regno < FIRST_PSEUDO_REGISTER
+ || reg_equiv_constant[regno] == 0);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
+ /* 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);
- /* We require a base register here... */
- if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ 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