This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Prevent coalesce in new-ra when class size == 1





Here's the reworked patch which also sets prefer_colors of the other web
when one web has a single register in its preferred class.

Bootstrapped and regtested on powerpc64-unknown-linux-gnu.

OK for mainline?

-Pat


2004-07-28  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.

Index: gcc/ra.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/ra.h,v
retrieving revision 1.11
diff -c -3 -p -r1.11 ra.h
*** gcc/ra.h      3 Jun 2004 15:01:08 -0000     1.11
--- gcc/ra.h      27 Jul 2004 17:49:52 -0000
*************** extern HARD_REG_SET never_use_colors;
*** 503,508 ****
--- 503,511 ----
  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
Index: gcc/ra.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/ra.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 ra.c
*** gcc/ra.c      20 May 2004 11:45:25 -0000    1.18
--- gcc/ra.c      27 Jul 2004 17:49:52 -0000
***************
*** 84,89 ****
--- 84,90 ----
     * 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);
*************** int orig_max_uid;
*** 147,152 ****
--- 148,154 ----
  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];
*************** hard_regs_count (HARD_REG_SET rs)
*** 212,217 ****
--- 214,232 ----
    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.  */
*************** init_ra (void)
*** 515,520 ****
--- 530,539 ----
        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: gcc/ra-colorize.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/ra-colorize.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 ra-colorize.c
*** gcc/ra-colorize.c   15 Mar 2004 18:20:39 -0000    1.18
--- gcc/ra-colorize.c   27 Jul 2004 17:49:52 -0000
*************** static void add_web_pair_cost (struct we
*** 92,97 ****
--- 92,98 ----
                           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);
*************** coalesce (void)
*** 841,847 ****
      }
    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))
      {
        remove_move (source, m);
        remove_move (target, m);
--- 842,849 ----
      }
    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)
!        || !ok_class (target, source))
      {
        remove_move (source, m);
        remove_move (target, m);
*************** sort_and_combine_web_pairs (int for_move
*** 2464,2469 ****
--- 2466,2504 ----
    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.  */

*************** aggressive_coalesce (void)
*** 2487,2493 ****
      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))
        {
          if ((s->type == PRECOLORED && ok (t, s))
            || s->type != PRECOLORED)
--- 2522,2529 ----
      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)
!         && ok_class (t, s))
        {
          if ((s->type == PRECOLORED && ok (t, s))
            || s->type != PRECOLORED)
*************** extended_coalesce_2 (void)
*** 2557,2562 ****
--- 2593,2599 ----
                            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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]