enum machine_mode reload_mode, enum reload_type type,
enum insn_code *picode, secondary_reload_info *prev_sri)
{
- enum reg_class class = NO_REGS;
+ enum reg_class rclass = NO_REGS;
enum reg_class scratch_class;
enum machine_mode mode = reload_mode;
enum insn_code icode = CODE_FOR_nothing;
sri.icode = CODE_FOR_nothing;
sri.prev_sri = prev_sri;
- class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+ rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
icode = sri.icode;
/* If we don't need any secondary registers, done. */
- if (class == NO_REGS && icode == CODE_FOR_nothing)
+ if (rclass == NO_REGS && icode == CODE_FOR_nothing)
return -1;
- if (class != NO_REGS)
- t_reload = push_secondary_reload (in_p, x, opnum, optional, class,
+ if (rclass != NO_REGS)
+ t_reload = push_secondary_reload (in_p, x, opnum, optional, rclass,
reload_mode, type, &t_icode, &sri);
/* If we will be using an insn, the secondary reload is for a
an icode to reload from an intermediate tertiary reload register.
We should probably have a new field in struct reload to tag a
chain of scratch operand reloads onto. */
- gcc_assert (class == NO_REGS);
+ gcc_assert (rclass == NO_REGS);
scratch_constraint = insn_data[(int) icode].operand[2].constraint;
gcc_assert (*scratch_constraint == '=');
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
scratch_constraint));
- class = scratch_class;
+ rclass = scratch_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. */
- gcc_assert (!in_p || class != reload_class || icode != CODE_FOR_nothing
+ gcc_assert (!in_p || rclass != reload_class || icode != CODE_FOR_nothing
|| t_icode != CODE_FOR_nothing);
/* See if we can reuse an existing secondary reload. */
for (s_reload = 0; s_reload < n_reloads; s_reload++)
if (rld[s_reload].secondary_p
- && (reg_class_subset_p (class, rld[s_reload].class)
- || reg_class_subset_p (rld[s_reload].class, class))
+ && (reg_class_subset_p (rclass, rld[s_reload].rclass)
+ || reg_class_subset_p (rld[s_reload].rclass, rclass))
&& ((in_p && rld[s_reload].inmode == mode)
|| (! in_p && rld[s_reload].outmode == mode))
&& ((in_p && rld[s_reload].secondary_in_reload == t_reload)
|| (! in_p && rld[s_reload].secondary_out_reload == t_reload))
&& ((in_p && rld[s_reload].secondary_in_icode == t_icode)
|| (! in_p && rld[s_reload].secondary_out_icode == t_icode))
- && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (secondary_type, rld[s_reload].when_needed,
opnum, rld[s_reload].opnum))
{
if (! in_p)
rld[s_reload].outmode = mode;
- if (reg_class_subset_p (class, rld[s_reload].class))
- rld[s_reload].class = class;
+ if (reg_class_subset_p (rclass, rld[s_reload].rclass))
+ rld[s_reload].rclass = rclass;
rld[s_reload].opnum = MIN (rld[s_reload].opnum, opnum);
rld[s_reload].optional &= optional;
way reloads are output. */
if (in_p && icode == CODE_FOR_nothing
- && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
+ && SECONDARY_MEMORY_NEEDED (rclass, reload_class, mode))
{
get_secondary_mem (x, reload_mode, opnum, type);
/* We need to make a new secondary reload for this register class. */
rld[s_reload].in = rld[s_reload].out = 0;
- rld[s_reload].class = class;
+ rld[s_reload].rclass = rclass;
rld[s_reload].inmode = in_p ? mode : VOIDmode;
rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
#ifdef SECONDARY_MEMORY_NEEDED
if (! in_p && icode == CODE_FOR_nothing
- && SECONDARY_MEMORY_NEEDED (reload_class, class, mode))
+ && SECONDARY_MEMORY_NEEDED (reload_class, rclass, mode))
get_secondary_mem (x, mode, opnum, type);
#endif
}
register and a scratch register is needed, we return the class of the
intermediate register. */
enum reg_class
-secondary_reload_class (bool in_p, enum reg_class class,
+secondary_reload_class (bool in_p, enum reg_class rclass,
enum machine_mode mode, rtx x)
{
enum insn_code icode;
sri.icode = CODE_FOR_nothing;
sri.prev_sri = NULL;
- class = targetm.secondary_reload (in_p, x, class, mode, &sri);
+ rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
icode = sri.icode;
/* If there are no secondary reloads at all, we return NO_REGS.
If an intermediate register is needed, we return its class. */
- if (icode == CODE_FOR_nothing || class != NO_REGS)
- return class;
+ if (icode == CODE_FOR_nothing || rclass != NO_REGS)
+ return rclass;
/* No intermediate register is needed, but we have a special reload
pattern, which we assume for now needs a scratch register. */
{
const char *scratch_constraint;
char scratch_letter;
- enum reg_class class;
+ enum reg_class rclass;
gcc_assert (insn_data[(int) icode].n_operands == 3);
scratch_constraint = insn_data[(int) icode].operand[2].constraint;
scratch_letter = *scratch_constraint;
if (scratch_letter == 'r')
return GENERAL_REGS;
- class = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
+ rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
scratch_constraint);
- gcc_assert (class != NO_REGS);
- return class;
+ gcc_assert (rclass != NO_REGS);
+ return rclass;
}
\f
#ifdef SECONDARY_MEMORY_NEEDED
unsigned int dest_regno ATTRIBUTE_UNUSED)
{
int best_cost = -1;
- int class;
+ int rclass;
int regno;
enum reg_class best_class = NO_REGS;
enum reg_class dest_class ATTRIBUTE_UNUSED = REGNO_REG_CLASS (dest_regno);
unsigned int best_size = 0;
int cost;
- for (class = 1; class < N_REG_CLASSES; class++)
+ for (rclass = 1; rclass < N_REG_CLASSES; rclass++)
{
int bad = 0;
int good = 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER - n && ! bad; regno++)
- if (TEST_HARD_REG_BIT (reg_class_contents[class], regno))
+ if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno))
{
if (HARD_REGNO_MODE_OK (regno, inner))
{
good = 1;
- if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+ if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], regno + n)
|| ! HARD_REGNO_MODE_OK (regno + n, outer))
bad = 1;
}
if (bad || !good)
continue;
- cost = REGISTER_MOVE_COST (outer, class, dest_class);
+ cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
- if ((reg_class_size[class] > best_size
+ if ((reg_class_size[rclass] > best_size
&& (best_cost < 0 || best_cost >= cost))
|| best_cost > cost)
{
- best_class = class;
- best_size = reg_class_size[class];
- best_cost = REGISTER_MOVE_COST (outer, class, dest_class);
+ best_class = rclass;
+ best_size = reg_class_size[rclass];
+ best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
}
}
\f
/* Return the number of a previously made reload that can be combined with
a new one, or n_reloads if none of the existing reloads can be used.
- OUT, CLASS, TYPE and OPNUM are the same arguments as passed to
+ OUT, RCLASS, TYPE and OPNUM are the same arguments as passed to
push_reload, they determine the kind of the new reload that we try to
combine. P_IN points to the corresponding value of IN, which can be
modified by this function.
DONT_SHARE is nonzero if we can't share any input-only reload for IN. */
static int
-find_reusable_reload (rtx *p_in, rtx out, enum reg_class class,
+find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
enum reload_type type, int opnum, int dont_share)
{
rtx in = *p_in;
than we otherwise would. */
for (i = 0; i < n_reloads; i++)
- if ((reg_class_subset_p (class, rld[i].class)
- || reg_class_subset_p (rld[i].class, class))
+ if ((reg_class_subset_p (rclass, rld[i].rclass)
+ || reg_class_subset_p (rld[i].rclass, rclass))
/* If the existing reload has a register, it must fit our class. */
&& (rld[i].reg_rtx == 0
- || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ || TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
true_regnum (rld[i].reg_rtx)))
&& ((in != 0 && MATCHES (rld[i].in, in) && ! dont_share
&& (out == 0 || rld[i].out == 0 || MATCHES (rld[i].out, out)))
|| (out != 0 && MATCHES (rld[i].out, out)
&& (in == 0 || rld[i].in == 0 || MATCHES (rld[i].in, in))))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed, opnum, rld[i].opnum))
return i;
the preincrementation as happening before any ref in this insn
to that register. */
for (i = 0; i < n_reloads; i++)
- if ((reg_class_subset_p (class, rld[i].class)
- || reg_class_subset_p (rld[i].class, class))
+ if ((reg_class_subset_p (rclass, rld[i].rclass)
+ || reg_class_subset_p (rld[i].rclass, rclass))
/* If the existing reload has a register, it must fit our
class. */
&& (rld[i].reg_rtx == 0
- || TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ || TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
true_regnum (rld[i].reg_rtx)))
&& out == 0 && rld[i].out == 0 && rld[i].in != 0
&& ((REG_P (in)
&& GET_RTX_CLASS (GET_CODE (in)) == RTX_AUTOINC
&& MATCHES (XEXP (in, 0), rld[i].in)))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
- && (SMALL_REGISTER_CLASS_P (class) || SMALL_REGISTER_CLASSES)
+ && (SMALL_REGISTER_CLASS_P (rclass) || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed,
opnum, rld[i].opnum))
{
If IN and OUT are both nonzero, it means the same register must be used
to reload both IN and OUT.
- CLASS is a register class required for the reloaded data.
+ RCLASS is a register class required for the reloaded data.
INMODE is the machine mode that the instruction requires
for the reg that replaces IN and OUTMODE is likewise for OUT.
int
push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
- enum reg_class class, enum machine_mode inmode,
+ enum reg_class rclass, enum machine_mode inmode,
enum machine_mode outmode, int strict_low, int optional,
int opnum, enum reload_type type)
{
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, rclass)
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
!= (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
[GET_MODE (SUBREG_REG (in))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
- || (secondary_reload_class (1, class, inmode, in) != NO_REGS
- && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
+ || (secondary_reload_class (1, rclass, inmode, in) != NO_REGS
+ && (secondary_reload_class (1, rclass, GET_MODE (SUBREG_REG (in)),
SUBREG_REG (in))
== NO_REGS))
#ifdef CANNOT_CHANGE_MODE_CLASS
if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
{
- enum reg_class in_class = class;
+ enum reg_class in_class = rclass;
if (REG_P (SUBREG_REG (in)))
in_class
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
- && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
!= (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
[GET_MODE (SUBREG_REG (out))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
- || (secondary_reload_class (0, class, outmode, out) != NO_REGS
- && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
+ || (secondary_reload_class (0, rclass, outmode, out) != NO_REGS
+ && (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
SUBREG_REG (out))
== NO_REGS))
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
{
- enum reg_class preferred_class = class;
+ enum reg_class preferred_class = rclass;
if (in != 0)
- preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+ preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
/* Output reloads may need analogous treatment, different in detail. */
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
/* Discard what the target said if we cannot do it. */
if (preferred_class != NO_REGS
|| (optional && type == RELOAD_FOR_OUTPUT))
- class = preferred_class;
+ rclass = preferred_class;
}
/* Make sure we use a class that can handle the actual pseudo
can handle SImode, QImode needs a smaller class. */
#ifdef LIMIT_RELOAD_CLASS
if (in_subreg_loc)
- class = LIMIT_RELOAD_CLASS (inmode, class);
+ rclass = LIMIT_RELOAD_CLASS (inmode, rclass);
else if (in != 0 && GET_CODE (in) == SUBREG)
- class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (in)), class);
+ rclass = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (in)), rclass);
if (out_subreg_loc)
- class = LIMIT_RELOAD_CLASS (outmode, class);
+ rclass = LIMIT_RELOAD_CLASS (outmode, rclass);
if (out != 0 && GET_CODE (out) == SUBREG)
- class = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (out)), class);
+ rclass = LIMIT_RELOAD_CLASS (GET_MODE (SUBREG_REG (out)), rclass);
#endif
/* Verify that this class is at least possible for the mode that
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (HARD_REGNO_MODE_OK (i, mode)
- && in_hard_reg_set_p (reg_class_contents[(int) class], mode, i))
+ && in_hard_reg_set_p (reg_class_contents[(int) rclass], mode, i))
break;
if (i == FIRST_PSEUDO_REGISTER)
{
/* 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. */
- gcc_assert (class != NO_REGS
+ gcc_assert (rclass != NO_REGS
|| (optional != 0 && type == RELOAD_FOR_OUTPUT));
- i = find_reusable_reload (&in, out, class, type, opnum, dont_share);
+ i = find_reusable_reload (&in, out, rclass, type, opnum, dont_share);
if (i == n_reloads)
{
if (in != 0)
secondary_in_reload
- = push_secondary_reload (1, in, opnum, optional, class, inmode, type,
+ = push_secondary_reload (1, in, opnum, optional, rclass, inmode, type,
&secondary_in_icode, NULL);
if (out != 0 && GET_CODE (out) != SCRATCH)
secondary_out_reload
- = push_secondary_reload (0, out, opnum, optional, class, outmode,
+ = push_secondary_reload (0, out, opnum, optional, rclass, outmode,
type, &secondary_out_icode, NULL);
/* We found no existing reload suitable for re-use.
|| (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))
+ rclass, inmode))
get_secondary_mem (in, inmode, opnum, type);
#endif
i = n_reloads;
rld[i].in = in;
rld[i].out = out;
- rld[i].class = class;
+ rld[i].rclass = rclass;
rld[i].inmode = inmode;
rld[i].outmode = outmode;
rld[i].reg_rtx = 0;
&& (REG_P (out)
|| (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (class,
+ && SECONDARY_MEMORY_NEEDED (rclass,
REGNO_REG_CLASS (reg_or_subregno (out)),
outmode))
get_secondary_mem (out, outmode, opnum, type);
else
remove_address_replacements (rld[i].in);
}
- rld[i].in = in;
- rld[i].in_reg = in_reg;
+ /* When emitting reloads we don't necessarily look at the in-
+ and outmode, but also directly at the operands (in and out).
+ So we can't simply overwrite them with whatever we have found
+ for this (to-be-merged) reload, we have to "merge" that too.
+ Reusing another reload already verified that we deal with the
+ same operands, just possibly in different modes. So we
+ overwrite the operands only when the new mode is larger.
+ See also PR33613. */
+ if (!rld[i].in
+ || GET_MODE_SIZE (GET_MODE (in))
+ > GET_MODE_SIZE (GET_MODE (rld[i].in)))
+ rld[i].in = in;
+ if (!rld[i].in_reg
+ || (in_reg
+ && GET_MODE_SIZE (GET_MODE (in_reg))
+ > GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
+ rld[i].in_reg = in_reg;
}
if (out != 0)
{
- rld[i].out = out;
- rld[i].out_reg = outloc ? *outloc : 0;
+ if (!rld[i].out
+ || (out
+ && GET_MODE_SIZE (GET_MODE (out))
+ > GET_MODE_SIZE (GET_MODE (rld[i].out))))
+ rld[i].out = out;
+ if (outloc
+ && (!rld[i].out_reg
+ || GET_MODE_SIZE (GET_MODE (*outloc))
+ > GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
+ rld[i].out_reg = *outloc;
}
- if (reg_class_subset_p (class, rld[i].class))
- rld[i].class = class;
+ if (reg_class_subset_p (rclass, rld[i].rclass))
+ rld[i].rclass = rclass;
rld[i].optional &= optional;
if (MERGE_TO_OTHER (type, rld[i].when_needed,
opnum, rld[i].opnum))
{
rld[i].reg_rtx = find_dummy_reload (in, out, inloc, outloc,
inmode, outmode,
- rld[i].class, i,
+ rld[i].rclass, i,
earlyclobber_operand_p (out));
/* If the outgoing register already contains the same value
&& reg_mentioned_p (XEXP (note, 0), in)
/* Check that a former pseudo is valid; see find_dummy_reload. */
&& (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
- || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
- ORIGINAL_REGNO (XEXP (note, 0)))
+ || (! bitmap_bit_p (flag_ira
+ ? DF_LR_OUT (ENTRY_BLOCK_PTR)
+ : DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+ ORIGINAL_REGNO (XEXP (note, 0)))
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
&& ! refers_to_regno_for_reload_p (regno,
end_hard_regno (rel_mode,
for (offs = 0; offs < nregs; offs++)
if (fixed_regs[regno + offs]
- || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
regno + offs))
break;
&& rld[i].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
&& rld[i].when_needed != RELOAD_FOR_OUTADDR_ADDRESS
&& rld[i].when_needed != RELOAD_OTHER
- && (CLASS_MAX_NREGS (rld[i].class, rld[i].inmode)
- == CLASS_MAX_NREGS (rld[output_reload].class,
+ && (CLASS_MAX_NREGS (rld[i].rclass, rld[i].inmode)
+ == CLASS_MAX_NREGS (rld[output_reload].rclass,
rld[output_reload].outmode))
&& rld[i].inc == 0
&& rld[i].reg_rtx == 0
secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum]))
#endif
&& (SMALL_REGISTER_CLASSES
- ? (rld[i].class == rld[output_reload].class)
- : (reg_class_subset_p (rld[i].class,
- rld[output_reload].class)
- || reg_class_subset_p (rld[output_reload].class,
- rld[i].class)))
+ ? (rld[i].rclass == rld[output_reload].rclass)
+ : (reg_class_subset_p (rld[i].rclass,
+ rld[output_reload].rclass)
+ || reg_class_subset_p (rld[output_reload].rclass,
+ rld[i].rclass)))
&& (MATCHES (rld[i].in, rld[output_reload].out)
/* Args reversed because the first arg seems to be
the one that we imagine being modified
rld[output_reload].out))))
&& ! reload_inner_reg_of_subreg (rld[i].in, rld[i].inmode,
rld[i].when_needed != RELOAD_FOR_INPUT)
- && (reg_class_size[(int) rld[i].class]
+ && (reg_class_size[(int) rld[i].rclass]
|| SMALL_REGISTER_CLASSES)
/* We will allow making things slightly worse by combining an
input and an output, but no worse than that. */
= secondary_memlocs_elim[(int) rld[output_reload].outmode][rld[output_reload].opnum];
#endif
/* If required, minimize the register class. */
- if (reg_class_subset_p (rld[output_reload].class,
- rld[i].class))
- rld[i].class = rld[output_reload].class;
+ if (reg_class_subset_p (rld[output_reload].rclass,
+ rld[i].rclass))
+ rld[i].rclass = rld[output_reload].rclass;
/* Transfer all replacements from the old reload to the combined. */
for (j = 0; j < n_replacements; j++)
rld[output_reload].out)
&& (regno = REGNO (XEXP (note, 0))) < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_MODE_OK (regno, rld[output_reload].outmode)
- && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].class],
+ && TEST_HARD_REG_BIT (reg_class_contents[(int) rld[output_reload].rclass],
regno)
&& (hard_regno_nregs[regno][rld[output_reload].outmode]
<= hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))])
won't want this register. */
&& ((secondary_out = rld[output_reload].secondary_out_reload) == -1
|| (!(TEST_HARD_REG_BIT
- (reg_class_contents[(int) rld[secondary_out].class], regno))
+ (reg_class_contents[(int) rld[secondary_out].rclass], regno))
&& ((secondary_out = rld[secondary_out].secondary_out_reload) == -1
|| !(TEST_HARD_REG_BIT
- (reg_class_contents[(int) rld[secondary_out].class],
+ (reg_class_contents[(int) rld[secondary_out].rclass],
regno)))))
&& !fixed_regs[regno]
/* Check that a former pseudo is valid; see find_dummy_reload. */
If so, return the register rtx that proves acceptable.
INLOC and OUTLOC are locations where IN and OUT appear in the insn.
- CLASS is the register class required for the reload.
+ RCLASS is the register class required for the reload.
If FOR_REAL is >= 0, it is the number of the reload,
and in some cases when it can be discovered that OUT doesn't need
static rtx
find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
enum machine_mode inmode, enum machine_mode outmode,
- enum reg_class class, int for_real, int earlyclobber)
+ enum reg_class rclass, int for_real, int earlyclobber)
{
rtx in = real_in;
rtx out = real_out;
/* Narrow down the reg class, the same way push_reload will;
otherwise we might find a dummy now, but push_reload won't. */
{
- enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, class);
+ enum reg_class preferred_class = PREFERRED_RELOAD_CLASS (in, rclass);
if (preferred_class != NO_REGS)
- class = preferred_class;
+ rclass = preferred_class;
}
/* See if OUT will do. */
unsigned int i;
for (i = 0; i < nwords; i++)
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ if (! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
regno + i))
break;
can ignore the conflict). We must never introduce writes
to such hardregs, as they would clobber the other live
pseudo. See PR 20973. */
- || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+ || (!bitmap_bit_p (flag_ira
+ ? DF_LR_OUT (ENTRY_BLOCK_PTR)
+ : DF_LIVE_OUT (ENTRY_BLOCK_PTR),
ORIGINAL_REGNO (in))
/* Similarly, only do this if we can be sure that the death
note is still valid. global can assign some hardreg to
unsigned int i;
for (i = 0; i < nwords; i++)
- if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ if (! TEST_HARD_REG_BIT (reg_class_contents[(int) rclass],
regno + i))
break;
if (REG_P (SUBREG_REG (operand))
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
- if (!subreg_offset_representable_p
- (REGNO (SUBREG_REG (operand)),
- GET_MODE (SUBREG_REG (operand)),
- SUBREG_BYTE (operand),
- GET_MODE (operand)))
- force_reload = 1;
+ if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand)) < 0)
+ force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
/* Any constants that aren't allowed and can't be reloaded
into registers are here changed into memory references. */
for (i = 0; i < noperands; i++)
- if (! goal_alternative_win[i]
- && CONST_POOL_OK_P (recog_data.operand[i])
- && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
- (enum reg_class) goal_alternative[i])
- == NO_REGS)
- || no_input_reloads)
- && operand_mode[i] != VOIDmode)
+ if (! goal_alternative_win[i])
{
- int this_address_reloaded;
+ rtx op = recog_data.operand[i];
+ rtx subreg = NULL_RTX;
+ rtx plus = NULL_RTX;
+ enum machine_mode mode = operand_mode[i];
+
+ /* Reloads of SUBREGs of CONSTANT RTXs are handled later in
+ push_reload so we have to let them pass here. */
+ if (GET_CODE (op) == SUBREG)
+ {
+ subreg = op;
+ op = SUBREG_REG (op);
+ mode = GET_MODE (op);
+ }
- this_address_reloaded = 0;
- substed_operand[i] = recog_data.operand[i]
- = find_reloads_toplev (force_const_mem (operand_mode[i],
- recog_data.operand[i]),
- i, address_type[i], ind_levels, 0, insn,
- &this_address_reloaded);
- if (alternative_allows_const_pool_ref (this_address_reloaded == 0
- ? substed_operand[i]
- : NULL,
- recog_data.constraints[i],
- goal_alternative_number))
- goal_alternative_win[i] = 1;
- }
+ if (GET_CODE (op) == PLUS)
+ {
+ plus = op;
+ op = XEXP (op, 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);
+ if (CONST_POOL_OK_P (op)
+ && ((PREFERRED_RELOAD_CLASS (op,
+ (enum reg_class) goal_alternative[i])
+ == NO_REGS)
+ || no_input_reloads)
+ && mode != VOIDmode)
+ {
+ int this_address_reloaded;
+ rtx tem = force_const_mem (mode, op);
- substed_operand[i] = recog_data.operand[i]
- = find_reloads_toplev (tem, i, address_type[i],
- ind_levels, 0, insn, NULL);
+ /* If we stripped a SUBREG or a PLUS above add it back. */
+ if (plus != NULL_RTX)
+ tem = gen_rtx_PLUS (mode, XEXP (plus, 0), tem);
+
+ if (subreg != NULL_RTX)
+ tem = gen_rtx_SUBREG (operand_mode[i], tem, SUBREG_BYTE (subreg));
+
+ this_address_reloaded = 0;
+ substed_operand[i] = recog_data.operand[i]
+ = find_reloads_toplev (tem, i, address_type[i], ind_levels,
+ 0, insn, &this_address_reloaded);
+
+ /* If the alternative accepts constant pool refs directly
+ there will be no reload needed at all. */
+ if (plus == NULL_RTX
+ && subreg == NULL_RTX
+ && alternative_allows_const_pool_ref (this_address_reloaded == 0
+ ? substed_operand[i]
+ : NULL,
+ recog_data.constraints[i],
+ goal_alternative_number))
+ goal_alternative_win[i] = 1;
+ }
}
/* Record the values of the earlyclobber operands for the caller. */
&& (!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));
+ add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
}
else
retval |= (substed_operand[i] != *recog_data.operand_loc[i]);
&& rld[i].out == 0)
{
rld[i].reg_rtx
- = find_equiv_reg (rld[i].in, insn, rld[i].class, -1,
+ = find_equiv_reg (rld[i].in, insn, rld[i].rclass, -1,
static_reload_reg_p, 0, rld[i].inmode);
/* Prevent generation of insn to load the value
because the one we found already has the value. */
if (i != j && rld[j].in != 0 && rld[j].out == 0
&& rld[j].when_needed == rld[i].when_needed
&& MATCHES (rld[i].in, rld[j].in)
- && rld[i].class == rld[j].class
+ && rld[i].rclass == rld[j].rclass
&& !rld[i].nocombine && !rld[j].nocombine
&& rld[i].reg_rtx == rld[j].reg_rtx)
{
> GET_MODE_SIZE (rld[i].inmode)))
? rld[i].outmode : rld[i].inmode;
- rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
+ rld[i].nregs = CLASS_MAX_NREGS (rld[i].rclass, rld[i].mode);
}
/* Special case a simple move with an input reload and a
unsigned int regno = REGNO (dest);
if (regno < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
+ && TEST_HARD_REG_BIT (reg_class_contents[rld[i].rclass], regno)
&& HARD_REGNO_MODE_OK (regno, rld[i].mode))
{
int nr = hard_regno_nregs[regno][rld[i].mode];
int ok = 1, nri;
for (nri = 1; nri < nr; nri ++)
- if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno + nri))
+ if (! TEST_HARD_REG_BIT (reg_class_contents[rld[i].rclass], regno + nri))
ok = 0;
if (ok)
is larger than the class size, then reload the whole SUBREG. */
else
{
- enum reg_class class = context_reg_class;
- if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
- > reg_class_size[class])
+ enum reg_class rclass = context_reg_class;
+ if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
+ > reg_class_size[rclass])
{
x = find_reloads_subreg_address (x, 0, opnum,
ADDR_TYPE (type),
ind_levels, insn);
- push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
+ push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
}
\f
/* X, which is found at *LOC, is a part of an address that needs to be
- reloaded into a register of class CLASS. If X is a constant, or if
+ reloaded into a register of class RCLASS. If X is a constant, or if
X is a PLUS that contains a constant, check that the constant is a
legitimate operand and that we are supposed to be able to load
it into the register.
supports. */
static void
-find_reloads_address_part (rtx x, rtx *loc, enum reg_class class,
+find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
enum machine_mode mode, int opnum,
enum reload_type type, int ind_levels)
{
if (CONSTANT_P (x)
&& (! LEGITIMATE_CONSTANT_P (x)
- || PREFERRED_RELOAD_CLASS (x, class) == NO_REGS))
+ || PREFERRED_RELOAD_CLASS (x, rclass) == NO_REGS))
{
x = force_const_mem (mode, x);
find_reloads_address (mode, &x, XEXP (x, 0), &XEXP (x, 0),
else if (GET_CODE (x) == PLUS
&& CONSTANT_P (XEXP (x, 1))
&& (! LEGITIMATE_CONSTANT_P (XEXP (x, 1))
- || PREFERRED_RELOAD_CLASS (XEXP (x, 1), class) == NO_REGS))
+ || PREFERRED_RELOAD_CLASS (XEXP (x, 1), rclass) == NO_REGS))
{
rtx tem;
opnum, type, ind_levels, 0);
}
- push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
+ push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
mode, VOIDmode, 0, 0, opnum, type);
}
\f
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
/* 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
+ SImode but not in HImode. Similarly, the address may
+ have been valid before the subreg offset was added,
+ but not afterwards. find_reloads_address
assumes that we pass it a valid address, and doesn't
force a reload. This will probably be fine if
find_reloads_address finds some reloads. But if it
doesn't find any, then we may have just converted a
valid address into an invalid one. Check for that
here. */
- if (reloaded != 1
- && strict_memory_address_p (orig_mode, XEXP (tem, 0))
+ if (reloaded == 0
&& !strict_memory_address_p (GET_MODE (tem),
XEXP (tem, 0)))
push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
\f
/* Check the insns before INSN to see if there is a suitable register
containing the same value as GOAL.
- If OTHER is -1, look for a register in class CLASS.
+ If OTHER is -1, look for a register in class RCLASS.
Otherwise, just see if register number OTHER shares GOAL's value.
Return an rtx for the register found, or zero if none is found.
as if it were a constant except that sp is required to be unchanging. */
rtx
-find_equiv_reg (rtx goal, rtx insn, enum reg_class class, int other,
+find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
short *reload_reg_p, int goalreg, enum machine_mode mode)
{
rtx p = insn;
}
else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
continue;
- else if (!in_hard_reg_set_p (reg_class_contents[(int) class],
+ else if (!in_hard_reg_set_p (reg_class_contents[(int) rclass],
mode, valueno))
continue;
value = valtry;
fprintf (f, "\n\t");
}
- fprintf (f, "%s, ", reg_class_names[(int) rld[r].class]);
+ fprintf (f, "%s, ", reg_class_names[(int) rld[r].rclass]);
fprintf (f, "%s (opnum = %d)",
reload_when_needed_name[(int) rld[r].when_needed],