OSDN Git Service

* config/rs6000/t-aix43 (BOOT_LDFLAGS): Define.
[pf3gnuchains/gcc-fork.git] / gcc / global.c
index 424bdad..35fec4a 100644 (file)
@@ -24,13 +24,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-
 #include "machmode.h"
 #include "hard-reg-set.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
-#include "basic-block.h"
 #include "regs.h"
 #include "function.h"
 #include "insn-config.h"
@@ -310,14 +308,12 @@ static void reg_dies (int, enum machine_mode, struct insn_chain *);
 
 static void allocate_bb_info (void);
 static void free_bb_info (void);
-static void check_earlyclobber (rtx);
-static bool regclass_intersect (enum reg_class, enum reg_class);
+static bool check_earlyclobber (rtx);
 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 set_up_bb_rts_numbers (void);
 static int rpost_cmp (const void *, const void *);
-static bool modify_bb_reg_pav (basic_block, basic_block, bool);
 static void calculate_reg_pav (void);
 static void modify_reg_pav (void);
 static void make_accurate_live_analysis (void);
@@ -669,7 +665,7 @@ allocno_compare (const void *v1p, const void *v2p)
 static void
 global_conflicts (void)
 {
-  int i;
+  unsigned i;
   basic_block b;
   rtx insn;
   int *block_start_allocnos;
@@ -695,25 +691,25 @@ global_conflicts (void)
         since one hard reg can be used with various sizes.
         Therefore, we must require that all the hard regs
         implicitly live as part of a multi-word hard reg
-        are explicitly marked in basic_block_live_at_start.  */
+        be explicitly marked in basic_block_live_at_start.  */
 
       {
        regset old = b->global_live_at_start;
        int ax = 0;
+       reg_set_iterator rsi;
 
        REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
-       EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i,
-                                  {
-                                    int a = reg_allocno[i];
-                                    if (a >= 0)
-                                      {
-                                        SET_ALLOCNO_LIVE (a);
-                                        block_start_allocnos[ax++] = a;
-                                      }
-                                    else if ((a = reg_renumber[i]) >= 0)
-                                      mark_reg_live_nc
-                                        (a, PSEUDO_REGNO_MODE (i));
-                                  });
+       EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i, rsi)
+         {
+           int a = reg_allocno[i];
+           if (a >= 0)
+             {
+               SET_ALLOCNO_LIVE (a);
+               block_start_allocnos[ax++] = a;
+             }
+           else if ((a = reg_renumber[i]) >= 0)
+             mark_reg_live_nc (a, PSEUDO_REGNO_MODE (i));
+         }
 
        /* Record that each allocno now live conflicts with each hard reg
           now live.
@@ -1806,9 +1802,8 @@ build_insn_chain (rtx first)
   struct insn_chain **p = &reload_insn_chain;
   struct insn_chain *prev = 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);
+  live_relevant_regs = ALLOC_REG_SET (&reg_obstack);
 
   for (; first; first = NEXT_INSN (first))
     {
@@ -1816,7 +1811,7 @@ build_insn_chain (rtx first)
 
       if (first == BB_HEAD (b))
        {
-         int i;
+         unsigned i;
          bitmap_iterator bi;
 
          CLEAR_REG_SET (live_relevant_regs);
@@ -2014,9 +2009,10 @@ struct bb_info
   /* Registers correspondingly killed (clobbered) and defined but not
      killed afterward in the basic block.  */
   bitmap killed, avloc;
-  /* Registers partially available correspondingly at the start and
-     end of the basic block.  */
-  bitmap pavin, pavout;
+  /* Registers partially available and living (in other words whose
+     values were calculated and used) correspondingly at the start
+     and end of the basic block.  */
+  bitmap live_pavin, live_pavout;
 };
 
 /* Macros for accessing data flow information of basic blocks.  */
@@ -2025,8 +2021,8 @@ struct bb_info
 #define BB_INFO_BY_INDEX(N) BB_INFO (BASIC_BLOCK(N))
 
 /* The function allocates the info structures of each basic block.  It
-   also initialized PAVIN and PAVOUT as if all hard registers were
-   partially available.  */
+   also initialized LIVE_PAVIN and LIVE_PAVOUT as if all hard
+   registers were partially available.  */
 
 static void
 allocate_bb_info (void)
@@ -2046,10 +2042,10 @@ allocate_bb_info (void)
       bb_info->earlyclobber = BITMAP_XMALLOC ();
       bb_info->avloc = BITMAP_XMALLOC ();
       bb_info->killed = BITMAP_XMALLOC ();
-      bb_info->pavin = BITMAP_XMALLOC ();
-      bb_info->pavout = BITMAP_XMALLOC ();
-      bitmap_copy (bb_info->pavin, init);
-      bitmap_copy (bb_info->pavout, init);
+      bb_info->live_pavin = BITMAP_XMALLOC ();
+      bb_info->live_pavout = BITMAP_XMALLOC ();
+      bitmap_copy (bb_info->live_pavin, init);
+      bitmap_copy (bb_info->live_pavout, init);
     }
   BITMAP_XFREE (init);
 }
