OSDN Git Service

update the sample output
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index da16edc..c022b0a 100644 (file)
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 #include "rtl.h"
+#include "expr.h"
 #include "tm_p.h"
 #include "hard-reg-set.h"
 #include "flags.h"
@@ -115,7 +116,16 @@ int n_non_fixed_regs;
    and are also considered fixed.  */
 
 char global_regs[FIRST_PSEUDO_REGISTER];
-  
+
+/* Contains 1 for registers that are set or clobbered by calls.  */
+/* ??? Ideally, this would be just call_used_regs plus global_regs, but
+   for someone's bright idea to have call_used_regs strictly include
+   fixed_regs.  Which leaves us guessing as to the set of fixed_regs
+   that are actually preserved.  We know for sure that those associated
+   with the local stack frame are safe, but scant others.  */
+
+HARD_REG_SET regs_invalidated_by_call;
+
 /* Table of register numbers in the order in which to try to use them.  */
 #ifdef REG_ALLOC_ORDER
 int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
@@ -174,6 +184,10 @@ const char * reg_names[] = REGISTER_NAMES;
 
 enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
 
+/* 1 if class does contain register of given mode.  */
+
+static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
+
 /* Maximum cost of moving from a register in one class to a register in
    another class.  Based on REGISTER_MOVE_COST.  */
 
@@ -261,9 +275,10 @@ init_reg_sets ()
     {
       CLEAR_HARD_REG_SET (reg_class_contents[i]);
 
+      /* Note that we hard-code 32 here, not HOST_BITS_PER_INT.  */
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-       if (int_reg_class_contents[i][j / HOST_BITS_PER_INT]
-           & ((unsigned) 1 << (j % HOST_BITS_PER_INT)))
+       if (int_reg_class_contents[i][j / 32]
+           & ((unsigned) 1 << (j % 32)))
          SET_HARD_REG_BIT (reg_class_contents[i], j);
     }
 
@@ -288,7 +303,6 @@ init_reg_sets_1 ()
 {
   register unsigned int i, j;
   register unsigned int /* enum machine_mode */ m;
-  char contains_reg_of_mode [LIM_REG_CLASSES] [MAX_MACHINE_MODE];
   char allocatable_regs_of_mode [MAX_MACHINE_MODE];
 
   /* This macro allows the fixed or call-used registers
@@ -406,6 +420,7 @@ init_reg_sets_1 ()
   CLEAR_HARD_REG_SET (fixed_reg_set);
   CLEAR_HARD_REG_SET (call_used_reg_set);
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
+  CLEAR_HARD_REG_SET (regs_invalidated_by_call);
 
   memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
 
@@ -424,72 +439,104 @@ init_reg_sets_1 ()
        SET_HARD_REG_BIT (call_fixed_reg_set, i);
       if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
        SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
+
+      /* There are a couple of fixed registers that we know are safe to
+        exclude from being clobbered by calls:
+
+        The frame pointer is always preserved across calls.  The arg pointer
+        is if it is fixed.  The stack pointer usually is, unless
+        RETURN_POPS_ARGS, in which case an explicit CLOBBER will be present.
+        If we are generating PIC code, the PIC offset table register is
+        preserved across calls, though the target can override that.  */
+        
+      if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM)
+       ;
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+      else if (i == HARD_FRAME_POINTER_REGNUM)
+       ;
+#endif
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+      else if (i == ARG_POINTER_REGNUM && fixed_regs[i])
+       ;
+#endif
+#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+      else if (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
+       ;
+#endif
+      else if (call_used_regs[i] || global_regs[i])
+       SET_HARD_REG_BIT (regs_invalidated_by_call, i);
     }
+
   memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
   memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode));
-  for (m = 0; m < MAX_MACHINE_MODE; m++)
+  for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
     for (i = 0; i < N_REG_CLASSES; i++)
-      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-       if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
-           && HARD_REGNO_MODE_OK (j, m))
-          {
-            contains_reg_of_mode [i][m] = 1;
-            allocatable_regs_of_mode [m] = 1;
-            break;
-          }
+      if (CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
+       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+         if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
+             && HARD_REGNO_MODE_OK (j, m))
+            {
+              contains_reg_of_mode [i][m] = 1;
+              allocatable_regs_of_mode [m] = 1;
+              break;
+            }
 
   /* Initialize the move cost table.  Find every subset of each class
      and take the maximum cost of moving any subset to any other.  */
 
-  for (m = 0; m < MAX_MACHINE_MODE; m++)
+  for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
     if (allocatable_regs_of_mode [m])
