ra.h (single_reg_in_regclass): Declare.
authorPat Haugen <pthaugen@us.ibm.com>
Thu, 29 Jul 2004 14:49:22 +0000 (14:49 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Thu, 29 Jul 2004 14:49:22 +0000 (10:49 -0400)
2004-07-29  Pat Haugen  <pthaugen@us.ibm.com>

        * ra.h (single_reg_in_regclass): Declare.
        * ra.c (single_reg_in_regclass): Define.
        (first_hard_reg): New.
        (init_ra): Initialize single_reg_in_regclass.
        * ra-colorize.c (ok_class): New.
        (coalesce, aggressive_coalesce, extended_coalesce_2): Use it.

From-SVN: r85300

gcc/ChangeLog
gcc/ra-colorize.c
gcc/ra.c
gcc/ra.h

index a71b8a2c992406f44f44d27d6b749577c9e58db5..896e6b0785078108b8677e0327d6c4afa8c5be18 100644 (file)
@@ -1,3 +1,12 @@
+2004-07-29  Pat Haugen  <pthaugen@us.ibm.com>
+
+       * ra.h (single_reg_in_regclass): Declare.
+       * ra.c (single_reg_in_regclass): Define.
+       (first_hard_reg): New.
+       (init_ra): Initialize single_reg_in_regclass.
+       * ra-colorize.c (ok_class): New.
+       (coalesce, aggressive_coalesce, extended_coalesce_2): Use it.
+
 2004-07-29  Nathan Sidwell  <nathan@codesourcery.com>
 
        * gcov-io.h: Allow zero tag as EOF indicator.
index 3d248fa40ea6e69ffc5063d4a095444f15af695d..e3118a0cdac3a36d2f2810e8c713a0c637e51e73 100644 (file)
@@ -92,6 +92,7 @@ static void add_web_pair_cost (struct web *, struct web *,
                               unsigned HOST_WIDE_INT, unsigned int);
 static int comp_web_pairs (const void *, const void *);
 static void sort_and_combine_web_pairs (int);
+static int ok_class (struct web *, struct web *);
 static void aggressive_coalesce (void);
 static void extended_coalesce_2 (void);
 static void check_uncoalesced_moves (void);
@@ -841,7 +842,8 @@ coalesce (void)
     }
   else if (target->type == PRECOLORED
           || TEST_BIT (sup_igraph, source->id * num_webs + target->id)
-          || TEST_BIT (sup_igraph, target->id * num_webs + source->id))
+          || TEST_BIT (sup_igraph, target->id * num_webs + source->id)
+          || !ok_class (target, source))
     {
       remove_move (source, m);
       remove_move (target, m);
@@ -2464,6 +2466,39 @@ sort_and_combine_web_pairs (int for_move)
   free (sorted);
 }
 
+/* Returns nonzero if source/target reg classes are ok for coalesce.  */
+
+static int
+ok_class (struct web *target, struct web *source)
+{
+  /* Don't coalesce if preferred classes are different and at least one
+     of them has a size of 1. This was preventing things such as the
+     branch on count transformation (i.e. DoLoop) since the target, which
+     prefers the CTR, was being coalesced with a source which preferred
+     GENERAL_REGS. If only one web has a preferred class with 1 free reg
+     then set it as the preferred color of the other web.   */
+  enum reg_class t_class, s_class;
+  t_class = reg_preferred_class (target->regno);
+  s_class = reg_preferred_class (source->regno);
+  if (t_class != s_class)
+    {
+      if (num_free_regs[t_class] == 1)
+       {
+         if (num_free_regs[s_class] != 1)
+           SET_HARD_REG_BIT (source->prefer_colors,
+                             single_reg_in_regclass[t_class]);
+         return 0;
+       }
+      else if (num_free_regs[s_class] == 1)
+       {
+           SET_HARD_REG_BIT (target->prefer_colors,
+                             single_reg_in_regclass[s_class]);
+         return 0;
+       }
+    }
+  return 1;
+}
+
 /* Greedily coalesce all moves possible.  Begin with the web pair
    giving the most saving if coalesced.  */
 
