OSDN Git Service

(global_alloc): Make a more accurate attempt to see if the frame pointer will
[pf3gnuchains/gcc-fork.git] / gcc / global.c
index a96d3ef..297e930 100644 (file)
@@ -1,5 +1,5 @@
 /* Allocate registers for pseudo-registers that span basic blocks.
-   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -246,24 +246,24 @@ static struct { int allocno1, allocno2;}
 static rtx *regs_set;
 static int n_regs_set;
 
-/* All register that can be eliminated.  */
+/* All registers that can be eliminated.  */
 
 static HARD_REG_SET eliminable_regset;
 
-static int allocno_compare ();
-static void mark_reg_store ();
-static void mark_reg_clobber ();
-static void mark_reg_conflicts ();
-static void mark_reg_live_nc ();
-static void mark_reg_death ();
-static void dump_conflicts ();
-void dump_global_regs ();
-static void find_reg ();
-static void global_conflicts ();
-static void expand_preferences ();
-static void prune_preferences ();
-static void record_conflicts ();
-static void set_preference ();
+static int allocno_compare     PROTO((int *, int *));
+static void global_conflicts   PROTO((void));
+static void expand_preferences PROTO((void));
+static void prune_preferences  PROTO((void));
+static void find_reg           PROTO((int, HARD_REG_SET, int, int, int));
+static void record_one_conflict PROTO((int));
+static void record_conflicts   PROTO((short *, int));
+static void mark_reg_store     PROTO((rtx, rtx));
+static void mark_reg_clobber   PROTO((rtx, rtx));
+static void mark_reg_conflicts PROTO((rtx));
+static void mark_reg_death     PROTO((rtx));
+static void mark_reg_live_nc   PROTO((int, enum machine_mode));
+static void set_preference     PROTO((rtx, rtx));
+static void dump_conflicts     PROTO((FILE *));
 \f
 /* Perform allocation of pseudo-registers not allocated by local_alloc.
    FILE is a file to output debugging information on,
@@ -279,6 +279,13 @@ global_alloc (file)
 #ifdef ELIMINABLE_REGS
   static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
+  int need_fp
+    = (! flag_omit_frame_pointer
+#ifdef EXIT_IGNORE_STACK
+       || (current_function_calls_alloca && EXIT_IGNORE_STACK)
+#endif
+       || FRAME_POINTER_REQUIRED);
+
   register int i;
   rtx x;
 
@@ -302,16 +309,18 @@ global_alloc (file)
       SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
 
       if (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
-         || (eliminables[i].from == FRAME_POINTER_REGNUM
-             && (! flag_omit_frame_pointer || FRAME_POINTER_REQUIRED)))
+         || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp))
        SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from);
     }
+#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+  SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
+  if (need_fp)
+    SET_HARD_REG_BIT (no_global_alloc_regs, HARD_FRAME_POINTER_REGNUM);
+#endif
+
 #else
   SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
-
-  /* If we know we will definitely not be eliminating the frame pointer,
-     don't allocate it.  */
-  if (! flag_omit_frame_pointer || FRAME_POINTER_REQUIRED)
+  if (need_fp)
     SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM);
 #endif
 
@@ -360,7 +369,7 @@ global_alloc (file)
   /* Initialize the shared-hard-reg mapping
      from the list of pairs that may share.  */
   reg_may_share = (int *) alloca (max_regno * sizeof (int));
-  bzero (reg_may_share, max_regno * sizeof (int));
+  bzero ((char *) reg_may_share, max_regno * sizeof (int));
   for (x = regs_may_share; x; x = XEXP (XEXP (x, 1), 1))
     {
       int r1 = REGNO (XEXP (x, 0));
@@ -396,10 +405,10 @@ global_alloc (file)
   allocno_calls_crossed = (int *) alloca (max_allocno * sizeof (int));
   allocno_n_refs = (int *) alloca (max_allocno * sizeof (int));
   allocno_live_length = (int *) alloca (max_allocno * sizeof (int));
-  bzero (allocno_size, max_allocno * sizeof (int));
-  bzero (allocno_calls_crossed, max_allocno * sizeof (int));
-  bzero (allocno_n_refs, max_allocno * sizeof (int));
-  bzero (allocno_live_length, max_allocno * sizeof (int));
+  bzero ((char *) allocno_size, max_allocno * sizeof (int));
+  bzero ((char *) allocno_calls_crossed, max_allocno * sizeof (int));
+  bzero ((char *) allocno_n_refs, max_allocno * sizeof (int));
+  bzero ((char *) allocno_live_length, max_allocno * sizeof (int));
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_allocno[i] >= 0)
@@ -416,8 +425,8 @@ global_alloc (file)
   /* Calculate amount of usage of each hard reg by pseudos
      allocated by local-alloc.  This is to see if we want to
      override it.  */