@@ -2065,8 +2061,8 @@ free_bb_info (void)
   FOR_EACH_BB (bb)
     {
       bb_info = BB_INFO (bb);
-      BITMAP_XFREE (bb_info->pavout);
-      BITMAP_XFREE (bb_info->pavin);
+      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);
@@ -2104,13 +2100,15 @@ mark_reg_change (rtx reg, rtx setter, void *data)
 
 static varray_type earlyclobber_regclass;
 
-/* The function stores classes of registers which could be early
-   clobbered in INSN.  */
+/* This function finds and stores register classes that could be early
+   clobbered in INSN.  If any earlyclobber classes are found, the function
+   returns TRUE, in all other cases it returns FALSE.  */
 
-static void
+static bool
 check_earlyclobber (rtx insn)
 {
   int opno;
+  bool found = false;
 
   extract_insn (insn);
 
@@ -2151,6 +2149,7 @@ check_earlyclobber (rtx insn)
            case ',':
              if (amp_p && class != NO_REGS)
                {
+                 found = true;
                  for (i = VARRAY_ACTIVE_SIZE (earlyclobber_regclass) - 1;
                       i >= 0; i--)
                    if (VARRAY_INT (earlyclobber_regclass, i) == (int) class)
@@ -2176,27 +2175,14 @@ check_earlyclobber (rtx insn)
          p += CONSTRAINT_LEN (c, p);
        }
     }
-}
-
-/* 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;
+  return found;
 }
 
 /* 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.  */
+   clobbered in the same insn.
+   This function is a no-op if earlyclobber_regclass is empty.  */
 
 static int
 mark_reg_use_for_earlyclobber (rtx *x, void *data ATTRIBUTE_UNUSED)
@@ -2215,11 +2201,12 @@ mark_reg_use_for_earlyclobber (rtx *x, void *data ATTRIBUTE_UNUSED)
       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)
+       if (reg_classes_intersect_p (VARRAY_INT (earlyclobber_regclass, i),
+                                    pref_class)
            || (VARRAY_INT (earlyclobber_regclass, i) != NO_REGS
-               && regclass_intersect (VARRAY_INT (earlyclobber_regclass, i),
-                                      alt_class)))
+               && reg_classes_intersect_p (VARRAY_INT (earlyclobber_regclass,
+                                                       i),
+                                           alt_class)))
          {
            bitmap_set_bit (bb_info->earlyclobber, regno);
            break;
@@ -2254,8 +2241,8 @@ calculate_local_reg_bb_info (void)
        if (INSN_P (insn))
          {
            note_stores (PATTERN (insn), mark_reg_change, bb);
-           check_earlyclobber (insn);
-           note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
+           if (check_earlyclobber (insn))
+             note_uses (&PATTERN (insn), mark_reg_use_for_earlyclobber_1, bb);
          }
     }
 }
@@ -2286,40 +2273,23 @@ rpost_cmp (const void *bb1, const void *bb2)
   return BB_INFO (b2)->rts_number - BB_INFO (b1)->rts_number;
 }
 
-/* The function calculates partial availability of registers.  The
-   function calculates partial availability at the end of basic block
-   BB by propagating partial availability at end of predecessor basic
-   block PRED.  The function returns true if the partial availability
-   at the end of BB has been changed or if CHANGED_P.  We have the
-   following equations:
-
-     bb.pavin = empty for entry block | union (pavout of predecessors)
-     bb.pavout = union (bb.pavin - b.killed, bb.avloc)  */
+/* Temporary bitmap used for live_pavin, live_pavout calculation.  */
+static bitmap temp_bitmap;
 
