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]

[new-ra] good register classes for webs


Hi Michael !

This is a patch for choosing better register classes for webs. This
patch based on pre-rload not on regclass.
(You must be more happy with this ;)

I have collected all correct alternatives for all insns as list of
alternatives connected to ra_ref's. Look at changes in pre-reload they
are very simple !

After that I have a four passes of different web_class_... routines.
1. Calculate cost of each alternative for a ref, select alternative
   with minimal cost, calculate sum of all cost for all refs for each
   web. This process similar to regclass but based on information
   collected by pre-reload. Now we can calculate preferred class for
   each web but such class will be without influence of other webs.
   IE: *movxf_integer allow float->float, int->int
        but regect float->int and int->float.
       many insns with Q_REGS (QImode) have similar things.
   IMHO: it's important;
2. insn by insn select better alternative according to web costs;
3. restart pass 1 with selected insn alternatives. Calculate right
   costs;
4. Select reg_class for each web and add spill code for each ref which
   have a wrong reg_class (reg_class which isn't a subset of web->regclass).


I have successfully bootstrapped GCC with this patch but only with C
and F77 languages. It's because of syntax error inside libstdc++-v3 or
C++ parser error or may be my problem with something else (IMHO: not
with new-ra).

Denis.

2004-03-03  Denis Chertykov  <denisc@overta.ru>

        * ra-build.c (flags.h): include new file.
        (long_blocks_for_mode) New array. The number of
        non-overlapping blocks of hardregs required for MODE.
        (select_regclass): Use web_class_costs for calculation of
        reg_class costs for each web. Use web_class_insn_alt to select
        right insn alternative for each insn. Use we_class_spill to
        generate spill code for refs with wrong reg_class.
        (class_ok_for_mode): Removed. Better to use
        long_blocks_for_mode.
        (web_class): Removed.
        (init_long_blocks_for_classes): New function. Initialize
        long_blocks_for_mode.
        (calc_pref_class): New function. Calculate preferred class
        for web.
        (web_class_costs): New function. Calculate reg_class costs for
        web.
        (web_class_insn_alt): New functin. Select insn alternatives
        according to costs of register classes.
        (web_class_spill): New functin. Add spill code for refs with
        wrong reg_class.

        * ra-colorize.c (colorize_one_web): Add code which disable
        spilling of dead webs.

        * ra.c (one_pass): Remeber last max uid of insn and use it
        after spilling introduced by web_class...

        * ra.h (costs): New structure. Records the cost of using a
          hard register of each class.
        (init_long_blocks_for_classes): Declare prototype.

        * pre-reload.h 
        * pre-reload.c (scan_addr_create_ref): Initialize alt_link field.
        (scan_alternative): Right hanlde '*' and '#' constraint modifiers.
        (collect_insn_info): Record list of correct alternatives.
        * pre-reload.h (alt_link): New structure. Used for list of correct
        alternatives.
        (struct ra_ref): Use alt_link.



Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-build.c,v
retrieving revision 1.1.2.26
diff -c -3 -p -r1.1.2.26 ra-build.c
*** ra-build.c  6 Nov 2003 17:07:02 -0000       1.1.2.26
--- ra-build.c  3 Mar 2004 12:00:46 -0000
***************
*** 1,5 ****
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>
  
--- 1,5 ----
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>
  
***************
*** 36,41 ****
--- 36,42 ----
  #include "ggc.h"
  #include "obstack.h"
  #include "reload.h"
+ #include "flags.h"
  #include "pre-reload.h"
  #include "ra.h"
  
*************** static void free_bb_info (void);
*** 126,132 ****
  static void build_web_parts_and_conflicts (struct df *);
  static void select_regclass (void);
  static void detect_spanned_deaths (unsigned int *spanned_deaths);
! static void web_class (struct web*);
  
  /* A sbitmap of DF_REF_IDs of uses, which are live over an abnormal
     edge.  */
--- 127,135 ----
  static void build_web_parts_and_conflicts (struct df *);
  static void select_regclass (void);
  static void detect_spanned_deaths (unsigned int *spanned_deaths);
! static void web_class_spill (struct web*, char *);
! static void web_class_costs (struct web *, char *, struct costs *);
! static void web_class_insn_alt (rtx, char *, struct costs *);
  
  /* A sbitmap of DF_REF_IDs of uses, which are live over an abnormal
     edge.  */
*************** struct ra_bb_info
*** 177,182 ****
--- 180,188 ----
    void *old_aux;
  };
  