-  bzero (local_reg_live_length, sizeof local_reg_live_length);
-  bzero (local_reg_n_refs, sizeof local_reg_n_refs);
+  bzero ((char *) local_reg_live_length, sizeof local_reg_live_length);
+  bzero ((char *) local_reg_n_refs, sizeof local_reg_n_refs);
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_allocno[i] < 0 && reg_renumber[i] >= 0)
       {
@@ -442,30 +451,32 @@ global_alloc (file)
 
   hard_reg_conflicts
     = (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
-  bzero (hard_reg_conflicts, max_allocno * sizeof (HARD_REG_SET));
+  bzero ((char *) hard_reg_conflicts, max_allocno * sizeof (HARD_REG_SET));
 
   hard_reg_preferences
     = (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
-  bzero (hard_reg_preferences, max_allocno * sizeof (HARD_REG_SET));
+  bzero ((char *) hard_reg_preferences, max_allocno * sizeof (HARD_REG_SET));
   
   hard_reg_copy_preferences
     = (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
-  bzero (hard_reg_copy_preferences, max_allocno * sizeof (HARD_REG_SET));
+  bzero ((char *) hard_reg_copy_preferences,
+        max_allocno * sizeof (HARD_REG_SET));
   
   hard_reg_full_preferences
     = (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
-  bzero (hard_reg_full_preferences, max_allocno * sizeof (HARD_REG_SET));
+  bzero ((char *) hard_reg_full_preferences,
+        max_allocno * sizeof (HARD_REG_SET));
   
   regs_someone_prefers
     = (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
-  bzero (regs_someone_prefers, max_allocno * sizeof (HARD_REG_SET));
+  bzero ((char *) regs_someone_prefers, max_allocno * sizeof (HARD_REG_SET));
 
   allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
 
   conflicts = (INT_TYPE *) alloca (max_allocno * allocno_row_words
                                   * sizeof (INT_TYPE));
-  bzero (conflicts, max_allocno * allocno_row_words
-        * sizeof (INT_TYPE));
+  bzero ((char *) conflicts,
+        max_allocno * allocno_row_words * sizeof (INT_TYPE));
 
   allocnos_live = (INT_TYPE *) alloca (allocno_row_words * sizeof (INT_TYPE));
 
@@ -569,12 +580,12 @@ allocno_compare (v1, v2)
      Multiplying this by 10000 can't overflow.  */
   register int pri1
     = (((double) (floor_log2 (allocno_n_refs[*v1]) * allocno_n_refs[*v1])
-       / (allocno_live_length[*v1] * allocno_size[*v1]))
-       * 10000);
+       / allocno_live_length[*v1])
+       * 10000 * allocno_size[*v1]);
   register int pri2
     = (((double) (floor_log2 (allocno_n_refs[*v2]) * allocno_n_refs[*v2])
-       / (allocno_live_length[*v2] * allocno_size[*v2]))
-       * 10000);
+       / allocno_live_length[*v2])
+       * 10000 * allocno_size[*v2]);
   if (pri2 - pri1)
     return pri2 - pri1;
 
@@ -600,7 +611,7 @@ global_conflicts ()
 
   for (b = 0; b < n_basic_blocks; b++)
     {
-      bzero (allocnos_live, allocno_row_words * sizeof (INT_TYPE));
+      bzero ((char *) allocnos_live, allocno_row_words * sizeof (INT_TYPE));
 
       /* Initialize table of registers currently live
         to the state at the beginning of this basic block.
@@ -670,9 +681,9 @@ global_conflicts ()
 
          if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
            {
-             int i = 0;
 
 #if 0
+             int i = 0;
              for (link = REG_NOTES (insn);
                   link && i < NUM_NO_CONFLICT_PAIRS;
                   link = XEXP (link, 1))
@@ -1040,7 +1051,11 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
     }
  no_prefs:
 
-  /* If we haven't succeeded yet, try with caller-saves.  */
+  /* If we haven't succeeded yet, try with caller-saves. 
+     We need not check to see if the current function has nonlocal
+     labels because we don't put any pseudos that are live over calls in
+     registers in that case.  */
+
   if (flag_caller_saves && best_reg < 0)
     {
       /* Did not find a register.  If it would be profitable to
@@ -1071,31 +1086,40 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
     {
       /* Count from the end, to find the least-used ones first.  */
       for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-       if (local_reg_n_refs[i] != 0
-           /* Don't use a reg no good for this pseudo.  */
-           && ! TEST_HARD_REG_BIT (used2, i)
-           && HARD_REGNO_MODE_OK (i, mode)
-           && ((double) local_reg_n_refs[i] / local_reg_live_length[i]
-               < ((double) allocno_n_refs[allocno]
-                  / allocno_live_length[allocno])))
-         {
-           /* Hard reg I was used less in total by local regs
-              than it would be used by this one allocno!  */
-           int k;
-           for (k = 0; k < max_regno; k++)
-             if (reg_renumber[k] >= 0)
-               {
-                 int regno = reg_renumber[k];
-                 int endregno
-                   = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (k));
+       {
+#ifdef REG_ALLOC_ORDER
+         int regno = reg_alloc_order[i];
+#else
+         int regno = i;
+#endif
 
-                 if (i >= regno && i < endregno)
-                   reg_renumber[k] = -1;
-               }
+         if (local_reg_n_refs[regno] != 0
+             /* Don't use a reg no good for this pseudo.  */
+             && ! TEST_HARD_REG_BIT (used2, regno)
+             && HARD_REGNO_MODE_OK (regno, mode)
+             && (((double) local_reg_n_refs[regno]
+                  / local_reg_live_length[regno])
+                 < ((double) allocno_n_refs[allocno]
+                    / allocno_live_length[allocno])))
+           {
+             /* Hard reg REGNO was used less in total by local regs
+                than it would be used by this one allocno!  */
+             int k;
+             for (k = 0; k < max_regno; k++)
+               if (reg_renumber[k] >= 0)
+                 {
+                   int r = reg_renumber[k];
+                   int endregno
+                     = r + HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (k));
 
-           best_reg = i;
-           break;
-         }
+                   if (regno >= r && regno < endregno)
+                     reg_renumber[k] = -1;
+                 }
+
+             best_reg = regno;
+             break;
+           }
+       }
     }
 
   /* Did we find a register?  */