* ira.c (ira_bad_reload_regno, ira_build_reload_regno_1): New functions.
* ira.h (ira_bad_reload_regno): Declare
* reload1.c (allocate_reload_reg): Use ira_bad_reload_regno.
From-SVN: r160001
2010-05-28 Jeff Law <law@redhat.com>
+ * ira.c (ira_bad_reload_regno, ira_build_reload_regno_1): New
+ functions.
+ * ira.h (ira_bad_reload_regno): Declare
+ * reload1.c (allocate_reload_reg): Use ira_bad_reload_regno.
+
* ira-color.c (update_curr_costs): Free updated hard reg costs.
(ira_reassign_conflict_allocnos): Remove bogus asserts.
(allocno_reload_assign): Likewise.
\f
+/* Return nonzero if REGNO is a particularly bad choice for reloading X. */
+static bool
+ira_bad_reload_regno_1 (int regno, rtx x)
+{
+ int x_regno;
+ ira_allocno_t a;
+ enum reg_class pref;
+
+ /* We only deal with pseudo regs. */
+ if (! x || GET_CODE (x) != REG)
+ return false;
+
+ x_regno = REGNO (x);
+ if (x_regno < FIRST_PSEUDO_REGISTER)
+ return false;
+
+ /* If the pseudo prefers REGNO explicitly, then do not consider
+ REGNO a bad spill choice. */
+ pref = reg_preferred_class (x_regno);
+ if (reg_class_size[pref] == 1)
+ return !TEST_HARD_REG_BIT (reg_class_contents[pref], regno);
+
+ /* If the pseudo conflicts with REGNO, then we consider REGNO a
+ poor choice for a reload regno. */
+ a = ira_regno_allocno_map[x_regno];
+ if (TEST_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), regno))
+ return true;
+
+ return false;
+}
+
+/* Return nonzero if REGNO is a particularly bad choice for reloading
+ IN or OUT. */
+bool
+ira_bad_reload_regno (int regno, rtx in, rtx out)
+{
+ return (ira_bad_reload_regno_1 (regno, in)
+ || ira_bad_reload_regno_1 (regno, out));
+}
+
/* Function specific hard registers that can not be used for the
register allocation. */
HARD_REG_SET ira_no_alloc_regs;
extern rtx ira_reuse_stack_slot (int, unsigned int, unsigned int);
extern void ira_mark_new_stack_slot (rtx, int, unsigned int);
extern bool ira_better_spill_reload_regno_p (int *, int *, rtx, rtx, rtx);
+extern bool ira_bad_reload_regno (int, rtx, rtx);
take any reg in the right class and not in use.
If we want a consecutive group, here is where we look for it.
- We use two passes so we can first look for reload regs to
+ We use three passes so we can first look for reload regs to
reuse, which are already in use for other reloads in this insn,
- and only then use additional registers.
+ and only then use additional registers which are not "bad", then
+ finally any register.
+
I think that maximizing reuse is needed to make sure we don't
run out of reload regs. Suppose we have three reloads, and
reloads A and B can share regs. These need two regs.
Suppose A and B are given different regs.
That leaves none for C. */
- for (pass = 0; pass < 2; pass++)
+ for (pass = 0; pass < 3; pass++)
{
/* I is the index in spill_regs.
We advance it round-robin between insns to use all spill regs
regnum))))
{
int nr = hard_regno_nregs[regnum][rld[r].mode];
+
+ /* During the second pass we want to avoid reload registers
+ which are "bad" for this reload. */
+ if (pass == 1
+ && ira_bad_reload_regno (regnum, rld[r].in, rld[r].out))
+ continue;
+
/* Avoid the problem where spilling a GENERAL_OR_FP_REG
(on 68000) got us two FP regs. If NR is 1,
we would reject both of them. */
}
}
- /* If we found something on pass 1, omit pass 2. */
+ /* If we found something on the current pass, omit later passes. */
if (count < n_spills)
break;
}