+ /* The number of non-overlapping blocks of hardregs required for MODE.  */
+ static int long_blocks_for_mode[N_REG_CLASSES][MAX_MACHINE_MODE];
+ 
  /* We need a fast way to describe a certain part of a register.
     Therefore we put together the size and offset (in bytes) in one
     integer.  */
*************** static void
*** 2980,2986 ****
--- 2986,3047 ----
  select_regclass ()
  {
    struct dlist *d, *d_next;
+   char *insn_alternative;
+   basic_block bb;
+   struct costs *web_costs = xcalloc (sizeof (struct costs), num_webs);
+ 
+   /* Firts pass of web_class. Choose the best reg_class for each web.  */
+   for (d = WEBS (INITIAL); d; d = d_next)
+     {
+       struct web *web = DLIST_WEB (d);
+       d_next = d->next;
+       if (web->regno < FIRST_PSEUDO_REGISTER)
+       continue;
+       web_class_costs (web, NULL, web_costs);
+     }
+   insn_alternative = xmalloc (get_max_uid ());
+   memset (insn_alternative, -1, get_max_uid ());
+   /* Second pass of web_clsss. Select a better alternative for each insn
+      depend from reg_class of each web.  */
+   FOR_EACH_BB (bb)
+     {
+       rtx end = bb->end;
+       rtx insn;
+ 
+       for (insn = bb->head;
+          insn && PREV_INSN (insn) != end;
+          insn = NEXT_INSN (insn))
+       {
+         enum rtx_code pat_code;
+         enum rtx_code code = GET_CODE (insn);
+         
+         if (GET_RTX_CLASS (code) != 'i')
+           continue;
  
+         pat_code = GET_CODE (PATTERN (insn));
+         if (pat_code == USE
+             || pat_code == CLOBBER
+             || pat_code == ASM_INPUT
+             || pat_code == ADDR_VEC
+             || pat_code == ADDR_DIFF_VEC)
+           continue;
+         web_class_insn_alt (insn, insn_alternative, web_costs);
+       }
+     }
+   memset (web_costs, 0, sizeof (struct costs) * num_webs);
+   /* Third pass of web_class. Select better reg_class for each web according
+      to selected insn alternatives.  */
+   for (d = WEBS (INITIAL); d; d = d_next)
+     {
+       struct web *web = DLIST_WEB (d);
+       d_next = d->next;
+       if (web->regno < FIRST_PSEUDO_REGISTER)
+       continue;
+       web_class_costs (web, insn_alternative, web_costs);
+     }
+ 
+   free (web_costs);
+   
    for (d = WEBS (INITIAL); d; d = d_next)
      {
        int i;
*************** select_regclass ()
*** 2995,3001 ****
        
        if (flag_ra_pre_reload)
        {
!         web_class (web);
          if (WEBS (SPILLED))
            continue;
        }
--- 3056,3064 ----
        
        if (flag_ra_pre_reload)
        {
!         /* Fourth pass of web_class. Emit a spill code for such refs of web
!          which have wrong reg_class. */
!         web_class_spill (web, insn_alternative);
          if (WEBS (SPILLED))
            continue;
        }
*************** found:
*** 3143,3148 ****
--- 3206,3212 ----
          COPY_HARD_REG_SET (sweb->orig_usable_regs, web->orig_usable_regs);
        }
      }
+   free (insn_alternative);
  }  
  
  /* Second top-level function of this file.
*************** detect_spanned_deaths (spanned_deaths)
*** 3909,3947 ****
    sbitmap_free (defs_per_insn);
  }
  
! static int class_ok_for_mode PARAMS ((enum reg_class, enum machine_mode));
!      
! /* Returns true if at least one of the hardregs in CLASS is OK
!    for MODE.  */
! static int
! class_ok_for_mode (class, mode)
!      enum reg_class class;
!      enum machine_mode mode;
  {
!   int i;
!   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], i)
!       && HARD_REGNO_MODE_OK (i, mode))
!       return 1;
!   return 0;
  }
  
! /* Select a reg_class for the WEB. Split the WEB if single reg_class
!    can't be selected.  */
  static void