-      for (i = 0; i < N_REG_CLASSES; i++)
-       if (contains_reg_of_mode [i][m])
-         for (j = 0; j < N_REG_CLASSES; j++)
-           {
-             int cost;
-             enum reg_class *p1, *p2;
-
-             if (!contains_reg_of_mode [j][m])
-               {
-                 move_cost[m][i][j] = 65536;
-                 may_move_in_cost[m][i][j] = 65536;
-                 may_move_out_cost[m][i][j] = 65536;
-               }
-             else
-               {
-                 cost = i == j ? 2 : REGISTER_MOVE_COST (m, i, j);
-
-                 for (p2 = &reg_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES;
-                      p2++)
-                   if (*p2 != i && contains_reg_of_mode [*p1][m])
-                     cost = MAX (cost, move_cost [m][i][*p2]);
-
-                 for (p1 = &reg_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES;
-                      p1++)
-                   if (*p1 != j && contains_reg_of_mode [*p1][m])
-                     cost = MAX (cost, move_cost [m][*p1][j]);
-
-                 move_cost[m][i][j] = cost;
-
-                 if (reg_class_subset_p (i, 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))
-                   may_move_out_cost[m][i][j] = 0;
-                 else
-                   may_move_out_cost[m][i][j] = cost;
-               }
-           }
-       else
-         for (j = 0; j < N_REG_CLASSES; j++)
-           {
-             move_cost[m][i][j] = 65536;
-             may_move_in_cost[m][i][j] = 65536;
-             may_move_out_cost[m][i][j] = 65536;
-           }
+      {
+       for (i = 0; i < N_REG_CLASSES; i++)
+         if (contains_reg_of_mode [i][m])
+           for (j = 0; j < N_REG_CLASSES; j++)
+             {
+               int cost;
+               enum reg_class *p1, *p2;
+
+               if (!contains_reg_of_mode [j][m])
+                 {
+                   move_cost[m][i][j] = 65536;
+                   may_move_in_cost[m][i][j] = 65536;
+                   may_move_out_cost[m][i][j] = 65536;
+                 }
+               else
+                 {
+                   cost = i == j ? 2 : REGISTER_MOVE_COST (m, i, j);
+
+                   for (p2 = &reg_class_subclasses[j][0];
+                        *p2 != LIM_REG_CLASSES;
+                        p2++)
+                     if (*p2 != i && contains_reg_of_mode [*p2][m])
+                       cost = MAX (cost, move_cost [m][i][*p2]);
+
+                   for (p1 = &reg_class_subclasses[i][0];
+                        *p1 != LIM_REG_CLASSES;
+                        p1++)
+                     if (*p1 != j && contains_reg_of_mode [*p1][m])
+                       cost = MAX (cost, move_cost [m][*p1][j]);
+
+                   move_cost[m][i][j] = cost;
+
+                   if (reg_class_subset_p (i, 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))
+                     may_move_out_cost[m][i][j] = 0;
+                   else
+                     may_move_out_cost[m][i][j] = cost;
+                 }
+             }
+         else
+           for (j = 0; j < N_REG_CLASSES; j++)
+             {
+               move_cost[m][i][j] = 65536;
+               may_move_in_cost[m][i][j] = 65536;
+               may_move_out_cost[m][i][j] = 65536;
+             }
+      }
 
 #ifdef CLASS_CANNOT_CHANGE_MODE
   {
@@ -623,6 +670,7 @@ choose_hard_reg_mode (regno, nregs)
      unsigned int regno ATTRIBUTE_UNUSED;
      unsigned int nregs;
 {
+  unsigned int /* enum machine_mode */ m;
   enum machine_mode found_mode = VOIDmode, mode;
 
   /* We first look for the largest integer mode that can be validly
@@ -650,10 +698,13 @@ choose_hard_reg_mode (regno, nregs)
     return found_mode;
 
   /* Iterate over all of the CCmodes.  */
-  for (mode = CCmode; mode < NUM_MACHINE_MODES; ++mode)
-    if (HARD_REGNO_NREGS (regno, mode) == nregs
-        && HARD_REGNO_MODE_OK (regno, mode))
-    return mode;
+  for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
+    {
+      mode = (enum machine_mode) m;
+      if (HARD_REGNO_NREGS (regno, mode) == nregs
+         && HARD_REGNO_MODE_OK (regno, mode))
+       return mode;
+    }
 
   /* We can't find a mode valid for this register.  */
   return VOIDmode;
@@ -781,10 +832,9 @@ static struct reg_pref *reg_pref;
 
 static struct reg_pref *reg_pref_buffer;
 
-/* Account for the fact that insns within a loop are executed very commonly,
-   but don't keep doing this as loops go too deep.  */
+/* Frequency of executions of current insn.  */
 
-static int loop_cost;
+static int frequency;
 
 static rtx scan_one_insn       PARAMS ((rtx, int));
 static void record_operand_costs PARAMS ((rtx, struct costs *, struct reg_pref *));
@@ -851,13 +901,23 @@ dump_regclass (dump)
   int i;
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
-      enum reg_class class;
+      int /* enum reg_class */ class;
       if (REG_N_REFS (i))
        {
          fprintf (dump, "  Register %i costs:", i);
-         for (class = 0; class < N_REG_CLASSES; class++)
-           fprintf (dump, " %s:%i", reg_class_names[(int) class],
-                    costs[i].cost[class]);
+         for (class = 0; class < (int) N_REG_CLASSES; class++)
+           if (contains_reg_of_mode [(enum reg_class) class][PSEUDO_REGNO_MODE (i)]
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+               && (!in_inc_dec[i]
+                   || !forbidden_inc_dec_class[(enum reg_class) class])
+#endif
+#ifdef CLASS_CANNOT_CHANGE_MODE
+               && (!REGNO_REG_SET_P (reg_changes_mode, i)
+                    || class_can_change_mode [(enum reg_class) class])
+#endif
+               )
+           fprintf (dump, " %s:%i", reg_class_names[class],
+                    costs[i].cost[(enum reg_class) class]);
          fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
        }
     }
@@ -905,10 +965,10 @@ record_operand_costs (insn, op_costs, reg_pref)
 
       if (GET_CODE (recog_data.operand[i]) == MEM)
        record_address_regs (XEXP (recog_data.operand[i], 0),
-                            BASE_REG_CLASS, loop_cost * 2);
+                            BASE_REG_CLASS, frequency * 2);
       else if (constraints[i][0] == 'p')
        record_address_regs (recog_data.operand[i],
-                            BASE_REG_CLASS, loop_cost * 2);
+                            BASE_REG_CLASS, frequency * 2);
     }
 
   /* Check for commutative in a separate loop so everything will
@@ -984,9 +1044,9 @@ scan_one_insn (insn, pass)
       costs[REGNO (SET_DEST (set))].mem_cost
        -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
                              GENERAL_REGS, 1)
-           * loop_cost);
+           * frequency);
       record_address_regs (XEXP (SET_SRC (set), 0),
-                          BASE_REG_CLASS, loop_cost * 2);
+                          BASE_REG_CLASS, frequency * 2);
       return insn;
     }
 
@@ -1035,11 +1095,19 @@ scan_one_insn (insn, pass)
 
       /* This makes one more setting of new insns's dest.  */
       REG_N_SETS (REGNO (recog_data.operand[0]))++;
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
 
       *recog_data.operand_loc[1] = recog_data.operand[0];
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
       for (i = recog_data.n_dups - 1; i >= 0; i--)
        if (recog_data.dup_num[i] == 1)
