/* 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 Free Software Foundation,
- Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file contains subroutines used only from the file reload1.c.
It knows how to scan one insn for operands and values
#define REG_OK_STRICT
+/* We do not enable this with ENABLE_CHECKING, since it is awfully slow. */
+#undef DEBUG_RELOAD
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "recog.h"
#include "reload.h"
#include "regs.h"
+#include "addresses.h"
#include "hard-reg-set.h"
#include "flags.h"
#include "real.h"
#include "toplev.h"
#include "params.h"
#include "target.h"
+#include "df.h"
/* True if X is a constant that can be forced into the constant pool. */
#define CONST_POOL_OK_P(X) \
static rtx subst_reg_equivs (rtx, rtx);
static rtx subst_indexed_address (rtx);
static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, rtx, int, rtx *,
+static int find_reloads_address_1 (enum machine_mode, rtx, int,
+ enum rtx_code, enum rtx_code, rtx *,
int, enum reload_type,int, rtx);
static void find_reloads_address_part (rtx, rtx *, enum reg_class,
enum machine_mode, int,
static int refers_to_mem_for_reload_p (rtx);
static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
rtx, rtx *);
+
+/* Add NEW to reg_equiv_alt_mem_list[REGNO] if it's not present in the
+ list yet. */
+
+static void
+push_reg_equiv_alt_mem (int regno, rtx mem)
+{
+ rtx it;
+
+ for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+ if (rtx_equal_p (XEXP (it, 0), mem))
+ return;
+
+ reg_equiv_alt_mem_list [regno]
+ = alloc_EXPR_LIST (REG_EQUIV, mem,
+ reg_equiv_alt_mem_list [regno]);
+}
\f
/* Determine if any secondary reloads are needed for loading (if IN_P is
nonzero) or storing (if IN_P is zero) X to or from a reload register of
/* If IN appears in OUT, we can't share any input-only reload for IN. */
if (in != 0 && out != 0 && MEM_P (out)
- && (REG_P (in) || MEM_P (in))
+ && (REG_P (in) || MEM_P (in) || GET_CODE (in) == PLUS)
&& reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
dont_share = 1;
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
- if (in != 0)
- class = PREFERRED_RELOAD_CLASS (in, class);
+ {
+ enum reg_class preferred_class = class;
+
+ if (in != 0)
+ preferred_class = PREFERRED_RELOAD_CLASS (in, class);
/* Output reloads may need analogous treatment, different in detail. */
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
- if (out != 0)
- class = PREFERRED_OUTPUT_RELOAD_CLASS (out, class);
+ if (out != 0)
+ preferred_class = PREFERRED_OUTPUT_RELOAD_CLASS (out, preferred_class);
#endif
+ /* Discard what the target said if we cannot do it. */
+ if (preferred_class != NO_REGS
+ || (optional && type == RELOAD_FOR_OUTPUT))
+ class = preferred_class;
+ }
+
/* Make sure we use a class that can handle the actual pseudo
inside any subreg. For example, on the 386, QImode regs
can appear within SImode subregs. Although GENERAL_REGS
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (HARD_REGNO_MODE_OK (i, mode)
- && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
- {
- int nregs = hard_regno_nregs[i][mode];
-
- int j;
- for (j = 1; j < nregs; j++)
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], i + j))
- break;
- if (j == nregs)
- break;
- }
+ && in_hard_reg_set_p (reg_class_contents[(int) class], mode, i))
+ break;
if (i == FIRST_PSEUDO_REGISTER)
{
error_for_asm (this_insn, "impossible register constraint "
"in %<asm%>");
- class = ALL_REGS;
+ /* Avoid further trouble with this insn. */
+ PATTERN (this_insn) = gen_rtx_USE (VOIDmode, const0_rtx);
+ /* We used to continue here setting class to ALL_REGS, but it triggers
+ sanity check on i386 for:
+ void foo(long double d)
+ {
+ asm("" :: "a" (d));
+ }
+ 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;
}
}
#ifdef SECONDARY_MEMORY_NEEDED
/* If a memory location is needed for the copy, make one. */
- if (in != 0 && (REG_P (in) || GET_CODE (in) == SUBREG)
+ if (in != 0
+ && (REG_P (in)
+ || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
class, inmode))
n_reloads++;
#ifdef SECONDARY_MEMORY_NEEDED
- if (out != 0 && (REG_P (out) || GET_CODE (out) == SUBREG)
+ if (out != 0
+ && (REG_P (out)
+ || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (class,
REGNO_REG_CLASS (reg_or_subregno (out)),
/* 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,
+ || ! bitmap_bit_p (DF_RA_LIVE_OUT (ENTRY_BLOCK_PTR),
ORIGINAL_REGNO (XEXP (note, 0))))
&& ! refers_to_regno_for_reload_p (regno,
- (regno
- + hard_regno_nregs[regno]
- [rel_mode]),
+ end_hard_regno (rel_mode,
+ regno),
PATTERN (this_insn), inloc)
/* If this is also an output reload, IN cannot be used as
the reload register if it is set in this insn unless IN
is also OUT. */
&& (out == 0 || in == out
|| ! hard_reg_set_here_p (regno,
- (regno
- + hard_regno_nregs[regno]
- [rel_mode]),
+ end_hard_regno (rel_mode, regno),
PATTERN (this_insn)))
/* ??? Why is this code so different from the previous?
Is there any simple coherent way to describe the two together?
if (offs == nregs
&& (! (refers_to_regno_for_reload_p
- (regno, (regno + hard_regno_nregs[regno][inmode]),
- in, (rtx *)0))
+ (regno, end_hard_regno (inmode, regno), in, (rtx *) 0))
|| can_reload_into (in, regno, inmode)))
{
rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
return;
/* If there is a reload for part of the address of this operand, we would
- need to chnage it to RELOAD_FOR_OTHER_ADDRESS. But that would extend
+ need to change it to RELOAD_FOR_OTHER_ADDRESS. But that would extend
its life to the point where doing this combine would not lower the
number of spill registers needed. */
for (i = 0; i < n_reloads; i++)
|| ! (TEST_HARD_REG_BIT
(reg_class_contents[(int) rld[secondary_out].class],
REGNO (XEXP (note, 0)))))))
- && ! fixed_regs[REGNO (XEXP (note, 0))])
+ && ! fixed_regs[REGNO (XEXP (note, 0))]
+ /* 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 (DF_LR_OUT (ENTRY_BLOCK_PTR),
+ ORIGINAL_REGNO (XEXP (note, 0)))))
{
rld[output_reload].reg_rtx
= gen_rtx_REG (rld[output_reload].outmode,
/* Narrow down the reg class, the same way push_reload will;
otherwise we might find a dummy now, but push_reload won't. */
- class = PREFERRED_RELOAD_CLASS (in, class);
+ {
+ enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+ if (preferred_class != NO_REGS)
+ class = preferred_class;
+ }
/* See if OUT will do. */
if (REG_P (out)
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,
+ || ! bitmap_bit_p (DF_RA_LIVE_OUT (ENTRY_BLOCK_PTR),
ORIGINAL_REGNO (in))))
{
unsigned int regno = REGNO (in) + in_offset;
/* See if this reg overlaps range under consideration. */
if (r < end_regno
- && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
+ && end_hard_regno (GET_MODE (op0), r) > beg_regno)
return 1;
}
}
{
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_FIXED:
return 0;
case LABEL_REF:
}
else
/* A hard reg. */
- val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+ val.end = end_hard_regno (GET_MODE (x), val.start);
break;
case SUBREG:
return decompose (SUBREG_REG (x));
else
/* A hard reg. */
- val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+ val.end = val.start + subreg_nregs (x);
break;
case SCRATCH:
&& MEM_P (op)
&& REG_P (reg)
&& (GET_MODE_SIZE (GET_MODE (reg))
- >= GET_MODE_SIZE (GET_MODE (op))))
+ >= GET_MODE_SIZE (GET_MODE (op)))
+ && reg_equiv_constant[REGNO (reg)] == 0)
set_unique_reg_note (emit_insn_before (gen_rtx_USE (VOIDmode, reg),
insn),
REG_EQUAL, reg_equiv_memory_loc[REGNO (reg)]);
case 'p':
/* All necessary reloads for an address_operand
were handled in find_reloads_address. */
- this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ this_alternative[i]
+ = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
win = 1;
badop = 0;
break;
break;
case 'X':
+ force_reload = 0;
win = 1;
break;
/* If we didn't already win, we can reload
the address into a base register. */
- this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ this_alternative[i]
+ = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
badop = 0;
break;
}
losers++;
}
- /* If we can't reload this value at all, reject this
- alternative. Note that we could also lose due to
- LIMIT_RELOAD_RELOAD_CLASS, but we don't check that
- here. */
-
- if (! CONSTANT_P (operand)
- && (enum reg_class) this_alternative[i] != NO_REGS
- && (PREFERRED_RELOAD_CLASS (operand,
- (enum reg_class) this_alternative[i])
- == NO_REGS))
- bad = 1;
-
/* Alternative loses if it requires a type of reload not
permitted for this insn. We can always reload SCRATCH
and objects with a REG_UNUSED note. */
- else if (GET_CODE (operand) != SCRATCH
+ if (GET_CODE (operand) != SCRATCH
&& modified[i] != RELOAD_READ && no_output_reloads
&& ! find_reg_note (insn, REG_UNUSED, operand))
bad = 1;
&& ! const_to_mem)
bad = 1;
+ /* If we can't reload this value at all, reject this
+ alternative. Note that we could also lose due to
+ LIMIT_RELOAD_CLASS, but we don't check that
+ here. */
+
+ if (! CONSTANT_P (operand)
+ && (enum reg_class) this_alternative[i] != NO_REGS)
+ {
+ if (PREFERRED_RELOAD_CLASS
+ (operand, (enum reg_class) this_alternative[i])
+ == NO_REGS)
+ reject = 600;
+
+#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
+ if (operand_type[i] == RELOAD_FOR_OUTPUT
+ && PREFERRED_OUTPUT_RELOAD_CLASS
+ (operand, (enum reg_class) this_alternative[i])
+ == NO_REGS)
+ reject = 600;
+#endif
+ }
+
/* We prefer to reload pseudos over reloading other things,
since such reloads may be able to be eliminated later.
If we are reloading a SCRATCH, we won't be generating any
&& goal_alternative_offmemok[i]
&& 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. */
+ enum machine_mode address_mode;
+ address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
+ if (address_mode == VOIDmode)
+ address_mode = Pmode;
+
operand_reloadnum[i]
= push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
&XEXP (recog_data.operand[i], 0), (rtx*) 0,
- MODE_BASE_REG_CLASS (VOIDmode),
- GET_MODE (XEXP (recog_data.operand[i], 0)),
+ base_reg_class (VOIDmode, MEM, SCRATCH),
+ address_mode,
VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
rld[operand_reloadnum[i]].inc
= GET_MODE_SIZE (GET_MODE (recog_data.operand[i]));
*recog_data.operand_loc[i] = substitution;
- /* If we're replacing an operand with a LABEL_REF, we need
- to make sure that there's a REG_LABEL note attached to
+ /* If we're replacing an operand with a LABEL_REF, we need to
+ make sure that there's a REG_LABEL_OPERAND note attached to
this instruction. */
- if (!JUMP_P (insn)
- && GET_CODE (substitution) == LABEL_REF
- && !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
- REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
+ if (GET_CODE (substitution) == LABEL_REF
+ && !find_reg_note (insn, REG_LABEL_OPERAND,
+ XEXP (substitution, 0))
+ /* For a JUMP_P, if it was a branch target it must have
+ already been recorded as such. */
+ && (!JUMP_P (insn)
+ || !label_is_jump_target_p (XEXP (substitution, 0),
+ insn)))
+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND,
XEXP (substitution, 0),
REG_NOTES (insn));
}
}
#endif
+ /* 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)
+ n_reloads = 0;
+
/* Perhaps an output reload can be combined with another
to reduce needs by one. */
if (!goal_earlyclobber)
if (rld[i].when_needed == RELOAD_FOR_INPUT
&& GET_CODE (PATTERN (insn)) == SET
&& REG_P (SET_DEST (PATTERN (insn)))
- && SET_SRC (PATTERN (insn)) == rld[i].in)
+ && SET_SRC (PATTERN (insn)) == rld[i].in
+ && !elimination_target_reg_p (SET_DEST (PATTERN (insn))))
{
rtx dest = SET_DEST (PATTERN (insn));
unsigned int regno = REGNO (dest);
x = mem;
i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels, insn);
+ if (!rtx_equal_p (x, mem))
+ push_reg_equiv_alt_mem (regno, x);
if (address_reloaded)
*address_reloaded = i;
}
int regno = REGNO (SUBREG_REG (x));
rtx tem;
- if (subreg_lowpart_p (x)
- && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0
- && (tem = gen_lowpart_common (GET_MODE (x),
- reg_equiv_constant[regno])) != 0)
- return tem;
-
- if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
+ if (regno >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0)
{
tem =
simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
gcc_assert (tem);
+ if (CONSTANT_P (tem) && !LEGITIMATE_CONSTANT_P (tem))
+ {
+ tem = force_const_mem (GET_MODE (x), tem);
+ i = find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum, type,
+ ind_levels, insn);
+ if (address_reloaded)
+ *address_reloaded = i;
+ }
return tem;
}
a wider mode if we have a paradoxical SUBREG. find_reloads will
force a reload in that case. So we should not do anything here. */
- else if (regno >= FIRST_PSEUDO_REGISTER
+ if (regno >= FIRST_PSEUDO_REGISTER
#ifdef LOAD_EXTEND_OP
&& (GET_MODE_SIZE (GET_MODE (x))
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
+ rtx orig = tem;
+
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
ADDR_TYPE (type), ind_levels, insn);
+ if (!rtx_equal_p (tem, orig))
+ push_reg_equiv_alt_mem (regno, tem);
}
/* We can avoid a reload if the register's equivalent memory
expression is valid as an indirect memory address.
subject of a CLOBBER in this insn. */
else if (regno < FIRST_PSEUDO_REGISTER
- && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
+ && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
&& ! regno_clobbered_p (regno, this_insn, mode, 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, NULL_RTX, loc, (rtx*) 0, MODE_BASE_REG_CLASS (mode),
+ push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
return 1;
}
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
push_reload (tem, NULL_RTX, loc, (rtx*) 0,
- MODE_BASE_REG_CLASS (mode), GET_MODE (tem),
+ base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
VOIDmode, 0,
0, opnum, type);
return ! removed_and;
else if (GET_CODE (ad) == PLUS
&& REG_P (XEXP (ad, 0))
&& REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode)
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
+ CONST_INT))
+
{
/* Unshare the MEM rtx so we can safely alter it. */
if (memrefloc)
/* If the sum of two regs is not necessarily valid,
reload the sum into a base reg.
That will at least work. */
- find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+ find_reloads_address_part (ad, loc,
+ base_reg_class (mode, MEM, SCRATCH),
Pmode, opnum, type, ind_levels);
}
return ! removed_and;
for (op_index = 0; op_index < 2; ++op_index)
{
- rtx operand;
+ rtx operand, addend;
+ enum rtx_code inner_code;
+ if (GET_CODE (ad) != PLUS)
+ continue;
+
+ inner_code = GET_CODE (XEXP (ad, 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)))
+ && (inner_code == PLUS || inner_code == LO_SUM)))
continue;
operand = XEXP (XEXP (ad, 0), op_index);
if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
continue;
- if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
+ addend = XEXP (XEXP (ad, 0), 1 - op_index);
+
+ 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
|| operand == hard_frame_pointer_rtx
&XEXP (XEXP (ad, 0), 1 - op_index)))
{
rtx offset_reg;
- rtx addend;
+ enum reg_class cls;
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 ? addend : offset_reg);
*loc = ad;
+ cls = base_reg_class (mode, MEM, GET_CODE (addend));
find_reloads_address_part (XEXP (ad, op_index),
- &XEXP (ad, op_index),
- MODE_BASE_REG_CLASS (mode),
+ &XEXP (ad, op_index), cls,
GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode,
- XEXP (ad, 1 - op_index), 1,
+ find_reloads_address_1 (mode,
+ XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
+ GET_CODE (XEXP (ad, op_index)),
&XEXP (ad, 1 - op_index), opnum,
type, 0, insn);
loc = &XEXP (*loc, 0);
}
- find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+ find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
Pmode, opnum, type, ind_levels);
return ! removed_and;
}
- return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
- insn);
+ return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
+ ind_levels, insn);
}
\f
/* Find all pseudo regs appearing in AD
case CONST_INT:
case CONST:
case CONST_DOUBLE:
+ case CONST_FIXED:
case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
is strictly valid.)
CONTEXT = 1 means we are considering regs as index regs,
- = 0 means we are considering them as base regs, = 2 means we
- are considering them as base regs for REG + REG.
-
+ = 0 means we are considering them as base regs.
+ OUTER_CODE is the code of the enclosing RTX, typically a MEM, a PLUS,
+ or an autoinc code.
+ If CONTEXT == 0 and OUTER_CODE is a PLUS or LO_SUM, then INDEX_CODE
+ is the code of the index part of the address. Otherwise, pass SCRATCH
+ for this argument.
OPNUM and TYPE specify the purpose of any reloads made.
IND_LEVELS says how many levels of indirect addressing are
static int
find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
+ enum rtx_code outer_code, enum rtx_code index_code,
rtx *loc, int opnum, enum reload_type type,
int ind_levels, rtx insn)
{
-#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE) \
- ((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))
+#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))
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)
+ if (context == 1)
context_reg_class = INDEX_REG_CLASS;
else
- context_reg_class = MODE_BASE_REG_CLASS (mode);
+ context_reg_class = base_reg_class (mode, outer_code, index_code);
switch (code)
{
GET_MODE (orig_op1))));
}
/* Plus in the index register may be created only as a result of
- register remateralization for expression like &localvar*4. Reload it.
+ register rematerialization 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 == 1)
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
|| code1 == ZERO_EXTEND || code0 == MEM)
{
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code0 == CONST_INT || code0 == CONST
|| code0 == SYMBOL_REF || code0 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
else if (code1 == CONST_INT || code1 == CONST
|| code1 == SYMBOL_REF || code1 == LABEL_REF)
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
else if (code0 == REG && code1 == REG)
{
- if (REG_OK_FOR_INDEX_P (op0)
- && REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
+ if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
+ && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
return 0;
- else if (REG_OK_FOR_INDEX_P (op1)
- && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
+ && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
return 0;
- 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_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, 2, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- else if (REG_OK_FOR_INDEX_P (op0))
- find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
else
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
}
else if (code0 == REG)
{
- find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
}
else if (code1 == REG)
{
- find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels, insn);
- find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels, insn);
+ find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+ &XEXP (x, 1), opnum, type, ind_levels,
+ insn);
+ find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+ &XEXP (x, 0), opnum, type, ind_levels,
+ insn);
}
}
{
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
+ enum rtx_code index_code;
int regno;
int reloadnum;
/* Require index register (or constant). Let's just handle the
register case in the meantime... If the target allows
auto-modify by a constant then we could try replacing a pseudo
- register with its equivalent constant where applicable. */
- if (REG_P (XEXP (op1, 1)))
- if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
- find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
- opnum, type, ind_levels, insn);
+ register with its equivalent constant where applicable.
+
+ We also handle the case where the register was eliminated
+ resulting in a PLUS subexpression.
+
+ If we later decide to reload the whole PRE_MODIFY or
+ POST_MODIFY, inc_for_reload might clobber the reload register
+ before reading the index. The index register might therefore
+ need to live longer than a TYPE reload normally would, so be
+ conservative and class it as RELOAD_OTHER. */
+ if ((REG_P (XEXP (op1, 1))
+ && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
+ || GET_CODE (XEXP (op1, 1)) == PLUS)
+ find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
+ &XEXP (op1, 1), opnum, RELOAD_OTHER,
+ ind_levels, insn);
gcc_assert (REG_P (XEXP (op1, 0)));
regno = REGNO (XEXP (op1, 0));
+ index_code = GET_CODE (XEXP (op1, 1));
/* A register that is incremented cannot be constant! */
gcc_assert (regno < FIRST_PSEUDO_REGISTER
if (reg_equiv_address[regno]
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
+ rtx orig = tem;
+
/* 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
RELOAD_OTHER,
ind_levels, insn);
+ if (!rtx_equal_p (tem, orig))
+ push_reg_equiv_alt_mem (regno, tem);
+
/* Then reload the memory location into a base
- register. */
+ 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);
+ &XEXP (op1, 0),
+ base_reg_class (mode, code,
+ index_code),
+ GET_MODE (x), GET_MODE (x), 0,
+ 0, opnum, RELOAD_OTHER);
update_auto_inc_notes (this_insn, regno, reloadnum);
return 0;
regno = reg_renumber[regno];
/* We require a base register here... */
- if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
{
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);
+ &XEXP (op1, 0), &XEXP (x, 0),
+ base_reg_class (mode, code, index_code),
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
update_auto_inc_notes (this_insn, regno, reloadnum);
return 0;
if (reg_equiv_address[regno]
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
+ rtx orig = tem;
+
/* 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
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
ind_levels, insn);
+ if (!rtx_equal_p (tem, orig))
+ push_reg_equiv_alt_mem (regno, tem);
/* Put this inside a new increment-expression. */
x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
/* Proceed to reload that, as if it contained a register. */
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno];
if (regno >= FIRST_PSEUDO_REGISTER
- || !REG_OK_FOR_CONTEXT (context, regno, mode))
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
int reloadnum;
rtx equiv = (MEM_P (XEXP (x, 0))
? XEXP (x, 0)
: reg_equiv_mem[regno]);
- int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
+ int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
if (insn && NONJUMP_INSN_P (insn) && equiv
&& memory_operand (equiv, GET_MODE (equiv))
#ifdef HAVE_cc0
}
return value;
}
-
- else if (MEM_P (XEXP (x, 0)))
- {
- /* 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 register. Verify that the specified address is valid and
- reload it into a register. */
- /* Variable `tem' might or might not be used in FIND_REG_INC_NOTE. */
- rtx tem ATTRIBUTE_UNUSED = XEXP (x, 0);
- rtx link;
- int reloadnum;
-
- /* Since we know we are going to reload this item, don't decrement
- for the indirection level.
-
- Note that this is actually conservative: it would be slightly
- more efficient to use the value of SPILL_INDIRECT_LEVELS from
- reload1.c here. */
- /* 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 (x), &XEXP (x, 0),
- XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
- opnum, type, ind_levels, insn);
-
- reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
- context_reg_class,
- GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- rld[reloadnum].inc
- = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
-
- link = FIND_REG_INC_NOTE (this_insn, tem);
- if (link != 0)
- push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
-
- return 1;
- }
return 0;
case TRUNCATE:
(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,
+ context, code, SCRATCH, &XEXP (x, 0), opnum,
type, ind_levels, insn);
push_reload (x, NULL_RTX, loc, (rtx*) 0,
context_reg_class,
find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
&XEXP (x, 0), opnum, ADDR_TYPE (type),
ind_levels, insn);
+ if (!rtx_equal_p (x, tem))
+ push_reg_equiv_alt_mem (regno, x);
}
}
regno = reg_renumber[regno];
if (regno >= FIRST_PSEUDO_REGISTER
- || !REG_OK_FOR_CONTEXT (context, regno, mode))
+ || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
context_reg_class,
{
int regno ATTRIBUTE_UNUSED = subreg_regno (x);
- if (! REG_OK_FOR_CONTEXT (context, regno, mode))
+ if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+ index_code))
{
push_reload (x, NULL_RTX, loc, (rtx*) 0,
context_reg_class,
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i),
- opnum, type, ind_levels, insn);
+ /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
+ we get here. */
+ find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
+ &XEXP (x, i), opnum, type, ind_levels, insn);
}
}
&& (! LEGITIMATE_CONSTANT_P (x)
|| PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
{
- rtx tem;
-
- tem = x = force_const_mem (mode, x);
- find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
+ x = force_const_mem (mode, x);
+ find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels, 0);
}
tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), tem);
- find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
+ find_reloads_address (mode, &XEXP (x, 1), XEXP (tem, 0), &XEXP (tem, 0),
opnum, type, ind_levels, 0);
}
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
+ rtx orig = tem;
+ enum machine_mode orig_mode = GET_MODE (orig);
+ int reloaded;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
hold the correct (negative) byte offset. */
return x;
}
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, type,
- ind_levels, insn);
+ reloaded = find_reloads_address (GET_MODE (tem), &tem,
+ XEXP (tem, 0), &XEXP (tem, 0),
+ opnum, type, ind_levels, insn);
+ /* ??? Do we need to handle nonzero offsets somehow? */
+ if (!offset && !rtx_equal_p (tem, orig))
+ push_reg_equiv_alt_mem (regno, tem);
+
+ /* 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. 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. */
+ if (reloaded != 1
+ && strict_memory_address_p (orig_mode, XEXP (tem, 0))
+ && !strict_memory_address_p (GET_MODE (tem),
+ XEXP (tem, 0)))
+ push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
+ base_reg_class (GET_MODE (tem), MEM, SCRATCH),
+ GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
+ opnum, type);
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
rtx reloadreg = rld[r->what].reg_rtx;
if (reloadreg)
{
-#ifdef ENABLE_CHECKING
- /* Internal consistency test. Check that we don't modify
+#ifdef DEBUG_RELOAD
+ /* This checking takes a very long time on some platforms
+ causing the gcc.c-torture/compile/limits-fnargs.c test
+ to time out during testing. See PR 31850.
+
+ Internal consistency test. Check that we don't modify
anything in the equivalence arrays. Whenever something from
those arrays needs to be reloaded, it must be unshared before
being substituted into; the equivalence must not be modified.
CHECK_MODF (reg_equiv_mem);
#undef CHECK_MODF
}
-#endif /* ENABLE_CHECKING */
+#endif /* DEBUG_RELOAD */
- /* If we're replacing a LABEL_REF with a register, add a
- REG_LABEL note to indicate to flow which label this
+ /* If we're replacing a LABEL_REF with a register, there must
+ already be an indication (to e.g. flow) which label this
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));
- JUMP_LABEL (insn) = XEXP (*r->where, 0);
- }
+ gcc_assert (GET_CODE (*r->where) != LABEL_REF
+ || !JUMP_P (insn)
+ || find_reg_note (insn,
+ REG_LABEL_OPERAND,
+ XEXP (*r->where, 0))
+ || label_is_jump_target_p (XEXP (*r->where, 0), insn));
/* Encapsulate RELOADREG so its machine mode matches what
used to be there. Note that gen_lowpart_common will
unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
- ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
+ ? subreg_nregs (x) : 1);
return endregno > inner_regno && regno < inner_endregno;
}
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x));
+ endregno = regno + (regno < FIRST_PSEUDO_REGISTER
+ ? subreg_nregs (x) : 1);
+
+ return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
}
else if (REG_P (x))
{
gcc_assert (reg_equiv_constant[regno]);
return 0;
}
+
+ endregno = END_HARD_REGNO (x);
+
+ return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
}
else if (MEM_P (x))
return refers_to_mem_for_reload_p (in);
if (REG_P (in))
return 0;
else if (GET_CODE (in) == PLUS)
- return (reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
+ return (rtx_equal_p (x, in)
+ || reg_overlap_mentioned_for_reload_p (x, XEXP (in, 0))
|| reg_overlap_mentioned_for_reload_p (x, XEXP (in, 1)));
else return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
}
- endregno = regno + (regno < FIRST_PSEUDO_REGISTER
- ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
-
- return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
+ gcc_unreachable ();
}
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
}
else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
continue;
- else
- {
- int i;
-
- for (i = hard_regno_nregs[valueno][mode] - 1; i >= 0; i--)
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
- valueno + i))
- break;
- if (i >= 0)
- continue;
- }
+ else if (!in_hard_reg_set_p (reg_class_contents[(int) class],
+ mode, valueno))
+ continue;
value = valtry;
where = p;
break;
and is also a register that appears in the address of GOAL. */
if (goal_mem && value == SET_DEST (single_set (where))
- && refers_to_regno_for_reload_p (valueno,
- (valueno
- + hard_regno_nregs[valueno][mode]),
+ && refers_to_regno_for_reload_p (valueno, end_hard_regno (mode, valueno),
goal, (rtx*) 0))
return 0;