summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2010-05-28 22:19:22 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2010-05-28 22:19:22 +0000
commit732f3fd856cc1c94fc0f28b75f08d7b5fadc27dc (patch)
tree9dc1cb58dbd6084f4583c0e45cae66cdd60ca456
parent0570b029190acc7fbffc0930534f6320660229b3 (diff)
downloadgcc-732f3fd856cc1c94fc0f28b75f08d7b5fadc27dc.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@160001 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/ira.c40
-rw-r--r--gcc/ira.h1
-rw-r--r--gcc/reload1.c17
4 files changed, 59 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3027edb07e7..7bf25681d61 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
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.
diff --git a/gcc/ira.c b/gcc/ira.c
index 10be6da4054..84d7bc1643b 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1374,6 +1374,46 @@ setup_prohibited_mode_move_regs (void)
+/* 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;
diff --git a/gcc/ira.h b/gcc/ira.h
index 9688f7485dc..8c9734b8be3 100644
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -86,4 +86,5 @@ extern bool ira_reassign_pseudos (int *, int, HARD_REG_SET, HARD_REG_SET *,
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);
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 85880f8210c..f385fbb757a 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -5793,15 +5793,17 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
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
@@ -5841,6 +5843,13 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
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. */
@@ -5871,7 +5880,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
}
}
- /* 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;
}