re PR rtl-optimization/50107 ([IRA, i386] allocates registers in very non-optimal...
authorVladimir Makarov <vmakarov@redhat.com>
Thu, 18 Aug 2011 14:56:36 +0000 (14:56 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Thu, 18 Aug 2011 14:56:36 +0000 (14:56 +0000)
2011-08-17  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/50107
* ira-int.h (ira_hard_reg_not_in_set_p): Remove.
(ira_hard_reg_in_set_p): New.

* ira-color.c (calculate_saved_nregs): New.
(assign_hard_reg): Use it.  Set up allocated_hard_reg_p for all
hard regs.
(allocno_reload_assign, fast_allocation): Use
ira_hard_reg_set_intersection_p instead of
ira_hard_reg_not_in_set_p.

* ira.c (setup_reg_renumber): Use
ira_hard_reg_set_intersection_p instead of
ira_hard_reg_not_in_set_p.
(setup_allocno_assignment_flags, calculate_allocation_cost): Use
ira_hard_reg_in_set_p instead of ira_hard_reg_not_in_set_p.

* ira-costs.c (ira_tune_allocno_costs): Use
ira_hard_reg_set_intersection_p instead of
ira_hard_reg_not_in_set_p.

From-SVN: r177865

gcc/ChangeLog
gcc/ira-color.c
gcc/ira-costs.c
gcc/ira-int.h
gcc/ira.c

index dabaf4eda27d438b58f2912d9e1cb6c25aa416f9..41c3db20a36dabaf26466a4b4ae923ea2f149e85 100644 (file)
@@ -1,3 +1,26 @@
+2011-08-17  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/50107
+       * ira-int.h (ira_hard_reg_not_in_set_p): Remove.
+       (ira_hard_reg_in_set_p): New.
+
+       * ira-color.c (calculate_saved_nregs): New.
+       (assign_hard_reg): Use it.  Set up allocated_hard_reg_p for all
+       hard regs.
+       (allocno_reload_assign, fast_allocation): Use
+       ira_hard_reg_set_intersection_p instead of
+       ira_hard_reg_not_in_set_p.
+
+       * ira.c (setup_reg_renumber): Use
+       ira_hard_reg_set_intersection_p instead of
+       ira_hard_reg_not_in_set_p.
+       (setup_allocno_assignment_flags, calculate_allocation_cost): Use
+       ira_hard_reg_in_set_p instead of ira_hard_reg_not_in_set_p.
+
+       * ira-costs.c (ira_tune_allocno_costs): Use
+       ira_hard_reg_set_intersection_p instead of
+       ira_hard_reg_not_in_set_p.
+
 2011-08-18  H.J. Lu  <hongjiu.lu@intel.com>
            Igor Zamyatin <igor.zamyatin@intel.com>
 
index 7a1073b0bf2afadd35be5745880db79b3b9c5064..eb87b0e419b5459edfe12efe527a6ada793edd0f 100644 (file)
@@ -1519,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
@@ -1547,7 +1567,7 @@ static bool
 assign_hard_reg (ira_allocno_t a, bool retry_p)
 {
   HARD_REG_SET conflicting_regs[2], profitable_hard_regs[2];
-  int i, j, hard_regno, best_hard_regno, class_size;
+  int i, j, hard_regno, best_hard_regno, class_size, saved_nregs;
   int cost, mem_cost, min_cost, full_cost, min_full_cost, nwords, word;
   int *a_costs;
   enum reg_class aclass;
@@ -1716,16 +1736,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;
        }
@@ -1748,7 +1766,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 + 1] = true;
+    }
   ALLOCNO_HARD_REGNO (a) = best_hard_regno;
   ALLOCNO_ASSIGNED_P (a) = true;
   if (best_hard_regno >= 0)
@@ -3975,8 +3996,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;
@@ -4467,7 +4488,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;
index 39ef33a541c17b13b1479e732c7201f0ac072966..12d3ed67fa7612dbbec2427f989a10eff9ecb6cb 100644 (file)
@@ -2072,9 +2072,9 @@ ira_tune_allocno_costs (void)
              skip_p = false;
              FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
                {
-                 if (! ira_hard_reg_not_in_set_p (regno, mode,
-                                                  OBJECT_CONFLICT_HARD_REGS
-                                                  (obj)))
+                 if (ira_hard_reg_set_intersection_p (regno, mode,
+                                                      OBJECT_CONFLICT_HARD_REGS
+                                                      (obj)))
                    {
                      skip_p = true;
                      break;
@@ -2084,7 +2084,7 @@ ira_tune_allocno_costs (void)
                continue;
              rclass = REGNO_REG_CLASS (regno);
              cost = 0;
-             if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set)
+             if (ira_hard_reg_set_intersection_p (regno, mode, call_used_reg_set)
                  || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
                cost += (ALLOCNO_CALL_FREQ (a)
                         * (ira_memory_move_cost[mode][rclass][0]
index 6a6c4831c008b84af4738d1b33f4cdc19b250eef..1db9b411e0b160007e719385025d90fd3addda75 100644 (file)
@@ -1323,17 +1323,17 @@ hard_reg_set_size (HARD_REG_SET set)
 }
 
 /* The function returns TRUE if hard registers starting with
-   HARD_REGNO and containing value of MODE are not in set
+   HARD_REGNO and containing value of MODE are fully in set
    HARD_REGSET.  */
 static inline bool
-ira_hard_reg_not_in_set_p (int hard_regno, enum machine_mode mode,
-                          HARD_REG_SET hard_regset)
+ira_hard_reg_in_set_p (int hard_regno, enum machine_mode mode,
+                      HARD_REG_SET hard_regset)
 {
   int i;
 
   ira_assert (hard_regno >= 0);
   for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
-    if (TEST_HARD_REG_BIT (hard_regset, hard_regno + i))
+    if (!TEST_HARD_REG_BIT (hard_regset, hard_regno + i))
       return false;
   return true;
 }
index b54762e8962b025345369ce4b267c4221997072b..e4be8b52f714d9d7dc9b177a0a9296114933dae6 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1953,8 +1953,8 @@ setup_reg_renumber (void)
                                      reg_class_contents[pclass]);
            }
          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 (!optimize || flag_caller_saves
                          || regno >= ira_reg_equiv_len
@@ -1992,10 +1992,10 @@ setup_allocno_assignment_flags (void)
                                || ALLOCNO_EMIT_DATA (a)->mem_optimized_dest_p
                                || (ALLOCNO_MEMORY_COST (a)
                                    - ALLOCNO_CLASS_COST (a)) < 0);
-      ira_assert (hard_regno < 0
-                 || ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
-                                                 reg_class_contents
-                                                 [ALLOCNO_CLASS (a)]));
+      ira_assert
+       (hard_regno < 0
+        || ira_hard_reg_in_set_p (hard_regno, ALLOCNO_MODE (a),
+                                  reg_class_contents[ALLOCNO_CLASS (a)]));
     }
 }
 
@@ -2013,9 +2013,9 @@ calculate_allocation_cost (void)
     {
       hard_regno = ALLOCNO_HARD_REGNO (a);
       ira_assert (hard_regno < 0
-                 || ! ira_hard_reg_not_in_set_p
-                      (hard_regno, ALLOCNO_MODE (a),
-                       reg_class_contents[ALLOCNO_CLASS (a)]));
+                 || (ira_hard_reg_in_set_p
+                     (hard_regno, ALLOCNO_MODE (a),
+                      reg_class_contents[ALLOCNO_CLASS (a)])));
       if (hard_regno < 0)
        {
          cost = ALLOCNO_MEMORY_COST (a);