OSDN Git Service

2006-01-26 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / global.c
index 8644817..2186388 100644 (file)
@@ -1,6 +1,6 @@
 /* Allocate registers for pseudo-registers that span basic blocks.
    Copyright (C) 1987, 1988, 1991, 1994, 1996, 1997, 1998,
 /* Allocate registers for pseudo-registers that span basic blocks.
    Copyright (C) 1987, 1988, 1991, 1994, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 
 This file is part of GCC.
 
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
 
 
 #include "config.h"
@@ -36,6 +36,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "reload.h"
 #include "output.h"
 #include "toplev.h"
 #include "reload.h"
 #include "output.h"
 #include "toplev.h"
+#include "tree-pass.h"
+#include "timevar.h"
 
 /* This pass of the compiler performs global register allocation.
    It assigns hard register numbers to all the pseudo registers
 
 /* This pass of the compiler performs global register allocation.
    It assigns hard register numbers to all the pseudo registers
@@ -95,6 +97,9 @@ struct allocno
   /* Number of calls crossed by each allocno.  */
   int calls_crossed;
 
   /* Number of calls crossed by each allocno.  */
   int calls_crossed;
 
+  /* Number of calls that might throw crossed by each allocno.  */
+  int throwing_calls_crossed;
+
   /* Number of refs to each allocno.  */
   int n_refs;
 
   /* Number of refs to each allocno.  */
   int n_refs;
 
@@ -166,7 +171,7 @@ static int *reg_may_share;
 
 static INT_TYPE *conflicts;
 
 
 static INT_TYPE *conflicts;
 