! web_class (web)
!      struct web *web;
  {
    unsigned int i, n, num_refs;
    struct ref *dref;
    struct ref **refs;
    struct ra_ref *rref;
!   enum reg_class class;
!   int web_size;
    int spilled_web = 0;
    bitmap already_insn = NULL;
  
!   class = ALL_REGS;
    for (n = 0, refs = web->uses, num_refs = web->num_uses;
         n < 2;
         refs = web->defs, num_refs = web->num_defs, n++)
--- 3973,4217 ----
    sbitmap_free (defs_per_insn);
  }
  
! void
! init_long_blocks_for_classes (void)
  {
!   enum machine_mode m;
!   enum reg_class class;
!   for (class = 0; class < N_REG_CLASSES; ++class)
!     for (m = 0; m < MAX_MACHINE_MODE; ++m)
!       long_blocks_for_mode[class][m]
!       = count_long_blocks (usable_regs[class], CLASS_MAX_NREGS (class, m));
! }
! 
! /* Calculates the preferred reg_class for web WEB. The calculation based on
!    costs array.  */
! static enum reg_class
! calc_pref_class (struct costs *p, struct web *web)
! {
!   int class;
!   int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
!   enum reg_class best = ALL_REGS;
!   enum machine_mode mode = PSEUDO_REGNO_MODE (web->regno);
! 
!   for (class = (int) ALL_REGS - 1; class > 0; class--)
!     {
!       /* Ignore classes that are too small for this operand or
!        invalid for an operand that was auto-incremented.  */
!       if (!long_blocks_for_mode [class][mode]
! #ifdef FORBIDDEN_INC_DEC_CLASSES
!         || (in_inc_dec[web->regno] && forbidden_inc_dec_class[class])
! #endif
! #ifdef CANNOT_CHANGE_MODE_CLASS
!         || (web->mode_changed
!             && invalid_mode_change_p (web->regno, (enum reg_class) class,
!                                       mode))
! #endif
!         )
!       ;
!       else if (p->cost[class] < best_cost)
!       {
!         best_cost = p->cost[class];
!         best = (enum reg_class) class;
!       }
!       else if (p->cost[class] == best_cost
!              && reg_class_size[class] > reg_class_size[best])
!       best = class;
!     }
!   return best;
  }
  
! /* Calculate reg_class costs for web WEB.  */
  static void
