* ira.c (ira_bad_reload_regno, ira_build_reload_regno_1): New functions.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 May 2010 22:19:22 +0000 (22:19 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 May 2010 22:19:22 +0000 (22:19 +0000)
* 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

gcc/ChangeLog
gcc/ira.c
gcc/ira.h
gcc/reload1.c

index 3027edb..7bf2568 100644 (file)
@@ -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.
index 10be6da..84d7bc1 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1374,6 +1374,46 @@ setup_prohibited_mode_move_regs (void)
 
 \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;
index 9688f74..8c9734b 100644 (file)
--- 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);
 
index 85880f8..f385fbb 100644 (file)
@@ -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;
     }