-/* Number of ints require to hold max_allocno bits.
+/* Number of ints required to hold max_allocno bits.
    This is the length of a row in `conflicts'.  */
 
 static int allocno_row_words;
    This is the length of a row in `conflicts'.  */
 
 static int allocno_row_words;
@@ -309,7 +314,6 @@ static void reg_dies (int, enum machine_mode, struct insn_chain *);
 static void allocate_bb_info (void);
 static void free_bb_info (void);
 static bool check_earlyclobber (rtx);
 static void allocate_bb_info (void);
 static void free_bb_info (void);
 static bool check_earlyclobber (rtx);
-static bool regclass_intersect (enum reg_class, enum reg_class);
 static void mark_reg_use_for_earlyclobber_1 (rtx *, void *);
 static int mark_reg_use_for_earlyclobber (rtx *, void *);
 static void calculate_local_reg_bb_info (void);
 static void mark_reg_use_for_earlyclobber_1 (rtx *, void *);
 static int mark_reg_use_for_earlyclobber (rtx *, void *);
 static void calculate_local_reg_bb_info (void);
@@ -328,7 +332,7 @@ static void make_accurate_live_analysis (void);
    Return value is nonzero if reload failed
    and we must not do any more for this function.  */
 
    Return value is nonzero if reload failed
    and we must not do any more for this function.  */
 
-int
+static int
 global_alloc (FILE *file)
 {
   int retval;
 global_alloc (FILE *file)
 {
   int retval;
@@ -485,6 +489,8 @@ global_alloc (FILE *file)
        allocno[num].reg = i;
        allocno[num].size = PSEUDO_REGNO_SIZE (i);
        allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
        allocno[num].reg = i;
        allocno[num].size = PSEUDO_REGNO_SIZE (i);
        allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
+       allocno[num].throwing_calls_crossed
+         += REG_N_THROWING_CALLS_CROSSED (i);
        allocno[num].n_refs += REG_N_REFS (i);
        allocno[num].freq += REG_FREQ (i);
        if (allocno[num].live_length < REG_LIVE_LENGTH (i))
        allocno[num].n_refs += REG_N_REFS (i);
        allocno[num].freq += REG_FREQ (i);
        if (allocno[num].live_length < REG_LIVE_LENGTH (i))
@@ -610,12 +616,12 @@ global_alloc (FILE *file)
       free (allocno_order);
     }
 
       free (allocno_order);
     }
 
-  /* Do the reloads now while the allocno data still exist, so that we can
+  /* Do the reloads now while the allocno data still exists, so that we can
      try to assign new hard regs to any pseudo regs that are spilled.  */
 
 #if 0 /* We need to eliminate regs even if there is no rtl code,
         for the sake of debugging information.  */
      try to assign new hard regs to any pseudo regs that are spilled.  */
 
 #if 0 /* We need to eliminate regs even if there is no rtl code,
         for the sake of debugging information.  */
-  if (n_basic_blocks > 0)
+  if (n_basic_blocks > NUM_FIXED_BLOCKS)
 #endif
     {
       build_insn_chain (get_insns ());
 #endif
     {
       build_insn_chain (get_insns ());
@@ -695,7 +701,7 @@ global_conflicts (void)
         be explicitly marked in basic_block_live_at_start.  */
 
       {
         be explicitly marked in basic_block_live_at_start.  */
 
       {
-       regset old = b->global_live_at_start;
+       regset old = b->il.rtl->global_live_at_start;
        int ax = 0;
        reg_set_iterator rsi;
 
        int ax = 0;
        reg_set_iterator rsi;
 
@@ -715,7 +721,7 @@ global_conflicts (void)
        /* Record that each allocno now live conflicts with each hard reg
           now live.
 
        /* Record that each allocno now live conflicts with each hard reg
           now live.
 
-          It is not necessary to mark any conflicts between pseudos as
+          It is not necessary to mark any conflicts between pseudos at
           this point, even for pseudos which are live at the start of
           the basic block.
 
           this point, even for pseudos which are live at the start of
           the basic block.
 
@@ -740,9 +746,9 @@ global_conflicts (void)
 
        /* Pseudos can't go in stack regs at the start of a basic block that
           is reached by an abnormal edge. Likewise for call clobbered regs,
 
        /* Pseudos can't go in stack regs at the start of a basic block that
           is reached by an abnormal edge. Likewise for call clobbered regs,
-          because because caller-save, fixup_abnormal_edges, and possibly
-          the table driven EH machinery are not quite ready to handle such
-          regs live across such edges.  */
+          because caller-save, fixup_abnormal_edges and possibly the table
+          driven EH machinery are not quite ready to handle such regs live
+          across such edges.  */
        {
          edge e;
          edge_iterator ei;
        {
          edge e;
          edge_iterator ei;
@@ -1204,9 +1210,11 @@ find_reg (int num, HARD_REG_SET losers, int alt_regs_p, int accept_call_clobbere
     {
       /* Did not find a register.  If it would be profitable to
         allocate a call-clobbered register and save and restore it
     {
       /* Did not find a register.  If it would be profitable to
         allocate a call-clobbered register and save and restore it
-        around calls, do that.  */
+        around calls, do that.  Don't do this if it crosses any calls
+        that might throw.  */
       if (! accept_call_clobbered
          && allocno[num].calls_crossed != 0
       if (! accept_call_clobbered
          && allocno[num].calls_crossed != 0
+         && allocno[num].throwing_calls_crossed == 0
          && CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
                                     allocno[num].calls_crossed))
        {
          && CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
                                     allocno[num].calls_crossed))
        {
@@ -1506,7 +1514,7 @@ mark_reg_store (rtx reg, rtx setter, void *data ATTRIBUTE_UNUSED)
     }
 }
 \f
     }
 }
 \f
-/* Like mark_reg_set except notice just CLOBBERs; ignore SETs.  */
+/* Like mark_reg_store except notice just CLOBBERs; ignore SETs.  */
 
 static void
 mark_reg_clobber (rtx reg, rtx setter, void *data)
 
 static void
 mark_reg_clobber (rtx reg, rtx setter, void *data)
@@ -1727,7 +1735,7 @@ mark_elimination (int from, int to)
 
   FOR_EACH_BB (bb)
     {
 
   FOR_EACH_BB (bb)
     {
-      regset r = bb->global_live_at_start;
+      regset r = bb->il.rtl->global_live_at_start;
       if (REGNO_REG_SET_P (r, from))
        {
          CLEAR_REGNO_REG_SET (r, from);
       if (REGNO_REG_SET_P (r, from))
        {
          CLEAR_REGNO_REG_SET (r, from);
@@ -1817,7 +1825,7 @@ build_insn_chain (rtx first)
 
          CLEAR_REG_SET (live_relevant_regs);
 
 
          CLEAR_REG_SET (live_relevant_regs);
 
-         EXECUTE_IF_SET_IN_BITMAP (b->global_live_at_start, 0, i, bi)
+         EXECUTE_IF_SET_IN_BITMAP (b->il.rtl->global_live_at_start, 0, i, bi)
            {
              if (i < FIRST_PSEUDO_REGISTER
                  ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
            {
              if (i < FIRST_PSEUDO_REGISTER
                  ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
@@ -2011,7 +2019,7 @@ struct bb_info
      killed afterward in the basic block.  */
   bitmap killed, avloc;
   /* Registers partially available and living (in other words whose
      killed afterward in the basic block.  */
   bitmap killed, avloc;
   /* Registers partially available and living (in other words whose
-     values were calclualted and used) correspondingly at the start
+     values were calculated and used) correspondingly at the start
      and end of the basic block.  */
   bitmap live_pavin, live_pavout;
 };
      and end of the basic block.  */
   bitmap live_pavin, live_pavout;
 };
@@ -2034,21 +2042,21 @@ allocate_bb_info (void)
   bitmap init;
 
   alloc_aux_for_blocks (sizeof (struct bb_info));
   bitmap init;
 
   alloc_aux_for_blocks (sizeof (struct bb_info));
-  init = BITMAP_XMALLOC ();
+  init = BITMAP_ALLOC (NULL);
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     bitmap_set_bit (init, i);
   FOR_EACH_BB (bb)
     {
       bb_info = bb->aux;
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     bitmap_set_bit (init, i);
   FOR_EACH_BB (bb)
     {
       bb_info = bb->aux;
-      bb_info->earlyclobber = BITMAP_XMALLOC ();
-      bb_info->avloc = BITMAP_XMALLOC ();
-      bb_info->killed = BITMAP_XMALLOC ();
-      bb_info->live_pavin = BITMAP_XMALLOC ();
-      bb_info->live_pavout = BITMAP_XMALLOC ();
+      bb_info->earlyclobber = BITMAP_ALLOC (NULL);
+      bb_info->avloc = BITMAP_ALLOC (NULL);
+      bb_info->killed = BITMAP_ALLOC (NULL);
+      bb_info->live_pavin = BITMAP_ALLOC (NULL);
+      bb_info->live_pavout = BITMAP_ALLOC (NULL);
       bitmap_copy (bb_info->live_pavin, init);
       bitmap_copy (bb_info->live_pavout, init);
     }
       bitmap_copy (bb_info->live_pavin, init);
       bitmap_copy (bb_info->live_pavout, init);
     }
-  BITMAP_XFREE (init);
+  BITMAP_FREE (init);
 }
 
 /* The function frees the allocated info of all basic blocks.  */
 }
 
 /* The function frees the allocated info of all basic blocks.  */
@@ -2062,11 +2070,11 @@ free_bb_info (void)
   FOR_EACH_BB (bb)
     {
       bb_info = BB_INFO (bb);
   FOR_EACH_BB (bb)
     {
       bb_info = BB_INFO (bb);
-      BITMAP_XFREE (bb_info->live_pavout);
-      BITMAP_XFREE (bb_info->live_pavin);
-      BITMAP_XFREE (bb_info->killed);
-      BITMAP_XFREE (bb_info->avloc);
-      BITMAP_XFREE (bb_info->earlyclobber);
+      BITMAP_FREE (bb_info->live_pavout);
+      BITMAP_FREE (bb_info->live_pavin);
+      BITMAP_FREE (bb_info->killed);
+      BITMAP_FREE (bb_info->avloc);
+      BITMAP_FREE (bb_info->earlyclobber);
     }
   free_aux_for_blocks ();
 }
     }
   free_aux_for_blocks ();
 }
@@ -2099,7 +2107,10 @@ mark_reg_change (rtx reg, rtx setter, void *data)
 /* Classes of registers which could be early clobbered in the current
    insn.  */
 
 /* Classes of registers which could be early clobbered in the current
    insn.  */
 
-static varray_type earlyclobber_regclass;
+DEF_VEC_I(int);
+DEF_VEC_ALLOC_I(int,heap);
+
+static VEC(int,heap) *earlyclobber_regclass;
 
 /* This function finds and stores register classes that could be early
    clobbered in INSN.  If any earlyclobber classes are found, the function
 
 /* This function finds and stores register classes that could be early
    clobbered in INSN.  If any earlyclobber classes are found, the function
@@ -2113,7 +2124,7 @@ check_earlyclobber (rtx insn)
 
   extract_insn (insn);
 
 
   extract_insn (insn);
 
-  VARRAY_POP_ALL (earlyclobber_regclass);
+  VEC_truncate (int, earlyclobber_regclass, 0);
   for (opno = 0; opno < recog_data.n_operands; opno++)
     {
       char c;
   for (opno = 0; opno < recog_data.n_operands; opno++)
     {
       char c;
@@ -2150,13 +2161,23 @@ check_earlyclobber (rtx insn)
            case ',':
              if (amp_p && class != NO_REGS)
                {
            case ',':
              if (amp_p && class != NO_REGS)
                {
+                 int rc;
+
                  found = true;
                  found = true;
-                 for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1;
-                      i >= 0; i--)
-                   if (VARRAY_INT (earlyclobber_regclass, i) == (int) class)
-                     break;
-                 if (i < 0)
-                   VARRAY_PUSH_INT (earlyclobber_regclass, (int) class);
+                 for (i = 0;
+                      VEC_iterate (int, earlyclobber_regclass, i, rc);
+                      i++)
+                   {
+                     if (rc == (int) class)
+                       goto found_rc;
+                   }
+
+                 /* We use VEC_quick_push here because
+                    earlyclobber_regclass holds no more than
+                    N_REG_CLASSES elements. */
+                 VEC_quick_push (int, earlyclobber_regclass, (int) class);
+               found_rc:
+                 ;
                }
              
              amp_p = false;
                }
              
              amp_p = false;
@@ -2180,22 +2201,6 @@ check_earlyclobber (rtx insn)
   return found;
 }
 
   return found;
 }
 
-/* The function returns true if register classes C1 and C2 intersect.  */
-
-static bool
-regclass_intersect (enum reg_class c1, enum reg_class c2)
-{
-  HARD_REG_SET rs, zero;
-
-  CLEAR_HARD_REG_SET (zero);
-  COPY_HARD_REG_SET(rs, reg_class_contents [c1]);
-  AND_HARD_REG_SET (rs, reg_class_contents [c2]);
-  GO_IF_HARD_REG_EQUAL (zero, rs, yes);
-  return true;
- yes:
-  return false;
-}
-
 /* The function checks that pseudo-register *X has a class
    intersecting with the class of pseudo-register could be early
    clobbered in the same insn.
 /* The function checks that pseudo-register *X has a class
    intersecting with the class of pseudo-register could be early
    clobbered in the same insn.
@@ -2209,24 +2214,26 @@ mark_reg_use_for_earlyclobber (rtx *x, void *data ATTRIBUTE_UNUSED)
   basic_block bb = data;
   struct bb_info *bb_info = BB_INFO (bb);
 
   basic_block bb = data;
   struct bb_info *bb_info = BB_INFO (bb);
 
-  if (GET_CODE (*x) == REG && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
+  if (REG_P (*x) && REGNO (*x) >= FIRST_PSEUDO_REGISTER)
     {
     {
+      int rc;
+
       regno = REGNO (*x);
       if (bitmap_bit_p (bb_info->killed, regno)
          || bitmap_bit_p (bb_info->avloc, regno))
        return 0;
       pref_class = reg_preferred_class (regno);
       alt_class = reg_alternate_class (regno);
       regno = REGNO (*x);
       if (bitmap_bit_p (bb_info->killed, regno)
          || bitmap_bit_p (bb_info->avloc, regno))
        return 0;
       pref_class = reg_preferred_class (regno);
       alt_class = reg_alternate_class (regno);
-      for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1; i >= 0; i--)
-       if (regclass_intersect (VARRAY_INT (earlyclobber_regclass, i),
-                               pref_class)
-           || (VARRAY_INT (earlyclobber_regclass, i) != NO_REGS
-               && regclass_intersect (VARRAY_INT (earlyclobber_regclass, i),
-                                      alt_class)))
-         {
-           bitmap_set_bit (bb_info->earlyclobber, regno);
-           break;
-         }
+      for (i = 0; VEC_iterate (int, earlyclobber_regclass, i, rc); i++)
+       {
+         if (reg_classes_intersect_p (rc, pref_class)
+             || (rc != NO_REGS
+                 && reg_classes_intersect_p (rc, alt_class)))
+           {
+             bitmap_set_bit (bb_info->earlyclobber, regno);
+             break;
+           }
+       }
     }
   return 0;
 }
     }
   return 0;
 }
@@ -2248,8 +2255,9 @@ calculate_local_reg_bb_info (void)
   basic_block bb;
   rtx insn, bound;
 
   basic_block bb;
   rtx insn, bound;
 
-  VARRAY_INT_INIT (earlyclobber_regclass, 20,
-                  "classes of registers early clobbered in an insn");
+  /* We know that earlyclobber_regclass holds no more than
+    N_REG_CLASSES elements.  See check_earlyclobber.  */
+  earlyclobber_regclass = VEC_alloc (int, heap, N_REG_CLASSES);
   FOR_EACH_BB (bb)
     {
       bound = NEXT_INSN (BB_END (bb));
   FOR_EACH_BB (bb)
     {
       bound = NEXT_INSN (BB_END (bb));
@@ -2261,6 +2269,7 @@ calculate_local_reg_bb_info (void)
              note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
          }
     }
              note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
          }
     }
+  VEC_free (int, heap, earlyclobber_regclass);
 }
 
 /* The function sets up reverse post-order number of each basic
 }
 
 /* The function sets up reverse post-order number of each basic
@@ -2272,9 +2281,9 @@ set_up_bb_rts_numbers (void)
   int i;
   int *rts_order;
   
   int i;
   int *rts_order;
   
-  rts_order = xmalloc (sizeof (int) * n_basic_blocks);
-  flow_reverse_top_sort_order_compute (rts_order);
-  for (i = 0; i < n_basic_blocks; i++)
+  rts_order = xmalloc (sizeof (int) * (n_basic_blocks - NUM_FIXED_BLOCKS));
+  post_order_compute (rts_order, false);
+  for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
     BB_INFO_BY_INDEX (rts_order [i])->rts_number = i;
   free (rts_order);
 }
     BB_INFO_BY_INDEX (rts_order [i])->rts_number = i;
   free (rts_order);
 }
@@ -2307,22 +2316,22 @@ calculate_reg_pav (void)
   basic_block bb, succ;
   edge e;
   int i, nel;
   basic_block bb, succ;
   edge e;
   int i, nel;
-  varray_type bbs, new_bbs, temp;
+  VEC(basic_block,heap) *bbs, *new_bbs, *temp;
   basic_block *bb_array;
   sbitmap wset;
 
   basic_block *bb_array;
   sbitmap wset;
 
-  VARRAY_BB_INIT (bbs, n_basic_blocks, "basic blocks");
-  VARRAY_BB_INIT (new_bbs, n_basic_blocks, "basic blocks for the next iter.");
-  temp_bitmap = BITMAP_XMALLOC ();
+  bbs = VEC_alloc (basic_block, heap, n_basic_blocks);
+  new_bbs = VEC_alloc (basic_block, heap, n_basic_blocks);
+  temp_bitmap = BITMAP_ALLOC (NULL);
   FOR_EACH_BB (bb)
     {
   FOR_EACH_BB (bb)
     {
-      VARRAY_PUSH_BB (bbs, bb);
+      VEC_quick_push (basic_block, bbs, bb);
     }
   wset = sbitmap_alloc (n_basic_blocks + 1);
     }
   wset = sbitmap_alloc (n_basic_blocks + 1);
-  while (VARRAY_ACTIVE_SIZE (bbs))
+  while (VEC_length (basic_block, bbs))
     {
     {
-      bb_array = &VARRAY_BB (bbs, 0);
-      nel = VARRAY_ACTIVE_SIZE (bbs);
+      bb_array = VEC_address (basic_block, bbs);
+      nel = VEC_length (basic_block, bbs);
       qsort (bb_array, nel, sizeof (basic_block), rpost_cmp);
       sbitmap_zero (wset);
       for (i = 0; i < nel; i++)
       qsort (bb_array, nel, sizeof (basic_block), rpost_cmp);
       sbitmap_zero (wset);
       for (i = 0; i < nel; i++)
@@ -2342,10 +2351,10 @@ calculate_reg_pav (void)
              if (pred->index != ENTRY_BLOCK)
                bitmap_ior_into (bb_live_pavin, BB_INFO (pred)->live_pavout);
            }
              if (pred->index != ENTRY_BLOCK)
                bitmap_ior_into (bb_live_pavin, BB_INFO (pred)->live_pavout);
            }
-         bitmap_and_into (bb_live_pavin, bb->global_live_at_start);
+         bitmap_and_into (bb_live_pavin, bb->il.rtl->global_live_at_start);
          bitmap_ior_and_compl (temp_bitmap, bb_info->avloc,
                                bb_live_pavin, bb_info->killed);
          bitmap_ior_and_compl (temp_bitmap, bb_info->avloc,
                                bb_live_pavin, bb_info->killed);
-         bitmap_and_into (temp_bitmap, bb->global_live_at_end);
+         bitmap_and_into (temp_bitmap, bb->il.rtl->global_live_at_end);
          if (! bitmap_equal_p (temp_bitmap, bb_live_pavout))
            {
              bitmap_copy (bb_live_pavout, temp_bitmap);
          if (! bitmap_equal_p (temp_bitmap, bb_live_pavout))
            {
              bitmap_copy (bb_live_pavout, temp_bitmap);
@@ -2356,7 +2365,7 @@ calculate_reg_pav (void)
                      && !TEST_BIT (wset, succ->index))
                    {
                      SET_BIT (wset, succ->index);
                      && !TEST_BIT (wset, succ->index))
                    {
                      SET_BIT (wset, succ->index);
-                     VARRAY_PUSH_BB (new_bbs, succ);
+                     VEC_quick_push (basic_block, new_bbs, succ);
                    }
                }
            }
                    }
                }
            }
@@ -2364,10 +2373,12 @@ calculate_reg_pav (void)
       temp = bbs;
       bbs = new_bbs;
       new_bbs = temp;
       temp = bbs;
       bbs = new_bbs;
       new_bbs = temp;
-      VARRAY_POP_ALL (new_bbs);
+      VEC_truncate (basic_block, new_bbs, 0);
     }
   sbitmap_free (wset);
     }
   sbitmap_free (wset);
-  BITMAP_XFREE (temp_bitmap);
+  BITMAP_FREE (temp_bitmap);
+  VEC_free (basic_block, heap, new_bbs);
+  VEC_free (basic_block, heap, bbs);
 }
 
 /* The function modifies partial availability information for two
 }
 
 /* The function modifies partial availability information for two
@@ -2389,7 +2400,7 @@ modify_reg_pav (void)
   CLEAR_HARD_REG_SET (stack_hard_regs);
   for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
     SET_HARD_REG_BIT(stack_hard_regs, i);
   CLEAR_HARD_REG_SET (stack_hard_regs);
   for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
     SET_HARD_REG_BIT(stack_hard_regs, i);
-  stack_regs = BITMAP_XMALLOC ();
+  stack_regs = BITMAP_ALLOC (NULL);
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
       COPY_HARD_REG_SET (used, reg_class_contents[reg_preferred_class (i)]);
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
       COPY_HARD_REG_SET (used, reg_class_contents[reg_preferred_class (i)]);
@@ -2421,7 +2432,7 @@ modify_reg_pav (void)
 #endif
     }
 #ifdef STACK_REGS
 #endif
     }
 #ifdef STACK_REGS
-  BITMAP_XFREE (stack_regs);
+  BITMAP_FREE (stack_regs);
 #endif
 }
 
 #endif
 }
 
@@ -2464,8 +2475,55 @@ make_accurate_live_analysis (void)
     {
       bb_info = BB_INFO (bb);
       
     {
       bb_info = BB_INFO (bb);
       
-      bitmap_and_into (bb->global_live_at_start, bb_info->live_pavin);
-      bitmap_and_into (bb->global_live_at_end, bb_info->live_pavout);
+      bitmap_and_into (bb->il.rtl->global_live_at_start, bb_info->live_pavin);
+      bitmap_and_into (bb->il.rtl->global_live_at_end, bb_info->live_pavout);
     }
   free_bb_info ();
 }
     }
   free_bb_info ();
 }
+/* Run old register allocator.  Return TRUE if we must exit
+   rest_of_compilation upon return.  */
+static void
+rest_of_handle_global_alloc (void)
+{
+  bool failure;
+
+  /* If optimizing, allocate remaining pseudo-regs.  Do the reload
+     pass fixing up any insns that are invalid.  */
+
+  if (optimize)
+    failure = global_alloc (dump_file);
+  else
+    {
+      build_insn_chain (get_insns ());
+      failure = reload (get_insns (), 0);
+    }
+
+  if (dump_enabled_p (pass_global_alloc.static_pass_number))
+    {
+      timevar_push (TV_DUMP);
+      dump_global_regs (dump_file);
+      timevar_pop (TV_DUMP);
+    }
+
+  gcc_assert (reload_completed || failure);
+  reload_completed = !failure;
+}
+
+struct tree_opt_pass pass_global_alloc =
+{
+  "greg",                               /* name */
+  NULL,                                 /* gate */
+  rest_of_handle_global_alloc,          /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_GLOBAL_ALLOC,                      /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  'g'                                   /* letter */
+};
+