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
/* 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. Abort if no such class exists. */
+ into REGNO. Such a class must exist. */
static enum reg_class
find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
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. */
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);
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. */
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;
}
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
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);
}
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
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
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))