OSDN Git Service

2010-02-10 Joost VandeVondele <jv244@cam.ac.uk>
[pf3gnuchains/gcc-fork.git] / gcc / reginfo.c
index e579c28..ee6c7ee 100644 (file)
@@ -101,13 +101,11 @@ char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
 #endif
 
 
-/* Indexed by hard register number, contains 1 for registers that are
-   fixed use or call used registers that cannot hold quantities across
-   calls even if we are willing to save and restore them.  call fixed
-   registers are a subset of call used registers.  */
-char call_fixed_regs[FIRST_PSEUDO_REGISTER];
+/* Contains registers that are fixed use -- i.e. in fixed_reg_set -- or
+   a function value return register or TARGET_STRUCT_VALUE_RTX or
+   STATIC_CHAIN_REGNUM.  These are the registers that cannot hold quantities
+   across calls even if we are willing to save and restore them.  */
 
-/* The same info as a HARD_REG_SET.  */
 HARD_REG_SET call_fixed_reg_set;
 
 /* Indexed by hard register number, contains 1 for registers
@@ -277,7 +275,8 @@ init_move_cost (enum machine_mode m)
            cost = 65535;
          else
            {
-             cost = REGISTER_MOVE_COST (m, i, j);
+             cost = REGISTER_MOVE_COST (m, (enum reg_class) i,
+                                        (enum reg_class) j);
              gcc_assert (cost < 65535);
            }
          all_match &= (last_move_cost[i][j] == cost);
@@ -327,12 +326,12 @@ init_move_cost (enum machine_mode m)
              gcc_assert (cost <= 65535);
              move_cost[m][i][j] = cost;
 
-             if (reg_class_subset_p (i, j))
+             if (reg_class_subset_p ((enum reg_class) i, (enum reg_class) j))
                may_move_in_cost[m][i][j] = 0;
              else
                may_move_in_cost[m][i][j] = cost;
 
-             if (reg_class_subset_p (j, i))
+             if (reg_class_subset_p ((enum reg_class) j, (enum reg_class) i))
                may_move_out_cost[m][i][j] = 0;
              else
                may_move_out_cost[m][i][j] = cost;
@@ -514,8 +513,6 @@ init_reg_sets_1 (void)
   else
     CLEAR_REG_SET (regs_invalidated_by_call_regset);
 
-  memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
-
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
       /* call_used_regs must include fixed_regs.  */
@@ -530,8 +527,6 @@ init_reg_sets_1 (void)
 
       if (call_used_regs[i])
        SET_HARD_REG_BIT (call_used_reg_set, i);
-      if (call_fixed_regs[i])
-       SET_HARD_REG_BIT (call_fixed_reg_set, i);
 
       /* There are a couple of fixed registers that we know are safe to
         exclude from being clobbered by calls:
@@ -570,12 +565,14 @@ init_reg_sets_1 (void)
         }
     }
 
+  COPY_HARD_REG_SET(call_fixed_reg_set, fixed_reg_set);
+
   /* Preserve global registers if called more than once.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
       if (global_regs[i])
        {
-         fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
+         fixed_regs[i] = call_used_regs[i] = 1;
          SET_HARD_REG_BIT (fixed_reg_set, i);
          SET_HARD_REG_BIT (call_used_reg_set, i);
          SET_HARD_REG_BIT (call_fixed_reg_set, i);
@@ -589,11 +586,13 @@ init_reg_sets_1 (void)
       HARD_REG_SET ok_regs;
       CLEAR_HARD_REG_SET (ok_regs);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-       if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, m))
+       if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (enum machine_mode) m))
          SET_HARD_REG_BIT (ok_regs, j);
-      
+
       for (i = 0; i < N_REG_CLASSES; i++)
-       if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i]
+       if (((unsigned) CLASS_MAX_NREGS ((enum reg_class) i,
+                                        (enum machine_mode) m)
+            <= reg_class_size[i])
            && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
          {
             contains_reg_of_mode [i][m] = 1;
@@ -676,9 +675,9 @@ void
 init_fake_stack_mems (void)
 {
   int i;
-  
+
   for (i = 0; i < MAX_MACHINE_MODE; i++)
-    top_of_stack[i] = gen_rtx_MEM (i, stack_pointer_rtx);
+    top_of_stack[i] = gen_rtx_MEM ((enum machine_mode) i, stack_pointer_rtx);
 }
 
 
@@ -867,7 +866,7 @@ globalize_reg (int i)
   if (fixed_regs[i])
     return;
 
-  fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
+  fixed_regs[i] = call_used_regs[i] = 1;
 #ifdef CALL_REALLY_USED_REGISTERS
   call_really_used_regs[i] = 1;
 #endif
@@ -895,12 +894,19 @@ struct reg_pref
      but since it is recommended that there be a class corresponding to the
      union of most major pair of classes, that generality is not required.  */
   char altclass;