-         *recog_data.dup_loc[i] = recog_data.operand[0];
+         {
+           *recog_data.dup_loc[i] = recog_data.operand[0];
+           REG_N_REFS (REGNO (recog_data.operand[0]))++;
+           REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
+         }
 
       return PREV_INSN (newinsn);
     }
@@ -1056,9 +1124,9 @@ scan_one_insn (insn, pass)
        int regno = REGNO (recog_data.operand[i]);
        struct costs *p = &costs[regno], *q = &op_costs[i];
 
-       p->mem_cost += q->mem_cost * loop_cost;
+       p->mem_cost += q->mem_cost * frequency;
        for (j = 0; j < N_REG_CLASSES; j++)
-         p->cost[j] += q->cost[j] * loop_cost;
+         p->cost[j] += q->cost[j] * frequency;
       }
 
   return insn;
@@ -1164,7 +1232,7 @@ regclass (f, nregs, dump)
 
       if (!optimize)
        {
-         loop_cost = 1;
+         frequency = 1;
          for (insn = f; insn; insn = NEXT_INSN (insn))
            insn = scan_one_insn (insn, pass);
        }
@@ -1178,9 +1246,9 @@ regclass (f, nregs, dump)
               aggressive than the assumptions made elsewhere and is being
               tried as an experiment.  */
            if (optimize_size)
-             loop_cost = 1;
+             frequency = 1;
            else
-             loop_cost = 1 << (2 * MIN (bb->loop_depth, 5));
+             frequency = bb->frequency ? bb->frequency : 1;
            for (insn = bb->head; ; insn = NEXT_INSN (insn))
              {
                insn = scan_one_insn (insn, pass);
@@ -1220,8 +1288,7 @@ regclass (f, nregs, dump)
            {
              /* Ignore classes that are too small for this operand or
                 invalid for a operand that was auto-incremented.  */
-             if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i))
-                 > reg_class_size[class]
+             if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif