OSDN Git Service

* doc/cppopts.texi: Remove documentation of -A-.
[pf3gnuchains/gcc-fork.git] / gcc / global.c
index a460755..b35777e 100644 (file)
@@ -1,6 +1,6 @@
 /* Allocate registers for pseudo-registers that span basic blocks.
    Copyright (C) 1987, 1988, 1991, 1994, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,6 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "machmode.h"
 #include "hard-reg-set.h"
@@ -52,7 +54,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    1. Assign allocation-numbers (allocnos) to the pseudo-registers
    still needing allocations and to the pseudo-registers currently
    allocated by local-alloc which may be spilled by reload.
-   Set up tables reg_allocno and allocno_reg to map 
+   Set up tables reg_allocno and allocno_reg to map
    reg numbers to allocnos and vice versa.
    max_allocno gets the number of allocnos in use.
 
@@ -130,6 +132,11 @@ struct allocno
   /* Set of hard registers that some later allocno has a preference for.  */
 
   HARD_REG_SET regs_someone_prefers;
+
+#ifdef STACK_REGS
+  /* Set to true if allocno can't be allocated in the stack register.  */
+  bool no_stack_reg;
+#endif
 };
 
 static struct allocno *allocno;
@@ -168,12 +175,8 @@ static int allocno_row_words;
 /* Two macros to test or store 1 in an element of `conflicts'.  */
 
 #define CONFLICTP(I, J) \
- (conflicts[(I) * allocno_row_words + (unsigned)(J) / INT_BITS]        \
-  & ((INT_TYPE) 1 << ((unsigned)(J) % INT_BITS)))
-
-#define SET_CONFLICT(I, J) \
- (conflicts[(I) * allocno_row_words + (unsigned)(J) / INT_BITS]        \
-  |= ((INT_TYPE) 1 << ((unsigned)(J) % INT_BITS)))
+ (conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS]       \
+  & ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
 
 /* For any allocno set in ALLOCNO_SET, set ALLOCNO to that allocno,
    and execute CODE.  */
@@ -231,12 +234,8 @@ static int local_reg_freq[FIRST_PSEUDO_REGISTER];
 
 static int local_reg_live_length[FIRST_PSEUDO_REGISTER];
 
-/* Test a bit in TABLE, a vector of HARD_REG_SETs,
-   for vector element I, and hard register number J.  */
-
-#define REGBITP(TABLE, I, J)     TEST_HARD_REG_BIT (allocno[I].TABLE, J)
-
-/* Set to 1 a bit in a vector of HARD_REG_SETs.  Works like REGBITP.  */
+/* Set to 1 a bit in a vector TABLE of HARD_REG_SETs, for vector
+   element I, and hard register number J.  */
 
 #define SET_REGBIT(TABLE, I, J)  SET_HARD_REG_BIT (allocno[I].TABLE, J)
 
@@ -247,17 +246,13 @@ static INT_TYPE *allocnos_live;
 /* Test, set or clear bit number I in allocnos_live,
    a bit vector indexed by allocno.  */
 
