return false;
}
+/* 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) \
+ (ira_class_hard_regs_num [(C)] == 1 \
+ || (ira_class_hard_regs_num [(C)] >= 1 \
+ && targetm.class_likely_spilled_p (C)))
+
/* Return true if REG satisfies (or will satisfy) reg class constraint
CL. Use elimination first if REG is a hard register. If REG is a
reload pseudo created by this constraints pass, assume that it will
common_class = ira_reg_class_subset[rclass][cl];
if (new_class != NULL)
*new_class = common_class;
- return enough_allocatable_hard_regs_p (common_class, reg_mode);
+ return (enough_allocatable_hard_regs_p (common_class, reg_mode)
+ /* Do not permit reload insn operand matching (new_class == NULL
+ case) if the new class is too small. */
+ && (new_class != NULL || common_class == rclass
+ || !SMALL_REGISTER_CLASS_P (common_class)));
}
}
&& GET_MODE_SIZE (MODE).is_constant () \
&& !targetm.cannot_force_const_mem (MODE, 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) \
- (ira_class_hard_regs_num [(C)] == 1 \
- || (ira_class_hard_regs_num [(C)] >= 1 \
- && targetm.class_likely_spilled_p (C)))
-
/* If REG is a reload pseudo, try to make its class satisfying CL. */
static void
narrow_reload_pseudo_class (rtx reg, enum reg_class cl)
/* True if output stack pointer reload should be generated for the current
alternative. */
bool curr_alt_out_sp_reload_p;
+ bool curr_alt_class_change_p;
rtx op;
/* The register when the operand is a subreg of register, otherwise the
operand itself. */
early_clobbered_regs_num = 0;
curr_alt_out_sp_reload_p = false;
curr_reuse_alt_p = true;
+ curr_alt_class_change_p = false;
for (nop = 0; nop < n_operands; nop++)
{
bool scratch_p;
machine_mode mode;
enum constraint_num cn;
+ bool class_change_p = false;
opalt_num = nalt * n_operands + nop;
if (curr_static_id->operand_alternative[opalt_num].anything_ok)
(this_alternative_exclude_start_hard_regs,
hard_regno[nop]))))
win = true;
- else if (hard_regno[nop] < 0
- && in_class_p (op, this_alternative, NULL))
- win = true;
+ else if (hard_regno[nop] < 0)
+ {
+ if (in_class_p (op, this_alternative, NULL))
+ win = true;
+ else if (in_class_p (op, this_alternative, NULL, true))
+ {
+ class_change_p = true;
+ win = true;
+ }
+ }
}
break;
}
if (win)
{
this_alternative_win = true;
+ if (class_change_p)
+ {
+ curr_alt_class_change_p = true;
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file,
+ " %d Narrowing class: reject+=3\n",
+ nop);
+ reject += 3;
+ }
if (operand_reg[nop] != NULL_RTX)
{
if (hard_regno[nop] >= 0)
reject++;
}
if (in_class_p (operand_reg[nop],
- this_costly_alternative, NULL))
+ this_costly_alternative, NULL, true))
{
if (lra_dump_file != NULL)
fprintf
best_reload_sum = reload_sum;
goal_alt_number = nalt;
}
- if (losers == 0)
+ if (losers == 0 && !curr_alt_class_change_p)
/* Everything is satisfied. Do not process alternatives
anymore. */
break;
if (REG_P (reg) && (regno = REGNO (reg)) >= FIRST_PSEUDO_REGISTER)
{
- bool ok_p = in_class_p (reg, goal_alt[i], &new_class);
+ bool ok_p = in_class_p (reg, goal_alt[i], &new_class, true);
if (new_class != NO_REGS && get_reg_class (regno) != new_class)
{