! web_class_costs (struct web *web, char *insn_alternative,
!                struct costs *web_costs)
! {
!   struct costs q;
!   struct costs *p;
!   struct ref **refs;
!   struct ra_ref *rref;
!   unsigned int i,j;
!   int n;
!   unsigned int num_refs;
! 
!   p = &web_costs[web->id];
!   
!   for (n = 0, refs = web->uses, num_refs = web->num_uses;
!        n < 2;
!        refs = web->defs, num_refs = web->num_defs, n++)
!     for (i = 0; i < num_refs; i++)
!       {
!       struct ref *ref = refs[i];
!       enum machine_mode mode = GET_MODE (DF_REF_REG (ref));
!       rref = DF2RA (df2ra, ref);
!       if (rref)
!         {
!           int frequency;
!           
!           for (j = 0; j < N_REG_CLASSES; j++)
!             q.cost[j] = 10000;
!           
!           if (rref->alt_link)
!             {
!               struct alt_link *alt;
!               int altno = (insn_alternative
!                            ? insn_alternative[INSN_UID (rref->insn)]
!                            : -2);
!               /* Check for insns without alternatives.  */
!               if (altno == -1)
!                 abort ();
!               
!               for (alt = rref->alt_link; alt; alt = alt->next)
!                 if (altno < 0 || altno == alt->alt)
!                   for (j = 0; j < N_REG_CLASSES; ++j)
!                     {
!                       int c;
!                       if (n == 0) /* It's use.  */
!                         c = may_move_in_cost[mode][j][(int) alt->class];
!                       else
!                         c = may_move_out_cost[mode][(int) alt->class][j];
!                       q.cost[j] = MIN (c + alt->reject, q.cost[j]);
!                     }
!             }
!           else
!             for (j = 0; j < N_REG_CLASSES; ++j)
!               {
!                 int c;
!                 if (n == 0) /* It's use.  */
!                   c = may_move_in_cost[mode][j][(int) rref->class];
!                 else
!                   c = may_move_out_cost[mode][(int) rref->class][j];
!                 q.cost[j] = MIN (c, q.cost[j]);
!               }
!           frequency = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (rref->insn));
!           for (j = 0; j < N_REG_CLASSES; ++j)
!             p->cost[j] += q.cost[j] * frequency;
!         }
!       }
! 
!   web->regclass = calc_pref_class (p, web);
! }
! 
! /* Correct reg-class preferences according to insn alternatives.  */
! static void
! web_class_insn_alt (rtx insn, char * insn_alternative, struct costs *web_costs)
! {
!   unsigned int d, best_alt;
!   int best_cost, freeness;
!   int j;
!   struct costs *p;
!   struct ra_ref *rref;
!   int alt_costs[MAX_RECOG_ALTERNATIVES];
!   int alt_init_p[MAX_RECOG_ALTERNATIVES];
!   int alt_freeness[MAX_RECOG_ALTERNATIVES];
!   struct ra_insn_info info = insn_df[INSN_UID (insn)];
! 
!   memset (&alt_init_p, 0, sizeof (alt_init_p));
!   memset (&alt_freeness, 0, sizeof (alt_freeness));
!   for (d = 0; d < MAX_RECOG_ALTERNATIVES; ++d)
!     alt_costs[d] = (1 << (HOST_BITS_PER_INT - 2)) - 1;
!       
!   for (d = 0; d < info.num_defs; d++)
!     {
!       struct ref *ref = info.defs[d];
!       enum machine_mode mode = GET_MODE (DF_REF_REG (ref));
! 
!       if (REGNO (DF_REF_REAL_REG (ref)) <= FIRST_PSEUDO_REGISTER)
!       continue;
!       
!       rref = DF2RA (df2ra, ref);
!       if (rref)
!       {
!         struct web *web = def2web[DF_REF_ID (ref)];
!         p = &web_costs[web->id];
!           
!         if (rref->alt_link)
!           {
!             struct alt_link *alt;
!             for (alt = rref->alt_link; alt; alt = alt->next)
!               {
!                 if (p->cost[web->regclass] != p->cost[alt->class])
!                   j = may_move_out_cost[mode][web->regclass][alt->class];
!                 else
!                   j = 0;
!                 alt_costs[alt->alt] = (j * 1000 + alt->reject
!                                        + (alt_init_p[alt->alt]
!                                           ? alt_costs[alt->alt] : 0));
!                 alt_init_p[alt->alt] = 1;
!                 alt_freeness[alt->alt] += reg_class_size[alt->class];
!               }
!           }
!       }
!     }
!   for (d = 0; d < info.num_uses; d++)
!     {
!       struct ref *ref = info.uses[d];
!       enum machine_mode mode = GET_MODE (DF_REF_REG (ref));
! 
!       if (REGNO (DF_REF_REAL_REG (ref)) <= FIRST_PSEUDO_REGISTER)
!       continue;
!       
!       rref = DF2RA (df2ra, ref);
!       if (rref)
!       {
!         struct web *web = use2web[DF_REF_ID (ref)];
!         p = &web_costs[web->id];
!           
!         if (rref->alt_link)
!           {
!             struct alt_link *alt;
!             for (alt = rref->alt_link; alt; alt = alt->next)
!               {
!                 if (p->cost[web->regclass] != p->cost[alt->class])
!                   j = may_move_in_cost[mode][alt->class][web->regclass];
!                 else
!                   j = 0;
!                 alt_costs[alt->alt] = (j * 1000 + alt->reject
!                                        + (alt_init_p[alt->alt]
!                                           ? alt_costs[alt->alt] : 0));
!                 alt_init_p[alt->alt] = 1;
!                 alt_freeness[alt->alt] += reg_class_size[alt->class];
!               }
!           }
!       }
!     }  
!   best_alt = 0;
!   best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
!   freeness = 0;
!   for (d = 0; d < MAX_RECOG_ALTERNATIVES; ++d)
!     if (alt_costs[d] <= best_cost && alt_freeness[d] > freeness)
!       {
!       best_cost = alt_costs[d];
!       best_alt = d;
!       freeness = alt_freeness[d];
!       }
!   insn_alternative[INSN_UID (insn)] = best_alt;
! }
! 
! /* Add spill code for refs with wrong reg_class.  */
! static void
! web_class_spill (struct web *web, char *insn_alternative)
  {
    unsigned int i, n, num_refs;
    struct ref *dref;
    struct ref **refs;
    struct ra_ref *rref;
!   enum reg_class class = NO_REGS; /* Initialize to prevent warning.  */
    int spilled_web = 0;
    bitmap already_insn = NULL;
  
!   if (web->num_defs == 0 && web->num_uses == 0)
!     {
!       web->regclass = GENERAL_REGS;
!       COPY_HARD_REG_SET (web->usable_regs, usable_regs[GENERAL_REGS]);
!       return;
!     }
!   COPY_HARD_REG_SET (web->usable_regs, usable_regs[web->regclass]);
! 
!   /* FIXME: denisc@overta.ru  */
!   if (ra_pass != 1)
!     return;
!   
    for (n = 0, refs = web->uses, num_refs = web->num_uses;
         n < 2;
         refs = web->defs, num_refs = web->num_defs, n++)
*************** web_class (web)
*** 3954,4005 ****
        rref = DF2RA (df2ra, dref);
        if (rref)
          {
!           int blocks;
!           enum reg_class c = NO_REGS;
! 
!           if (reg_class_subset_p (rref->class, class))
!             c = rref->class;
!           else if (reg_class_subset_p (class, rref->class))
!             c = class;
!           
!           if (c != NO_REGS)
              {
!               web_size = CLASS_MAX_NREGS (c, PSEUDO_REGNO_MODE (web->regno));
!               blocks = count_long_blocks (usable_regs[c], web_size);
              }
            else
              {
!               blocks = 0;
!               c = class;
!               /* FIXME denisc@overta.ru
!                  I have disabled the `web_class_spill_ref'.  */
!               class = GENERAL_REGS;
!               break;
!             }
!           if (!blocks)
!             {
                web_class_spill_ref (web, dref);
                spilled_web = 1;
                if (!already_insn)
                  already_insn = BITMAP_XMALLOC ();
                bitmap_set_bit (already_insn, INSN_UID (DF_REF_INSN (dref)));
              }
-           else
-             class = c;
          }
        }
    if (spilled_web)
      {
        remove_list (web->dlink, &WEBS(INITIAL));
        put_web (web, SPILLED);
-     }
-   else
-     {
-       /* XXX Ugly hack to suppress repeated spilling tries for such webs.  */
-       if (!class_ok_for_mode (class, PSEUDO_REGNO_MODE (web->regno)))
-       class = GENERAL_REGS;
-       web->regclass = class;
-       COPY_HARD_REG_SET (web->usable_regs, usable_regs[class]);
      }
  
    if (already_insn)
