OSDN Git Service

* ChangeLog.vta: New.
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index 01d107e..dc56ca4 100644 (file)
@@ -1,13 +1,13 @@
 /* Allocate registers within a basic block, for GNU compiler.
    Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
-   Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* Allocation of hard register numbers to pseudo registers is done in
    two passes.  In this pass we consider only regs that are born and
@@ -81,6 +80,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "ggc.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "df.h"
+#include "dbgcnt.h"
+
 \f
 /* Next quantity number available for allocation.  */
 
@@ -285,7 +287,7 @@ static struct equivalence *reg_equiv;
 static int recorded_label_ref;
 
 static void alloc_qty (int, enum machine_mode, int, int);
-static void validate_equiv_mem_from_store (rtx, rtx, void *);
+static void validate_equiv_mem_from_store (rtx, const_rtx, void *);
 static int validate_equiv_mem (rtx, rtx, rtx);
 static int equiv_init_varies_p (rtx);
 static int equiv_init_movable_p (rtx, int);
@@ -293,7 +295,7 @@ static int contains_replace_regs (rtx);
 static int memref_referenced_p (rtx, rtx);
 static int memref_used_between_p (rtx, rtx, rtx);
 static void update_equiv_regs (void);
-static void no_equiv (rtx, rtx, void *);
+static void no_equiv (rtx, const_rtx, void *);
 static void block_alloc (int);
 static int qty_sugg_compare (int, int);
 static int qty_sugg_compare_1 (const void *, const void *);
@@ -302,7 +304,7 @@ static int qty_compare_1 (const void *, const void *);
 static int combine_regs (rtx, rtx, int, int, rtx, int);
 static int reg_meets_class_p (int, enum reg_class);
 static void update_qty_class (int, int);
-static void reg_is_set (rtx, rtx, void *);
+static void reg_is_set (rtx, const_rtx, void *);
 static void reg_is_born (rtx, int);
 static void wipe_dead_reg (rtx, int);
 static int find_free_reg (enum reg_class, enum machine_mode, int, int, int,
@@ -388,7 +390,7 @@ local_alloc (void)
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
-      if (REG_BASIC_BLOCK (i) >= 0 && REG_N_DEATHS (i) == 1)
+      if (REG_BASIC_BLOCK (i) >= NUM_FIXED_BLOCKS && REG_N_DEATHS (i) == 1)
        reg_qty[i] = -2;
       else
        reg_qty[i] = -1;
@@ -458,7 +460,7 @@ static int equiv_mem_modified;
    Called via note_stores.  */
 
 static void
-validate_equiv_mem_from_store (rtx dest, rtx set ATTRIBUTE_UNUSED,
+validate_equiv_mem_from_store (rtx dest, const_rtx set ATTRIBUTE_UNUSED,
                               void *data ATTRIBUTE_UNUSED)
 {
   if ((REG_P (dest)
@@ -536,6 +538,7 @@ equiv_init_varies_p (rtx x)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
@@ -604,7 +607,7 @@ equiv_init_movable_p (rtx x, int regno)
     case REG:
       return (reg_equiv[REGNO (x)].loop_depth >= reg_equiv[regno].loop_depth
              && reg_equiv[REGNO (x)].replace)
-            || (REG_BASIC_BLOCK (REGNO (x)) < 0 && ! rtx_varies_p (x, 0));
+            || (REG_BASIC_BLOCK (REGNO (x)) < NUM_FIXED_BLOCKS && ! rtx_varies_p (x, 0));
 
     case UNSPEC_VOLATILE:
       return 0;
@@ -653,6 +656,7 @@ contains_replace_regs (rtx x)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case PC:
     case CC0:
@@ -701,6 +705,7 @@ memref_referenced_p (rtx memref, rtx x)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case PC:
     case CC0:
@@ -796,11 +801,9 @@ update_equiv_regs (void)
   rtx insn;
   basic_block bb;
   int loop_depth;
-  regset_head cleared_regs;
-  int clear_regnos = 0;
-
+  bitmap cleared_regs;
+  
   reg_equiv = XCNEWVEC (struct equivalence, max_regno);
-  INIT_REG_SET (&cleared_regs);
   reg_equiv_init = ggc_alloc_cleared (max_regno * sizeof (rtx));
   reg_equiv_init_size = max_regno;
 
@@ -914,7 +917,7 @@ update_equiv_regs (void)
          if (note && GET_CODE (XEXP (note, 0)) == EXPR_LIST)
            note = NULL_RTX;
 
-         if (REG_N_SETS (regno) != 1
+         if (DF_REG_DEF_COUNT (regno) != 1
              && (! note
                  || rtx_varies_p (XEXP (note, 0), 0)
                  || (reg_equiv[regno].replacement
@@ -930,7 +933,7 @@ update_equiv_regs (void)
 
          /* If this register is known to be equal to a constant, record that
             it is always equivalent to the constant.  */
-         if (REG_N_SETS (regno) == 1
+         if (DF_REG_DEF_COUNT (regno) == 1
              && note && ! rtx_varies_p (XEXP (note, 0), 0))
            {
              rtx note_value = XEXP (note, 0);
@@ -955,7 +958,7 @@ update_equiv_regs (void)
 
          note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
 
-         if (note == 0 && REG_BASIC_BLOCK (regno) >= 0
+         if (note == 0 && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS
              && MEM_P (SET_SRC (set))
              && validate_equiv_mem (insn, dest, SET_SRC (set)))
            note = set_unique_reg_note (insn, REG_EQUIV, copy_rtx (SET_SRC (set)));
@@ -1052,8 +1055,8 @@ update_equiv_regs (void)
 
       if (MEM_P (dest) && REG_P (src)
          && (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
-         && REG_BASIC_BLOCK (regno) >= 0
-         && REG_N_SETS (regno) == 1
+         && REG_BASIC_BLOCK (regno) >= NUM_FIXED_BLOCKS
+         && DF_REG_DEF_COUNT (regno) == 1
          && reg_equiv[regno].init_insns != 0
          && reg_equiv[regno].init_insns != const0_rtx
          && ! find_reg_note (XEXP (reg_equiv[regno].init_insns, 0),
@@ -1071,10 +1074,12 @@ update_equiv_regs (void)
                 the register.  */
              reg_equiv_init[regno]
                = gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
+             df_notes_rescan (init_insn);
            }
        }
     }
 
+  cleared_regs = BITMAP_ALLOC (NULL);
   /* Now scan all regs killed in an insn to see if any of them are
      registers only used that once.  If so, see if we can replace the
      reference with the equivalent form.  If we can, delete the
@@ -1157,18 +1162,15 @@ update_equiv_regs (void)
                        }
 
                      remove_death (regno, insn);
-                     REG_N_REFS (regno) = 0;
+                     SET_REG_N_REFS (regno, 0);
                      REG_FREQ (regno) = 0;
                      delete_insn (equiv_insn);
 
                      reg_equiv[regno].init_insns
                        = XEXP (reg_equiv[regno].init_insns, 1);
 
-                     /* Remember to clear REGNO from all basic block's live
-                        info.  */
-                     SET_REGNO_REG_SET (&cleared_regs, regno);
-                     clear_regnos++;
                      reg_equiv_init[regno] = NULL_RTX;
+                     bitmap_set_bit (cleared_regs, regno);
                    }
                  /* Move the initialization of the register to just before
                     INSN.  Update the flow information.  */
@@ -1197,51 +1199,34 @@ update_equiv_regs (void)
                      if (insn == BB_HEAD (bb))
                        BB_HEAD (bb) = PREV_INSN (insn);
 
-                     /* Remember to clear REGNO from all basic block's live
-                        info.  */
-                     SET_REGNO_REG_SET (&cleared_regs, regno);
-                     clear_regnos++;
                      reg_equiv_init[regno]
                        = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
+                     bitmap_set_bit (cleared_regs, regno);
                    }
                }
            }
        }
     }
 
-  /* Clear all dead REGNOs from all basic block's live info.  */
-  if (clear_regnos)
-    {
-      unsigned j;
-      
-      if (clear_regnos > 8)
-       {
-         FOR_EACH_BB (bb)
-           {
-             AND_COMPL_REG_SET (bb->il.rtl->global_live_at_start,
-                                &cleared_regs);
-             AND_COMPL_REG_SET (bb->il.rtl->global_live_at_end,
-                                &cleared_regs);
-           }
-       }
-      else
-       {
-         reg_set_iterator rsi;
-         EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j, rsi)
-           {
-             FOR_EACH_BB (bb)
-               {
-                 CLEAR_REGNO_REG_SET (bb->il.rtl->global_live_at_start, j);
-                 CLEAR_REGNO_REG_SET (bb->il.rtl->global_live_at_end, j);
-               }
-           }
-       }
-    }
+  if (!bitmap_empty_p (cleared_regs))
+    FOR_EACH_BB (bb)
+      {
+       bitmap_and_compl_into (DF_RA_LIVE_IN (bb), cleared_regs);
+       if (DF_RA_LIVE_TOP (bb))
+         bitmap_and_compl_into (DF_RA_LIVE_TOP (bb), cleared_regs);
+       bitmap_and_compl_into (DF_RA_LIVE_OUT (bb), cleared_regs);
+       bitmap_and_compl_into (DF_LR_IN (bb), cleared_regs);
+       if (DF_LR_TOP (bb))
+         bitmap_and_compl_into (DF_LR_TOP (bb), cleared_regs);
+       bitmap_and_compl_into (DF_LR_OUT (bb), cleared_regs);
+      }
+
+  BITMAP_FREE (cleared_regs);
 
   out:
   /* Clean up.  */
+
   end_alias_analysis ();
-  CLEAR_REG_SET (&cleared_regs);
   free (reg_equiv);
 }
 
@@ -1253,7 +1238,7 @@ update_equiv_regs (void)
    assignment - a SET, CLOBBER or REG_INC note.  It is currently not used,
    but needs to be there because this function is called from note_stores.  */
 static void
-no_equiv (rtx reg, rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
+no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
 {
   int regno;
   rtx list;
@@ -1314,8 +1299,7 @@ block_alloc (int b)
 
   /* Initialize table of hardware registers currently live.  */
 
-  REG_SET_TO_HARD_REG_SET (regs_live,
-                          BASIC_BLOCK (b)->il.rtl->global_live_at_start);
+  REG_SET_TO_HARD_REG_SET (regs_live, DF_LR_TOP (BASIC_BLOCK (b)));
 
   /* This loop scans the instructions of the basic block
      and assigns quantities to registers.
@@ -1689,7 +1673,7 @@ block_alloc (int b)
                 This optimization is only appropriate when we will run
                 a scheduling pass after reload and we are not optimizing
                 for code size.  */
-             if (flag_schedule_insns_after_reload
+             if (flag_schedule_insns_after_reload && dbg_cnt (local_alloc_for_sched)
                  && !optimize_size
                  && !SMALL_REGISTER_CLASSES)
                {
@@ -1709,7 +1693,7 @@ block_alloc (int b)
 
 #ifdef INSN_SCHEDULING
          /* Similarly, avoid false dependencies.  */
-         if (flag_schedule_insns_after_reload
+         if (flag_schedule_insns_after_reload && dbg_cnt (local_alloc_for_sched)
              && !optimize_size
              && !SMALL_REGISTER_CLASSES
              && qty[q].alternate_class != NO_REGS)
@@ -2090,7 +2074,7 @@ update_qty_class (int qtyno, int reg)
    carry info from `block_alloc'.  */
 
 static void
-reg_is_set (rtx reg, rtx setter, void *data ATTRIBUTE_UNUSED)
+reg_is_set (rtx reg, const_rtx setter, void *data ATTRIBUTE_UNUSED)
 {
   /* Note that note_stores will only pass us a SUBREG if it is a SUBREG of
      a hard register.  These may actually not exist any more.  */
@@ -2524,15 +2508,41 @@ static unsigned int
 rest_of_handle_local_alloc (void)
 {
   int rebuild_notes;
+  int max_regno = max_reg_num ();
+
+  df_note_add_problem ();
+
+  if (optimize > 1)
+    df_remove_problem (df_live);
+  /* Create a new version of df that has the special version of UR if
+     we are doing optimization.  */
+  if (optimize)
+    df_urec_add_problem ();
+#ifdef ENABLE_CHECKING
+  df->changeable_flags |= DF_VERIFY_SCHEDULED;
+#endif
+  df_analyze ();
+  regstat_init_n_sets_and_refs ();
+  regstat_compute_ri ();
+
+  /* There is just too much going on in the register allocators to
+     keep things up to date.  At the end we have to rescan anyway
+     because things change when the reload_completed flag is set.  
+     So we just turn off scanning and we will rescan by hand.  */
+  df_set_flags (DF_NO_INSN_RESCAN);
+
+
+  /* If we are not optimizing, then this is the only place before
+     register allocation where dataflow is done.  And that is needed
+     to generate these warnings.  */
+  if (warn_clobbered)
+    generate_setjmp_warnings ();
 
   /* Determine if the current function is a leaf before running reload
      since this can impact optimizations done by the prologue and
      epilogue thus changing register elimination offsets.  */
   current_function_is_leaf = leaf_function_p ();
 
-  /* Allocate the reg_renumber array.  */
-  allocate_reg_info (max_regno, FALSE, TRUE);
-
   /* And the reg_equiv_memory_loc array.  */
   VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
   memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
@@ -2541,7 +2551,7 @@ rest_of_handle_local_alloc (void)
 
   allocate_initial_values (reg_equiv_memory_loc);
 
-  regclass (get_insns (), max_reg_num ());
+  regclass (get_insns (), max_regno);
   rebuild_notes = local_alloc ();
 
   /* Local allocation may have turned an indirect jump into a direct
@@ -2553,8 +2563,6 @@ rest_of_handle_local_alloc (void)
 
       rebuild_jump_labels (get_insns ());
       purge_all_dead_edges ();
-      delete_unreachable_blocks ();
-
       timevar_pop (TV_JUMP);
     }