OSDN Git Service

2006-01-26 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / global.c
index bdd3386..2186388 100644 (file)
@@ -36,6 +36,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #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
@@ -95,6 +97,9 @@ struct allocno
   /* 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;
 
@@ -166,7 +171,7 @@ static int *reg_may_share;
 
 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;
@@ -327,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.  */
 
-int
+static int
 global_alloc (FILE *file)
 {
   int retval;
@@ -484,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].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))
@@ -609,12 +616,12 @@ global_alloc (FILE *file)
       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.  */
-  if (n_basic_blocks > 0)
+  if (n_basic_blocks > NUM_FIXED_BLOCKS)
 #endif
     {
       build_insn_chain (get_insns ());
@@ -714,7 +721,7 @@ global_conflicts (void)
        /* 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.
 
@@ -739,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,
-          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;
@@ -1203,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
-        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
+         && allocno[num].throwing_calls_crossed == 0
          && CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
                                     allocno[num].calls_crossed))
        {
@@ -1505,7 +1514,7 @@ mark_reg_store (rtx reg, rtx setter, void *data ATTRIBUTE_UNUSED)
     }
 }
 \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)
@@ -2272,9 +2281,9 @@ set_up_bb_rts_numbers (void)
   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);
 }
@@ -2292,9 +2301,6 @@ rpost_cmp (const void *bb1, const void *bb2)
 /* Temporary bitmap used for live_pavin, live_pavout calculation.  */
 static bitmap temp_bitmap;
 
-DEF_VEC_P(basic_block);
-DEF_VEC_ALLOC_P(basic_block,heap);
-
 /* The function calculates partial register availability according to
    the following equations:
 
@@ -2474,3 +2480,50 @@ make_accurate_live_analysis (void)
     }
   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 */
+};
+