--- 4224,4270 ----
        rref = DF2RA (df2ra, dref);
        if (rref)
          {
!           if (rref->alt_link)
              {
!               struct alt_link *alt;
!               int altno = (insn_alternative
!                            ? insn_alternative[INSN_UID (rref->insn)]
!                            : -2);
!               /* Check for insns without alternatives.  */
!               if (altno == -1)
!                 abort ();
!               
!               for (alt = rref->alt_link; alt; alt = alt->next)
!                 if (altno == alt->alt)
!                   class = alt->class;
              }
            else
+             class = rref->class;
+ 
+           if (!reg_class_subset_p (web->regclass, class))
              {
!               static const char *const reg_class_names[] = REG_CLASS_NAMES;
!               fprintf (stderr, "%s pass: %d Web %d class %s insn class %s\n",
!                        cfun->name, ra_pass,
!                        web->id, reg_class_names[web->regclass],
!                        reg_class_names[class]);
!               fprintf (stderr, "Spill out reg %d from insn:\n",
!                        DF_REF_REGNO (dref));
!               debug_rtx (DF_REF_INSN (dref));
!               
                web_class_spill_ref (web, dref);
                spilled_web = 1;
                if (!already_insn)
                  already_insn = BITMAP_XMALLOC ();
                bitmap_set_bit (already_insn, INSN_UID (DF_REF_INSN (dref)));
              }
          }
        }
+ 
    if (spilled_web)
      {
        remove_list (web->dlink, &WEBS(INITIAL));
        put_web (web, SPILLED);
      }
  
    if (already_insn)