-#define ALLOCNO_LIVE_P(I)                              \
-  (allocnos_live[(unsigned)(I) / INT_BITS]             \
-   & ((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
-
 #define SET_ALLOCNO_LIVE(I)                            \
-  (allocnos_live[(unsigned)(I) / INT_BITS]             \
-     |= ((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
+  (allocnos_live[(unsigned) (I) / INT_BITS]            \
+     |= ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
 
 #define CLEAR_ALLOCNO_LIVE(I)                          \
-  (allocnos_live[(unsigned)(I) / INT_BITS]             \
-     &= ~((INT_TYPE) 1 << ((unsigned)(I) % INT_BITS)))
+  (allocnos_live[(unsigned) (I) / INT_BITS]            \
+     &= ~((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
 
 /* This is turned off because it doesn't work right for DImode.
    (And it is only used for DImode, so the other cases are worthless.)
@@ -379,8 +374,8 @@ global_alloc (file)
      that need a register window.  So prefer the ones that can be used in
      a leaf function.  */
   {
-    char *cheap_regs;
-    char *leaf_regs = LEAF_REGISTERS;
+    const char *cheap_regs;
+    const char *const leaf_regs = LEAF_REGISTERS;
 
     if (only_leaf_regs_used () && leaf_function_p ())
       cheap_regs = leaf_regs;
@@ -483,7 +478,7 @@ global_alloc (file)
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (regs_ever_live[i])
       local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
-       
+
   allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
 
   /* We used to use alloca here, but the size of what it would try to
@@ -549,7 +544,7 @@ global_alloc (file)
        }
 
       qsort (allocno_order, max_allocno, sizeof (int), allocno_compare);
-      
+
       prune_preferences ();
 
       if (file)
@@ -636,7 +631,8 @@ allocno_compare (v1p, v2p)
 static void
 global_conflicts ()
 {
-  int b, i;
+  int i;
+  basic_block b;
   rtx insn;
   int *block_start_allocnos;
 
@@ -645,7 +641,7 @@ global_conflicts ()
 
   block_start_allocnos = (int *) xmalloc (max_allocno * sizeof (int));
 
-  for (b = 0; b < n_basic_blocks; b++)
+  FOR_EACH_BB (b)
     {
       memset ((char *) allocnos_live, 0, allocno_row_words * sizeof (INT_TYPE));
 
@@ -664,7 +660,7 @@ global_conflicts ()
         are explicitly marked in basic_block_live_at_start.  */
 
       {
-       regset old = BASIC_BLOCK (b)->global_live_at_start;
+       regset old = b->global_live_at_start;
        int ax = 0;
 
        REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
@@ -699,7 +695,7 @@ global_conflicts ()
                2. Y is live at some instruction on the path that
                   evaluates X.
 
-               3. Either X or Y is not evaluted on the path to P
+               3. Either X or Y is not evaluated on the path to P
                   (ie it is used uninitialized) and thus the
                   conflict can be ignored.
 
@@ -713,17 +709,23 @@ global_conflicts ()
             that is reached by an abnormal edge.  */
 
          edge e;
-         for (e = BASIC_BLOCK (b)->pred; e ; e = e->pred_next)
+         for (e = b->pred; e ; e = e->pred_next)
            if (e->flags & EDGE_ABNORMAL)
              break;
          if (e != NULL)
-           for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
-             record_one_conflict (ax);
+           {
+             EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, ax,
+               {
+                 allocno[ax].no_stack_reg = 1;
+               });
+             for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
+               record_one_conflict (ax);
+           }
        }
 #endif
       }
 
-      insn = BLOCK_HEAD (b);
+      insn = b->head;
 
       /* Scan the code of this basic block, noting which allocnos
         and hard regs are born or die.  When one is born,
@@ -823,7 +825,7 @@ global_conflicts ()
                }
            }
 
-         if (insn == BLOCK_END (b))
+         if (insn == b->end)
            break;
          insn = NEXT_INSN (insn);
        }
@@ -883,18 +885,18 @@ expand_preferences ()
 \f
 /* Prune the preferences for global registers to exclude registers that cannot
    be used.
-   
+
    Compute `regs_someone_prefers', which is a bitmask of the hard registers
    that are preferred by conflicting registers of lower priority.  If possible,
    we will avoid using these registers.  */
-   
+
 static void
 prune_preferences ()
 {
   int i;
   int num;
   int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
-  
+
   /* Scan least most important to most important.
      For each allocno, remove from preferences registers that cannot be used,
      either because of conflicts or register type.  Then compute all registers
@@ -962,7 +964,7 @@ prune_preferences ()
    of a long enough stretch of hard regs none of which conflicts with ALLOCNO.
    The registers marked in PREFREGS are tried first.
 
-   LOSERS, if non-zero, is a HARD_REG_SET indicating registers that cannot
+   LOSERS, if nonzero, is a HARD_REG_SET indicating registers that cannot
    be used for this allocation.
 
    If ALT_REGS_P is zero, consider only the preferred class of ALLOCNO's reg.
@@ -985,10 +987,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
      int retrying;
 {
   int i, best_reg, pass;
-#ifdef HARD_REG_SET
-  register             /* Declare it register if it's a scalar.  */
-#endif
-    HARD_REG_SET used, used1, used2;
+  HARD_REG_SET used, used1, used2;
 
   enum reg_class class = (alt_regs_p
                          ? reg_alternate_class (allocno[num].reg)
@@ -1012,10 +1011,8 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
 
   IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
-  if (REG_CHANGES_MODE (allocno[num].reg))
-    IOR_HARD_REG_SET (used1,
-                     reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
 #endif
 
   /* Try each hard reg to see if it fits.  Do this in two passes.
@@ -1027,7 +1024,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
   COPY_HARD_REG_SET (used, used1);
   IOR_COMPL_HARD_REG_SET (used, regs_used_so_far);
   IOR_HARD_REG_SET (used, allocno[num].regs_someone_prefers);
-  
+
   best_reg = -1;
   for (i = FIRST_PSEUDO_REGISTER, pass = 0;
        pass <= 1 && i >= FIRST_PSEUDO_REGISTER;
@@ -1072,7 +1069,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
 
      Remove from the preferred registers and conflicting registers.  Note that
      additional conflicts may have been added after `prune_preferences' was
-     called. 
+     called.
 
      First do this for those register with copy preferences, then all
      preferred registers.  */
@@ -1086,6 +1083,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (TEST_HARD_REG_BIT (allocno[num].hard_reg_copy_preferences, i)
            && HARD_REGNO_MODE_OK (i, mode)
+           && (allocno[num].calls_crossed == 0
+               || accept_call_clobbered
+               || ! HARD_REGNO_CALL_PART_CLOBBERED (i, mode))
            && (REGNO_REG_CLASS (i) == REGNO_REG_CLASS (best_reg)
                || reg_class_subset_p (REGNO_REG_CLASS (i),
                                       REGNO_REG_CLASS (best_reg))
@@ -1122,6 +1122,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (TEST_HARD_REG_BIT (allocno[num].hard_reg_preferences, i)
            && HARD_REGNO_MODE_OK (i, mode)
+           && (allocno[num].calls_crossed == 0
+               || accept_call_clobbered
+               || ! HARD_REGNO_CALL_PART_CLOBBERED (i, mode))
            && (REGNO_REG_CLASS (i) == REGNO_REG_CLASS (best_reg)
                || reg_class_subset_p (REGNO_REG_CLASS (i),
                                       REGNO_REG_CLASS (best_reg))
@@ -1149,7 +1152,7 @@ find_reg (num, 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.  */
@@ -1169,7 +1172,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
            CLEAR_HARD_REG_SET (new_losers);
          else
            COPY_HARD_REG_SET (new_losers, losers);
-           
+
          IOR_HARD_REG_SET(new_losers, losing_caller_save_reg_set);
          find_reg (num, new_losers, alt_regs_p, 1, retrying);
          if (reg_renumber[allocno[num].reg] >= 0)
@@ -1202,18 +1205,28 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
              /* Don't use a reg no good for this pseudo.  */
              && ! TEST_HARD_REG_BIT (used2, regno)
              && HARD_REGNO_MODE_OK (regno, mode)
-#ifdef CLASS_CANNOT_CHANGE_MODE
-             && ! (REG_CHANGES_MODE (allocno[num].reg)
-                   && (TEST_HARD_REG_BIT
-                       (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                        regno)))
+             /* The code below assumes that we need only a single
+                register, but the check of allocno[num].size above
+                was not enough.  Sometimes we need more than one
+                register for a single-word value.  */
+             && HARD_REGNO_NREGS (regno, mode) == 1
+             && (allocno[num].calls_crossed == 0
+                 || accept_call_clobbered
+                 || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+             && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
+                                         mode)
+#endif
+#ifdef STACK_REGS
+            && (!allocno[num].no_stack_reg
+                || regno < FIRST_STACK_REG || regno > LAST_STACK_REG)
 #endif
              )
            {
              /* We explicitly evaluate the divide results into temporary
                 variables so as to avoid excess precision problems that occur
                 on an i386-unknown-sysv4.2 (unixware) host.  */
-                
+
              double tmp1 = ((double) local_reg_freq[regno]
                            / local_reg_live_length[regno]);
              double tmp2 = ((double) allocno[num].freq
@@ -1367,15 +1380,9 @@ record_conflicts (allocno_vec, len)
      int *allocno_vec;
      int len;
 {
-  int num;
-  int ialloc_prod;
-
   while (--len >= 0)
-    {
-      num = allocno_vec[len];
-      ialloc_prod = num * allocno_row_words;
-      IOR_HARD_REG_SET (allocno[num].hard_reg_conflicts, hard_regs_live);
-    }
+    IOR_HARD_REG_SET (allocno[allocno_vec[len]].hard_reg_conflicts,
+                      hard_regs_live);
 }
 
 /* If CONFLICTP (i, j) is true, make sure CONFLICTP (j, i) is also true.  */
@@ -1583,7 +1590,7 @@ mark_reg_live_nc (regno, mode)
    that SRC is a register.  If SRC or the first operand of SRC is a register,
    try to set a preference.  If one of the two is a hard register and the other
    is a pseudo-register, mark the preference.
-   
+
    Note that we are not as aggressive as local-alloc in trying to tie a
    pseudo-register to a hard register.  */
 
@@ -1699,11 +1706,11 @@ void
 mark_elimination (from, to)
      int from, to;
 {
-  int i;
+  basic_block bb;
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_EACH_BB (bb)
     {
-      regset r = BASIC_BLOCK (i)->global_live_at_start; 
+      regset r = bb->global_live_at_start;
       if (REGNO_REG_SET_P (r, from))
        {
          CLEAR_REGNO_REG_SET (r, from);
@@ -1731,7 +1738,7 @@ reg_becomes_live (reg, setter, regs_set)
 
   if (GET_CODE (reg) != REG)
     return;
-  
+
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
     {
@@ -1785,7 +1792,7 @@ build_insn_chain (first)
 {
   struct insn_chain **p = &reload_insn_chain;
   struct insn_chain *prev = 0;
-  int b = 0;
+  basic_block b = ENTRY_BLOCK_PTR->next_bb;
   regset_head live_relevant_regs_head;
 
   live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
@@ -1794,21 +1801,21 @@ build_insn_chain (first)
     {
       struct insn_chain *c;
 
-      if (first == BLOCK_HEAD (b))
+      if (first == b->head)
        {
          int i;
 
          CLEAR_REG_SET (live_relevant_regs);
 
          EXECUTE_IF_SET_IN_BITMAP
-           (BASIC_BLOCK (b)->global_live_at_start, 0, i,
+           (b->global_live_at_start, 0, i,
             {
               if (i < FIRST_PSEUDO_REGISTER
                   ? ! TEST_HARD_REG_BIT (eliminable_regset, i)
                   : reg_renumber[i] >= 0)
                 SET_REGNO_REG_SET (live_relevant_regs, i);
             });
-       }
+       }
 
       if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
        {
@@ -1818,7 +1825,7 @@ build_insn_chain (first)
          *p = c;
          p = &c->next;
          c->insn = first;
-         c->block = b;
+         c->block = b->index;
 
          if (INSN_P (first))
            {
@@ -1856,8 +1863,8 @@ build_insn_chain (first)
            }
        }
 
-      if (first == BLOCK_END (b))
-       b++;
+      if (first == b->end)
+       b = b->next_bb;
 
       /* Stop after we pass the end of the last basic block.  Verify that
         no real insns are after the end of the last basic block.
@@ -1865,7 +1872,7 @@ build_insn_chain (first)
         We may want to reorganize the loop somewhat since this test should
         always be the right exit test.  Allow an ADDR_VEC or ADDR_DIF_VEC if
         the previous real insn is a JUMP_INSN.  */
-      if (b == n_basic_blocks)
+      if (b == EXIT_BLOCK_PTR)
        {
          for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
            if (INSN_P (first)
@@ -1896,7 +1903,7 @@ dump_conflicts (file)
   for (i = 0; i < max_allocno; i++)
     {
       if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
-        continue;
+       continue;
       nregs++;
     }
   fprintf (file, ";; %d regs to allocate:", nregs);
@@ -1948,13 +1955,13 @@ dump_global_regs (file)
      FILE *file;
 {
   int i, j;
-  
+
   fprintf (file, ";; Register dispositions:\n");
   for (i = FIRST_PSEUDO_REGISTER, j = 0; i < max_regno; i++)
     if (reg_renumber[i] >= 0)
       {
        fprintf (file, "%d in %d  ", i, reg_renumber[i]);
-        if (++j % 6 == 0)
+       if (++j % 6 == 0)
          fprintf (file, "\n");
       }