-static bool
-modify_bb_reg_pav (basic_block bb, basic_block pred, bool changed_p)
-{
-  struct bb_info *bb_info;
-  bitmap bb_pavin, bb_pavout;
-
-  bb_info = BB_INFO (bb);
-  bb_pavin = bb_info->pavin;
-  bb_pavout = bb_info->pavout;
-  if (pred->index != ENTRY_BLOCK)
-    bitmap_a_or_b (bb_pavin, bb_pavin, BB_INFO (pred)->pavout);
-  changed_p |= bitmap_union_of_diff (bb_pavout, bb_info->avloc,
-                                    bb_pavin, bb_info->killed);
-  return changed_p;
-}
+/* The function calculates partial register availability according to
+   the following equations:
 
-/* The function calculates partial register availability.  */
+     bb.live_pavin
+       = empty for entry block
+         | union (live_pavout of predecessors) & global_live_at_start
+     bb.live_pavout = union (bb.live_pavin - bb.killed, bb.avloc)
+                      & global_live_at_end  */
 
 static void
 calculate_reg_pav (void)
 {
   basic_block bb, succ;
   edge e;
-  bool changed_p;
   int i, nel;
   varray_type bbs, new_bbs, temp;
   basic_block *bb_array;
@@ -2327,6 +2297,7 @@ calculate_reg_pav (void)
 
   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 ();
   FOR_EACH_BB (bb)
     {
       VARRAY_PUSH_BB (bbs, bb);
@@ -2341,21 +2312,38 @@ calculate_reg_pav (void)
       for (i = 0; i < nel; i++)
        {
          edge_iterator ei;
-
+         struct bb_info *bb_info;
+         bitmap bb_live_pavin, bb_live_pavout;
+             
          bb = bb_array [i];
-         changed_p = 0;
+         bb_info = BB_INFO (bb);
+         bb_live_pavin = bb_info->live_pavin;
+         bb_live_pavout = bb_info->live_pavout;
          FOR_EACH_EDGE (e, ei, bb->preds)
-           changed_p = modify_bb_reg_pav (bb, e->src, changed_p);
-         if (changed_p)
-           FOR_EACH_EDGE (e, ei, bb->succs)
-             {
-               succ = e->dest;
-               if (succ->index != EXIT_BLOCK && !TEST_BIT (wset, succ->index))
-                 {
-                   SET_BIT (wset, succ->index);
-                   VARRAY_PUSH_BB (new_bbs, succ);
-                 }
-             }
+           {
+             basic_block pred = e->src;
+
+             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_ior_and_compl (temp_bitmap, bb_info->avloc,
+                               bb_live_pavin, bb_info->killed);
+         bitmap_and_into (temp_bitmap, bb->global_live_at_end);
+         if (! bitmap_equal_p (temp_bitmap, bb_live_pavout))
+           {
+             bitmap_copy (bb_live_pavout, temp_bitmap);
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               {
+                 succ = e->dest;
+                 if (succ->index != EXIT_BLOCK
+                     && !TEST_BIT (wset, succ->index))
+                   {
+                     SET_BIT (wset, succ->index);
+                     VARRAY_PUSH_BB (new_bbs, succ);
+                   }
+               }
+           }
        }
       temp = bbs;
       bbs = new_bbs;
@@ -2363,6 +2351,7 @@ calculate_reg_pav (void)
       VARRAY_POP_ALL (new_bbs);
     }
   sbitmap_free (wset);
+  BITMAP_XFREE (temp_bitmap);
 }
 
 /* The function modifies partial availability information for two
@@ -2405,14 +2394,14 @@ modify_reg_pav (void)
         insn if the pseudo-register is used first time in given BB
         and not lived at the BB start.  To prevent this we don't
         change life information for such pseudo-registers.  */
-      bitmap_a_or_b (bb_info->pavin, bb_info->pavin, bb_info->earlyclobber);
+      bitmap_ior_into (bb_info->live_pavin, bb_info->earlyclobber);
 #ifdef STACK_REGS
       /* We can not use the same stack register for uninitialized
         pseudo-register and another living pseudo-register because if the
         uninitialized pseudo-register dies, subsequent pass reg-stack
         will be confused (it will believe that the other register
         dies).  */
-      bitmap_a_or_b (bb_info->pavin, bb_info->pavin, stack_regs);
+      bitmap_ior_into (bb_info->live_pavin, stack_regs);
 #endif
     }
 #ifdef STACK_REGS
@@ -2422,10 +2411,25 @@ modify_reg_pav (void)
 
 /* The following function makes live information more accurate by
    modifying global_live_at_start and global_live_at_end of basic
-   blocks.  After the function call a register lives at a program
-   point only if it is initialized on a path from CFG entry to the
-   program point.  The standard GCC life analysis permits registers to
-   live uninitialized.  */
+   blocks.
+
+   The standard GCC life analysis permits registers to live
+   uninitialized, for example:
+
+       R is never used
+       .....
+       Loop:
+         R is defined
+       ...
+       R is used.
+
+   With normal life_analysis, R would be live before "Loop:".
+   The result is that R causes many interferences that do not
+   serve any purpose.
+
+   After the function call a register lives at a program point
+   only if it is initialized on a path from CFG entry to the
+   program point.  */
 
 static void
 make_accurate_live_analysis (void)
@@ -2444,10 +2448,8 @@ make_accurate_live_analysis (void)
     {
       bb_info = BB_INFO (bb);
       
-      bitmap_a_and_b (bb->global_live_at_start, bb->global_live_at_start,
-                     bb_info->pavin);
-      bitmap_a_and_b (bb->global_live_at_end, bb->global_live_at_end,
-                     bb_info->pavout);
+      bitmap_and_into (bb->global_live_at_start, bb_info->live_pavin);
+      bitmap_and_into (bb->global_live_at_end, bb_info->live_pavout);
     }
   free_bb_info ();
 }