Index: ra-colorize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-colorize.c,v
retrieving revision 1.1.2.19
diff -c -3 -p -r1.1.2.19 ra-colorize.c
*** ra-colorize.c       10 Nov 2003 12:27:41 -0000      1.1.2.19
--- ra-colorize.c       3 Mar 2004 12:00:53 -0000
*************** colorize_one_web (struct web *web, int h
*** 1549,1555 ****
                     becoming recolored higher up in the recursion stack.
                     This would screw up the roll back of the neighbors
                     of _that_ web, when some got a color in between.  */
!                 || bitmap_bit_p (webs_in_recoloring, aw->id))
                continue;
              else
                {
--- 1549,1557 ----
                     becoming recolored higher up in the recursion stack.
                     This would screw up the roll back of the neighbors
                     of _that_ web, when some got a color in between.  */
!                 || bitmap_bit_p (webs_in_recoloring, aw->id)
!                 /* We can't spill dead webs.  */
!                 || find_web_for_subweb (w)->num_uses == 0)
                continue;
              else
                {
Index: ra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.c,v
retrieving revision 1.1.2.76
diff -c -3 -p -r1.1.2.76 ra.c
*** ra.c        29 Oct 2003 13:59:24 -0000      1.1.2.76
--- ra.c        3 Mar 2004 12:00:57 -0000
***************
*** 1,5 ****
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>.
  
--- 1,5 ----
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>.
  
*************** extern int have_splits_p (void);
*** 461,468 ****
  static int
  one_pass (struct df *df, int rebuild)
  {
-   long ticks = clock ();
    int something_spilled;
    remember_conflicts = 0;
  
    /* Build the complete interference graph, or if this is not the first
--- 461,469 ----
  static int
  one_pass (struct df *df, int rebuild)
  {
    int something_spilled;
+   int last_uid = get_max_uid ();
+   long ticks = clock ();
    remember_conflicts = 0;
  
    /* Build the complete interference graph, or if this is not the first
*************** one_pass (struct df *df, int rebuild)
*** 516,522 ****
        detect_web_parts_to_rebuild ();
        last_changed_insns = NULL;
        something_spilled = 1;
!       last_max_uid = get_max_uid ();
      }
    else
      abort ();
--- 517,523 ----
        detect_web_parts_to_rebuild ();
        last_changed_insns = NULL;
        something_spilled = 1;
!       last_max_uid = last_uid;
      }
    else
      abort ();
*************** init_ra (void)
*** 654,659 ****
--- 655,661 ----
        break;
    if (an_unusable_color == FIRST_PSEUDO_REGISTER)
      abort ();
+   init_long_blocks_for_classes ();
    compute_bb_for_insn ();
    ra_reg_renumber = NULL;
    insns_with_deaths = NULL;
Index: ra.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.h,v
retrieving revision 1.1.2.13
diff -c -3 -p -r1.1.2.13 ra.h
*** ra.h        27 Oct 2003 20:00:57 -0000      1.1.2.13
--- ra.h        3 Mar 2004 12:01:02 -0000
***************
*** 1,5 ****
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>.
  
--- 1,5 ----
  /* Graph coloring register allocator
!    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Michael Matz <matz@suse.de>
     and Daniel Berlin <dan@cgsoftware.com>.
  
*************** struct web_part
*** 88,93 ****
--- 88,103 ----
    unsigned int crosses_memset : 1;
  };
  
+ /* The `costs' struct records the cost of using a hard register of each class
+    and of using memory for each pseudo.  We use this data to set up
+    register class preferences.  */
+ 
+ struct costs
+ {
+   int cost[N_REG_CLASSES];
+   int mem_cost;
+ };
+ 
  /* Web structure used to store info about connected live ranges.
     This represents the nodes of the interference graph, which gets
     colored.  It can also hold subwebs, which are contained in webs
*************** extern int subst_to_stack_p (void);
*** 669,674 ****
--- 679,685 ----
  extern int copy_insn_p (rtx ,rtx *,rtx *);
  extern int hard_regs_combinable_p (struct web *,struct web *);
  extern void debug_colorized_spills (void);
+ extern void init_long_blocks_for_classes (void);
  
  #define SPILL_SLOT_P(REGNO) bitmap_bit_p (spill_slot_regs, (REGNO))
  
Index: pre-reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/pre-reload.c,v
retrieving revision 1.1.2.22
diff -c -3 -p -r1.1.2.22 pre-reload.c
*** pre-reload.c        27 Oct 2003 20:00:57 -0000      1.1.2.22
--- pre-reload.c        3 Mar 2004 12:01:03 -0000
***************
*** 1,5 ****
  /* Search an insn for pseudo regs that must be in reg_class and are not.
!    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
     Contributed by Denis Chertykov <denisc@overta.ru>
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Search an insn for pseudo regs that must be in reg_class and are not.
!    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Denis Chertykov <denisc@overta.ru>
  
  This file is part of GNU CC.
*************** Boston, MA 02111-1307, USA.  */
*** 47,52 ****
--- 47,53 ----
  #include "toplev.h"
  #include "except.h"
  #include "df.h"
+ #include "ra.h"
  #include "pre-reload.h"
  
  /* Disable this because i386 port has a strange abort inside it.  */
*************** scan_addr_create_ref (ra_info, loc, scan
*** 2077,2082 ****
--- 2078,2084 ----
    else
      COPY_HARD_REG_SET (ref->hardregs, reg_class_contents[ref->class]);
    ref->constraints = scan_state->constraints;
+   ref->alt_link = NULL;
  
    if (RA_REF_WRITE_P (ref))
      *scan_state->defs++ = ref;
*************** scan_alternative (this_alt, constraints,
*** 2368,2374 ****
            break;
                
          case '*':
!           reject += 4;
            break;
  
          case '%':
--- 2370,2381 ----
            break;
                
          case '*':
!           /* Ignore next constraint because it's reloading.
!              It's not a regclass.  */
!           c = *++p;
!           len = 0;
!           if (c && c != ',')
!             len = CONSTRAINT_LEN (c, p);
            break;
  
          case '%':
*************** scan_alternative (this_alt, constraints,
*** 2389,2401 ****
          case '#':
            /* Ignore rest of this alternative as far as
               reloading is concerned.  */
!           if (match_seen)
!             {
!               do
!                 p++;
!               while (*p && *p != ',');
!               len = 0;
!             }
            break;
  
          case '0':  case '1':  case '2':  case '3':  case '4':
--- 2396,2405 ----
          case '#':
            /* Ignore rest of this alternative as far as
               reloading is concerned.  */
!           do
!             p++;
!           while (*p && *p != ',');
!           len = 0;
            break;
  
          case '0':  case '1':  case '2':  case '3':  case '4':
*************** collect_insn_info (ra_info, insn, def_re
*** 2890,2896 ****
  
    struct alternative_info goal_alt[MAX_RECOG_OPERANDS];
    
-   int goal_alternative_number = 0;
    int operand_reloadnum[MAX_RECOG_OPERANDS];
    int goal_alternative_swapped;
    int best;
--- 2894,2899 ----
*************** collect_insn_info (ra_info, insn, def_re
*** 2899,2912 ****
    int commutative;
    char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
    rtx substed_operand[MAX_RECOG_OPERANDS];
-   rtx set = single_set (insn);
    enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
    int ind_levels = indirect_levels;
    ra_ref **orig_def_refs = def_refs;
    ra_ref **orig_use_refs = use_refs;
  
    *n_defs = 0;
    *n_uses = 0;
    
    extract_insn (insn);
  
--- 2902,2919 ----
    int commutative;
    char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
    rtx substed_operand[MAX_RECOG_OPERANDS];
    enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+   struct alt_link *alt_list[MAX_RECOG_OPERANDS];
+ 
+   rtx set = single_set (insn);
    int ind_levels = indirect_levels;
+   int goal_alternative_number = 0;
    ra_ref **orig_def_refs = def_refs;
    ra_ref **orig_use_refs = use_refs;
  
    *n_defs = 0;
    *n_uses = 0;
+   memset (alt_list, 0, sizeof (alt_list));
    
    extract_insn (insn);
  
*************** collect_insn_info (ra_info, insn, def_re
*** 3134,3140 ****
        int freeness = 0;
        int losers = scan_alternative (this_alt, constraints, modified,
                                     address_reloaded, operands_match,
!                                    swapped, &commutative, &freeness, &reject);
        
        /* If this alternative can be made to work by reloading,
         and it needs less reloading than the others checked so far,
--- 3141,3161 ----
        int freeness = 0;
        int losers = scan_alternative (this_alt, constraints, modified,
                                     address_reloaded, operands_match,
!                                    swapped, &commutative,
!                                    &freeness, &reject);
!       if (losers == 0)
!       for (i = 0; i < noperands; i++)
!         if (this_alt[i].reg
!             && REGNO (this_alt[i].reg) >= FIRST_PSEUDO_REGISTER)
!           {
!             struct alt_link *alt = obstack_alloc (&ra_info->obstack,
!                                                   sizeof (struct alt_link));
!             alt->class = this_alt[i].class;
!             alt->alt = this_alternative_number;
!             alt->reject = reject;
!             alt->next = alt_list[i];
!             alt_list[i] = alt;
!           }
        
        /* If this alternative can be made to work by reloading,
         and it needs less reloading than the others checked so far,
*************** collect_insn_info (ra_info, insn, def_re
*** 3563,3568 ****
--- 3584,3590 ----
              COPY_HARD_REG_SET (ref->hardregs,
                                 reg_class_contents[goal_alt[i].class]);
  
+           ref->alt_link = alt_list[i];
            /* Fields for debugging.  */
            ref->alt = goal_alternative_number;
            ref->constraints = goal_alt[i].constraints;
*************** pre_reload_collect (ra_info, modified)
*** 4467,4504 ****
                bb->end = PREV_INSN (next);
              else
                bb->end = get_last_insn ();
-           }
-       }
-     }
- 
-   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-     {
-       /* FIXME: denisc@overta.ru */
-       if (0)
-       {
-         if (RA_INSN_REFS (ra_info, insn))
-           {
-             debug_rtx (insn);
-             debug_ra_insn_refs (ra_info, insn);
-           }
-         else
-           {
-             enum rtx_code pat_code;
-             enum rtx_code code = GET_CODE (insn);
- 
-             if (GET_RTX_CLASS (code) != 'i')
-               continue;
- 
-             pat_code = GET_CODE (PATTERN (insn));
-             if (pat_code == USE
-                 || pat_code == CLOBBER
-                 || pat_code == ASM_INPUT
-                 || pat_code == ADDR_VEC
-                 || pat_code == ADDR_DIFF_VEC)
-               continue;
- 
-             debug_rtx (insn);
-             fprintf (stderr, "---- NOREFS ----\n");
            }
        }
      }
--- 4489,4494 ----
Index: pre-reload.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/pre-reload.h,v
retrieving revision 1.1.2.8
diff -c -3 -p -r1.1.2.8 pre-reload.h
*** pre-reload.h        8 Jan 2003 00:51:54 -0000       1.1.2.8
--- pre-reload.h        3 Mar 2004 12:01:03 -0000
***************
*** 1,5 ****
  /* Communication between reload.c, reload1.c, pre-reload.c and ra.c.
!    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
     Contributed by Denis Chertykov <denisc@overta.ru>
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Communication between reload.c, reload1.c, pre-reload.c and ra.c.
!    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Denis Chertykov <denisc@overta.ru>
  
  This file is part of GNU CC.
*************** enum ra_ref_type {RA_REF_NONE    = 0,
*** 92,97 ****
--- 92,106 ----
  #define RA_REF_ID(RA_REF)        ((RA_REF)->id)
  #define RA_REF_REGNO(REF)        (REGNO (REG_P ((REF)->reg) ? (REF)->reg : SUBREG_REG ((REF)->reg)))
  
+ /* List of all correct alternatives.  */
+ struct alt_link
+ {
+   struct alt_link *next;
+   ENUM_BITFIELD (reg_class) class:8;
+   unsigned char alt;
+   short reject;
+ };
+ 
  struct ra_ref
  {
    int id;                     /* ra_ref unique identifier */
*************** struct ra_ref
*** 109,114 ****
--- 118,125 ----
    int alt;                    /* selected constraints alternative  */
    enum reg_class class;               /* Register class */
    char *constraints;          /* constraints terminated by ',' or '\0' */
+   struct alt_link *alt_link;  /* Pointer to list of all correct
+                                  alternatives.  */
  };
  
  typedef struct ra_ref ra_ref;



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]