OSDN Git Service

PR testsuite/50796
[pf3gnuchains/gcc-fork.git] / gcc / ira-color.c
index 4e2dd2c..2b21fdd 100644 (file)
@@ -1057,6 +1057,8 @@ setup_profitable_hard_regs (void)
   enum reg_class aclass;
   enum machine_mode mode;
 
+  /* Initial set up from allocno classes and explicitly conflicting
+     hard regs.  */
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
@@ -1076,9 +1078,6 @@ setup_profitable_hard_regs (void)
            {
              COPY_HARD_REG_SET (obj_data->profitable_hard_regs,
                                 reg_class_contents[aclass]);
-             AND_COMPL_HARD_REG_SET
-               (obj_data->profitable_hard_regs,
-                ira_prohibited_class_mode_regs[aclass][mode]);
              AND_COMPL_HARD_REG_SET (obj_data->profitable_hard_regs,
                                      ira_no_alloc_regs);
              AND_COMPL_HARD_REG_SET (obj_data->profitable_hard_regs,
@@ -1086,6 +1085,7 @@ setup_profitable_hard_regs (void)
            }
        }
     }
+  /* Exclude hard regs already assigned for conflicting objects.  */
   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
@@ -1124,6 +1124,7 @@ setup_profitable_hard_regs (void)
            }
        }
     }
+  /* Exclude too costly hard regs.  */
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       int min_cost = INT_MAX;
@@ -1447,11 +1448,13 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
 }
 
 /* Set up conflicting and profitable regs (through CONFLICT_REGS and
-   PROFITABLE_REGS) for each object of allocno A.  */
+   PROFITABLE_REGS) for each object of allocno A.  Remember that the
+   profitable regs exclude hard regs which can not hold value of mode
+   of allocno A.  */
 static inline void
-setup_conflict_profitable_regs (ira_allocno_t a, bool retry_p,
-                               HARD_REG_SET *conflict_regs,
-                               HARD_REG_SET *profitable_regs)
+get_conflict_profitable_regs (ira_allocno_t a, bool retry_p,
+                             HARD_REG_SET *conflict_regs,
+                             HARD_REG_SET *profitable_regs)
 {
   int i, nwords;
   ira_object_t obj;
@@ -1463,8 +1466,13 @@ setup_conflict_profitable_regs (ira_allocno_t a, bool retry_p,
       COPY_HARD_REG_SET (conflict_regs[i],
                         OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
       if (retry_p)
-       COPY_HARD_REG_SET (profitable_regs[i],
-                          reg_class_contents[ALLOCNO_CLASS (a)]);
+       {
+         COPY_HARD_REG_SET (profitable_regs[i],
+                            reg_class_contents[ALLOCNO_CLASS (a)]);
+         AND_COMPL_HARD_REG_SET (profitable_regs[i],
+                                 ira_prohibited_class_mode_regs
+                                 [ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
+       }
       else
        COPY_HARD_REG_SET (profitable_regs[i],
                           OBJECT_COLOR_DATA (obj)->profitable_hard_regs);
@@ -1478,8 +1486,15 @@ check_hard_reg_p (ira_allocno_t a, int hard_regno,
                  HARD_REG_SET *conflict_regs, HARD_REG_SET *profitable_regs)
 {
   int j, nwords, nregs;
+  enum reg_class aclass;
+  enum machine_mode mode;
 
-  nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (a)];
+  aclass = ALLOCNO_CLASS (a);
+  mode = ALLOCNO_MODE (a);
+  if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[aclass][mode],
+                        hard_regno))
+    return false;
+  nregs = hard_regno_nregs[hard_regno][mode];
   nwords = ALLOCNO_NUM_OBJECTS (a);
   for (j = 0; j < nregs; j++)
     {
@@ -1504,6 +1519,26 @@ check_hard_reg_p (ira_allocno_t a, int hard_regno,
     }
   return j == nregs;
 }
+#ifndef HONOR_REG_ALLOC_ORDER
+
+/* Return number of registers needed to be saved and restored at
+   function prologue/epilogue if we allocate HARD_REGNO to hold value
+   of MODE.  */
+static int
+calculate_saved_nregs (int hard_regno, enum machine_mode mode)
+{
+  int i;
+  int nregs = 0;
+
+  ira_assert (hard_regno >= 0);
+  for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
+    if (!allocated_hardreg_p[hard_regno + i]
+       && !TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + i)
+       && !LOCAL_REGNO (hard_regno + i))
+      nregs++;
+  return nregs;
+}
+#endif
 
 /* Choose a hard register for allocno A.  If RETRY_P is TRUE, it means
    that the function called from function
@@ -1539,6 +1574,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
   enum machine_mode mode;
   static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
 #ifndef HONOR_REG_ALLOC_ORDER
+  int saved_nregs;
   enum reg_class rclass;
   int add_cost;
 #endif
@@ -1547,8 +1583,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
 #endif
 
   ira_assert (! ALLOCNO_ASSIGNED_P (a));
-  setup_conflict_profitable_regs (a, retry_p,
-                                 conflicting_regs, profitable_hard_regs);
+  get_conflict_profitable_regs (a, retry_p,
+                               conflicting_regs, profitable_hard_regs);
   aclass = ALLOCNO_CLASS (a);
   class_size = ira_class_hard_regs_num[aclass];
   best_hard_regno = -1;
@@ -1613,12 +1649,15 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
            {
              hard_regno = ALLOCNO_HARD_REGNO (conflict_a);
              if (hard_regno >= 0
-                 && ira_class_hard_reg_index[aclass][hard_regno] >= 0)
+                 && (ira_hard_reg_set_intersection_p
+                     (hard_regno, ALLOCNO_MODE (conflict_a),
+                      reg_class_contents[aclass])))
                {
-                 enum machine_mode mode = ALLOCNO_MODE (conflict_a);
-                 int conflict_nregs = hard_regno_nregs[hard_regno][mode];
                  int n_objects = ALLOCNO_NUM_OBJECTS (conflict_a);
+                 int conflict_nregs;
 
+                 mode = ALLOCNO_MODE (conflict_a);
+                 conflict_nregs = hard_regno_nregs[hard_regno][mode];
                  if (conflict_nregs == n_objects && conflict_nregs > 1)
                    {
                      int num = OBJECT_SUBWORD (conflict_obj);
@@ -1698,16 +1737,14 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
       cost = costs[i];
       full_cost = full_costs[i];
 #ifndef HONOR_REG_ALLOC_ORDER
-      if (! allocated_hardreg_p[hard_regno]
-         && ira_hard_reg_not_in_set_p (hard_regno, mode, call_used_reg_set)
-         && !LOCAL_REGNO (hard_regno))
+      if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
        /* We need to save/restore the hard register in
           epilogue/prologue.  Therefore we increase the cost.  */
        {
-         /* ??? If only part is call clobbered.  */
          rclass = REGNO_REG_CLASS (hard_regno);
-         add_cost = (ira_memory_move_cost[mode][rclass][0]
-                     + ira_memory_move_cost[mode][rclass][1] - 1);
+         add_cost = ((ira_memory_move_cost[mode][rclass][0]
+                      + ira_memory_move_cost[mode][rclass][1])
+                     * saved_nregs / hard_regno_nregs[hard_regno][mode] - 1);
          cost += add_cost;
          full_cost += add_cost;
        }
@@ -1730,7 +1767,10 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
     }
  fail:
   if (best_hard_regno >= 0)
-    allocated_hardreg_p[best_hard_regno] = true;
+    {
+      for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--)
+       allocated_hardreg_p[best_hard_regno + i] = true;
+    }
   ALLOCNO_HARD_REGNO (a) = best_hard_regno;
   ALLOCNO_ASSIGNED_P (a) = true;
   if (best_hard_regno >= 0)
@@ -2223,7 +2263,8 @@ setup_allocno_available_regs_num (ira_allocno_t a)
              ira_object_t obj = ALLOCNO_OBJECT (a, k);
              object_color_data_t obj_data = OBJECT_COLOR_DATA (obj);
 
-             /* Checking only profitable hard regs.  */
+             /* Checking only profitable hard regs which exclude
+                object's conflict hard regs.  */
              if (TEST_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
                                     hard_regno + j)
                  || ! TEST_HARD_REG_BIT (obj_data->profitable_hard_regs,
@@ -2393,8 +2434,8 @@ improve_allocation (void)
       else
        base_cost = allocno_costs[ira_class_hard_reg_index[aclass][hregno]];
       try_p = false;
-      setup_conflict_profitable_regs (a, false,
-                                     conflicting_regs, profitable_hard_regs);
+      get_conflict_profitable_regs (a, false,
+                                   conflicting_regs, profitable_hard_regs);
       class_size = ira_class_hard_regs_num[aclass];
       /* Set up cost improvement for usage of each profitable hard
         register for allocno A.  */
@@ -3956,8 +3997,8 @@ allocno_reload_assign (ira_allocno_t a, HARD_REG_SET forbidden_regs)
               : ALLOCNO_HARD_REG_COSTS (a)[ira_class_hard_reg_index
                                            [aclass][hard_regno]]));
       if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
-         && ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
-                                         call_used_reg_set))
+         && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
+                                             call_used_reg_set))
        {
          ira_assert (flag_caller_saves);
          caller_save_needed = 1;
@@ -4448,7 +4489,7 @@ fast_allocation (void)
              && hard_regno <= LAST_STACK_REG)
            continue;
 #endif
-         if (!ira_hard_reg_not_in_set_p (hard_regno, mode, conflict_hard_regs)
+         if (ira_hard_reg_set_intersection_p (hard_regno, mode, conflict_hard_regs)
              || (TEST_HARD_REG_BIT
                  (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
            continue;