OSDN Git Service

Use C fixincludes for UnixWare 7.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index ca4cbd6..3b07c13 100644 (file)
@@ -288,6 +288,8 @@ init_reg_sets_1 ()
 {
   register unsigned int i, j;
   register unsigned int /* enum machine_mode */ m;
+  char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
+  char allocatable_regs_of_mode [MAX_MACHINE_MODE];
 
   /* This macro allows the fixed or call-used registers
      and the register classes to depend on target flags.  */
@@ -423,44 +425,75 @@ init_reg_sets_1 ()
       if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
        SET_HARD_REG_BIT (losing_caller_save_reg_set, 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 (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;
+          }
 
   /* 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 (i = 0; i < N_REG_CLASSES; i++)
-      for (j = 0; j < N_REG_CLASSES; j++)
-       {
-         int cost = i == j ? 2 : REGISTER_MOVE_COST (m, i, j);
-         enum reg_class *p1, *p2;
-
-         for (p2 = &reg_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++)
-           if (*p2 != i)
-             cost = MAX (cost, REGISTER_MOVE_COST (m, i, *p2));
-
-         for (p1 = &reg_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++)
-           {
-             if (*p1 != j)
-               cost = MAX (cost, REGISTER_MOVE_COST (m, *p1, j));
-
-             for (p2 = &reg_class_subclasses[j][0];
-                  *p2 != LIM_REG_CLASSES; p2++)
-               if (*p1 != *p2)
-                 cost = MAX (cost, REGISTER_MOVE_COST (m, *p1, *p2));
-           }
-
-         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;
+    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 [*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
-           may_move_out_cost[m][i][j] = cost;
-       }
+           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
   {
@@ -2188,10 +2221,17 @@ free_reg_info ()
 
 /* Maximum number of parallel sets and clobbers in any insn in this fn.
    Always at least 3, since the combiner could put that many together
-   and we want this to remain correct for all the remaining passes.  */
+   and we want this to remain correct for all the remaining passes.
+   This corresponds to the maximum number of times note_stores will call
+   a function for any insn.  */
 
 int max_parallel;
 
+/* Used as a temporary to record the largest number of registers in 
+   PARALLEL in a SET_DEST.  This is added to max_parallel.  */
+
+static int max_set_parallel;
+
 void
 reg_scan (f, nregs, repeat)
      rtx f;
@@ -2202,6 +2242,7 @@ reg_scan (f, nregs, repeat)
 
   allocate_reg_info (nregs, TRUE, FALSE);
   max_parallel = 3;
+  max_set_parallel = 0;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == INSN
@@ -2216,6 +2257,8 @@ reg_scan (f, nregs, repeat)
        if (REG_NOTES (insn))
          reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0);
       }
+
+  max_parallel += max_set_parallel;
 }
 
 /* Update 'regscan' information by looking at the insns
@@ -2313,6 +2356,11 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
           dest = XEXP (dest, 0))
        ;
 
+      /* For a PARALLEL, record the number of things (less the usual one for a
+        SET) that are set.  */
+      if (GET_CODE (dest) == PARALLEL)
+       max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1);
+
       if (GET_CODE (dest) == REG
          && REGNO (dest) >= min_regno)
        REG_N_SETS (REGNO (dest))++;