+
+  /* coverclass is a register class that IRA uses for allocating
+     the pseudo.  */
+  char coverclass;
 };
 
 /* Record preferences of each pseudo.  This is available after RA is
    run.  */
 static struct reg_pref *reg_pref;
 
+/* Current size of reg_info.  */
+static int reg_info_size;
+
 /* Return the reg_class in which pseudo reg number REGNO is best allocated.
    This function is sometimes called before the info has been computed.
    When that happens, just return GENERAL_REGS, which is innocuous.  */
@@ -922,65 +928,53 @@ reg_alternate_class (int regno)
   return (enum reg_class) reg_pref[regno].altclass;
 }
 
-/* Initialize some global data for this pass.  */
-static unsigned int 
-reginfo_init (void)
+/* Return the reg_class which is used by IRA for its allocation.  */
+enum reg_class
+reg_cover_class (int regno)
 {
-  if (df)
-    df_compute_regs_ever_live (true);
-
-  /* This prevents dump_flow_info from losing if called
-     before reginfo is run.  */
-  reg_pref = NULL;
+  if (reg_pref == 0)
+    return NO_REGS;
 
-  /* No more global register variables may be declared.  */
-  no_global_reg_vars = 1;
-  return 1;
+  return (enum reg_class) reg_pref[regno].coverclass;
 }
 
-struct rtl_opt_pass pass_reginfo_init =
-{
- {
-  RTL_PASS,
-  "reginfo",                            /* name */
-  NULL,                                 /* gate */
-  reginfo_init,                         /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  0                                     /* todo_flags_finish */
- }
-};
-
 \f
 
 /* Allocate space for reg info.  */
-void
+static void
 allocate_reg_info (void)
 {
-  int size = max_reg_num ();
-
+  reg_info_size = max_reg_num ();
   gcc_assert (! reg_pref && ! reg_renumber);
-  reg_renumber = XNEWVEC (short, size);
-  reg_pref = XCNEWVEC (struct reg_pref, size);
-  memset (reg_renumber, -1, size * sizeof (short));
+  reg_renumber = XNEWVEC (short, reg_info_size);
+  reg_pref = XCNEWVEC (struct reg_pref, reg_info_size);
+  memset (reg_renumber, -1, reg_info_size * sizeof (short));
 }
 
 
-/* Resize reg info. The new elements will be uninitialized.  */
-void
+/* Resize reg info. The new elements will be uninitialized.  Return
+   TRUE if new elements (for new pseudos) were added.  */
+bool
 resize_reg_info (void)
 {
-  int size = max_reg_num ();
+  int old;
 
+  if (reg_pref == NULL)
+    {
+      allocate_reg_info ();
+      return true;
+    }
+  if (reg_info_size == max_reg_num ())
+    return false;
+  old = reg_info_size;
+  reg_info_size = max_reg_num ();
   gcc_assert (reg_pref && reg_renumber);
-  reg_renumber = XRESIZEVEC (short, reg_renumber, size);
-  reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, size);
+  reg_renumber = XRESIZEVEC (short, reg_renumber, reg_info_size);
+  reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, reg_info_size);
+  memset (reg_pref + old, -1,
+         (reg_info_size - old) * sizeof (struct reg_pref));
+  memset (reg_renumber + old, -1, (reg_info_size - old) * sizeof (short));
+  return true;
 }
 
 
@@ -1001,19 +995,55 @@ free_reg_info (void)
     }
 }
 
+/* Initialize some global data for this pass.  */
+static unsigned int
+reginfo_init (void)
+{
+  if (df)
+    df_compute_regs_ever_live (true);
+
+  /* This prevents dump_flow_info from losing if called
+     before reginfo is run.  */
+  reg_pref = NULL;
+  /* No more global register variables may be declared.  */
+  no_global_reg_vars = 1;
+  return 1;
+}
+
+struct rtl_opt_pass pass_reginfo_init =
+{
+ {
+  RTL_PASS,
+  "reginfo",                            /* name */
+  NULL,                                 /* gate */
+  reginfo_init,                         /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_NONE,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  0                                     /* todo_flags_finish */
+ }
+};
 
 \f
 
-/* Set up preferred and alternate classes for REGNO as PREFCLASS and
-   ALTCLASS.  */
+/* Set up preferred, alternate, and cover classes for REGNO as
+   PREFCLASS, ALTCLASS, and COVERCLASS.  */
 void
 setup_reg_classes (int regno,
-                  enum reg_class prefclass, enum reg_class altclass)
+                  enum reg_class prefclass, enum reg_class altclass,
+                  enum reg_class coverclass)
 {
   if (reg_pref == NULL)
     return;
+  gcc_assert (reg_info_size == max_reg_num ());
   reg_pref[regno].prefclass = prefclass;
   reg_pref[regno].altclass = altclass;
+  reg_pref[regno].coverclass = coverclass;
 }
 
 \f
@@ -1123,7 +1153,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
               && REG_POINTER (SET_SRC (x)))
              || ((GET_CODE (SET_SRC (x)) == PLUS
                   || GET_CODE (SET_SRC (x)) == LO_SUM)
-                 && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
+                 && CONST_INT_P (XEXP (SET_SRC (x), 1))
                  && REG_P (XEXP (SET_SRC (x), 0))
                  && REG_POINTER (XEXP (SET_SRC (x), 0)))
              || GET_CODE (SET_SRC (x)) == CONST
@@ -1268,7 +1298,7 @@ record_subregs_of_mode (rtx subreg)
 }
 
 /* Call record_subregs_of_mode for all the subregs in X.  */
-static void 
+static void
 find_subregs_of_mode (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
@@ -1277,7 +1307,7 @@ find_subregs_of_mode (rtx x)
 
   if (code == SUBREG)
     record_subregs_of_mode (x);
-    
+
   /* Time for some deep diving.  */
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
@@ -1292,7 +1322,7 @@ find_subregs_of_mode (rtx x)
     }
 }
 
-static unsigned int
+void
 init_subregs_of_mode (void)
 {
   basic_block bb;
@@ -1307,36 +1337,6 @@ init_subregs_of_mode (void)
     FOR_BB_INSNS (bb, insn)
     if (INSN_P (insn))
       find_subregs_of_mode (PATTERN (insn));
-
-  return 0;
-}
-
-/* Set bits in *USED which correspond to registers which can't change
-   their mode from FROM to any mode in which REGNO was
-   encountered.  */
-void
-cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
-                            unsigned int regno)
-{
-  struct subregs_of_mode_node dummy, *node;
-  enum machine_mode to;
-  unsigned char mask;
-  unsigned int i;
-
-  gcc_assert (subregs_of_mode);
-  dummy.block = regno & -8;
-  node = (struct subregs_of_mode_node *)
-    htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
-  if (node == NULL)
-    return;
-
-  mask = 1 << (regno & 7);
-  for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
-    if (node->modes[to] & mask)
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (!TEST_HARD_REG_BIT (*used, i)
-           && REG_CANNOT_CHANGE_MODE_P (i, from, to))
-         SET_HARD_REG_BIT (*used, i);
 }
 
 /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
@@ -1347,7 +1347,7 @@ invalid_mode_change_p (unsigned int regno,
                       enum machine_mode from)
 {
   struct subregs_of_mode_node dummy, *node;
-  enum machine_mode to;
+  unsigned int to;
   unsigned char mask;
 
   gcc_assert (subregs_of_mode);
@@ -1360,80 +1360,28 @@ invalid_mode_change_p (unsigned int regno,
   mask = 1 << (regno & 7);
   for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
     if (node->modes[to] & mask)
-      if (CANNOT_CHANGE_MODE_CLASS (from, to, rclass))
+      if (CANNOT_CHANGE_MODE_CLASS (from, (enum machine_mode) to, rclass))
        return true;
 
   return false;
 }
 
-static unsigned int
+void
 finish_subregs_of_mode (void)
 {
   htab_delete (subregs_of_mode);
   subregs_of_mode = 0;
-  return 0;
 }
 #else
-static unsigned int
+void
 init_subregs_of_mode (void)
 {
-  return 0;
 }
-static unsigned int
+void
 finish_subregs_of_mode (void)
 {
-  return 0;
 }
 
 #endif /* CANNOT_CHANGE_MODE_CLASS */
 
-static bool
-gate_subregs_of_mode_init (void)
-{
-#ifdef CANNOT_CHANGE_MODE_CLASS
-  return true;
-#else
-  return false;
-#endif
-}
-
-struct rtl_opt_pass pass_subregs_of_mode_init =
-{
- {
-  RTL_PASS,
-  "subregs_of_mode_init",               /* name */
-  gate_subregs_of_mode_init,            /* gate */
-  init_subregs_of_mode,                 /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  0                                     /* todo_flags_finish */
- }
-};
-
-struct rtl_opt_pass pass_subregs_of_mode_finish =
-{
- {
-  RTL_PASS,
-  "subregs_of_mode_finish",               /* name */
-  gate_subregs_of_mode_init,            /* gate */
-  finish_subregs_of_mode,               /* execute */
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  0                                     /* todo_flags_finish */
- }
-};
-
-
 #include "gt-reginfo.h"