@@ -2487,7 +2522,8 @@ aggressive_coalesce (void)
        if (s != t
            && t->type != PRECOLORED
            && !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
-           && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
+           && !TEST_BIT (sup_igraph, t->id * num_webs + s->id)
+           && ok_class (t, s))
          {
            if ((s->type == PRECOLORED && ok (t, s))
                || s->type != PRECOLORED)
@@ -2557,6 +2593,7 @@ extended_coalesce_2 (void)
                                    dest->id * num_webs + source->id)
                      && !TEST_BIT (sup_igraph,
                                    source->id * num_webs + dest->id)
+                     && ok_class (dest, source)
                      && hard_regs_intersect_p (&source->usable_regs,
                                                &dest->usable_regs))
                    add_web_pair_cost (dest, source,
index acc1be57e335fab43d08c9545825d0599677a33a..c1098e4c5fcb5a6a15c951e2a385b33f9928106d 100644 (file)
--- a/gcc/ra.c
+++ b/gcc/ra.c
@@ -84,6 +84,7 @@
    * use the constraints from asms
   */
 
+static int first_hard_reg (HARD_REG_SET);
 static struct obstack ra_obstack;
 static void create_insn_info (struct df *);
 static void free_insn_info (void);
@@ -147,6 +148,7 @@ int orig_max_uid;
 HARD_REG_SET never_use_colors;
 HARD_REG_SET usable_regs[N_REG_CLASSES];
 unsigned int num_free_regs[N_REG_CLASSES];
+int single_reg_in_regclass[N_REG_CLASSES];
 HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
 HARD_REG_SET invalid_mode_change_regs;
 unsigned char byte2bitcount[256];
@@ -212,6 +214,19 @@ hard_regs_count (HARD_REG_SET rs)
   return count;
 }
 
+/* Returns the first hardreg in HARD_REG_SET RS. Assumes there is at
+   least one reg in the set.  */
+
+static int
+first_hard_reg (HARD_REG_SET rs)
+{
+  int c;
+  for (c = 0; c < FIRST_PSEUDO_REGISTER && !TEST_HARD_REG_BIT (rs, c); c++)
+  if (c == FIRST_PSEUDO_REGISTER)
+    abort();
+  return c;
+}
+
 /* Basically like emit_move_insn (i.e. validifies constants and such),
    but also handle MODE_CC moves (but then the operands must already
    be basically valid.  */
@@ -515,6 +530,10 @@ init_ra (void)
       size = hard_regs_count (rs);
       num_free_regs[i] = size;
       COPY_HARD_REG_SET (usable_regs[i], rs);
+      if (size == 1)
+       single_reg_in_regclass[i] = first_hard_reg (rs);
+      else
+       single_reg_in_regclass[i] = -1;
     }
 
   /* Setup hardregs_for_mode[].
index 2e2fa408989c69041d5e97248b51ab10cde334b7..9bcc6f54c6a47ad694899fc07abc1b5141b8fc3e 100644 (file)
--- a/gcc/ra.h
+++ b/gcc/ra.h
@@ -503,6 +503,9 @@ extern HARD_REG_SET never_use_colors;
 extern HARD_REG_SET usable_regs[N_REG_CLASSES];
 /* For each class C the count of hardregs in usable_regs[C].  */
 extern unsigned int num_free_regs[N_REG_CLASSES];
+/* For each class C which has num_free_regs[C]==1, the color of the
+   single register in that class, -1 otherwise.  */
+extern int single_reg_in_regclass[N_REG_CLASSES];
 /* For each mode M the hardregs, which are MODE_OK for M, and have
    enough space behind them to hold an M value.  Additionally
    if reg R is OK for mode M, but it needs two hardregs, then R+1 will