Hi,

The patch is for google branch only.

In r216697, when a hardreg is assigned to an allocno, a positive cost
will be added to those conflict allocnos to reflect the disfavor of
the hardreg.

However, the fact that conflict allocno disfavors a hard_regno doesn't
necessarily mean current allocno should prefer the hard_regno, so it
is incorrect to update the costs of an allocno directly according to
its conflict allocnos. The patch changes the code to update costs[i]
of an allocno only when conflict_costs[i] < 0, .i.e, when conflict
allocno prefer hardreg i.

Another issue is the costs of an allocno is updated only when the
conflict allocno is not marked as may_be_spilled_p. However, even if a
conflict allocno is marked as may_be_spilled_p right now, it still has
high probablity to get colored later. It is not right to ignore the
preferences from those conflict allocnos marked as may_be_spilled_p.
The patch changes it.

Test:
Gcc unit tests ok.
Minor improvement for google internal benchmarks.

Thanks,
Wei.
gcc/ChangeLog:

2015-12-10  Wei Mi  <w...@google.com>

        * ira-color.c (restore_costs_from_conflicts): Don't record the
        cost change.
        (update_conflict_hard_regno_costs): Update costs[i] only when
        conflict_costs[i] < 0.
        (assign_hard_reg): Ditto.


Index: gcc/ira-color.c
===================================================================
--- gcc/ira-color.c     (revision 231143)
+++ gcc/ira-color.c     (working copy)
@@ -1588,9 +1588,11 @@ restore_costs_from_conflicts (ira_allocn
                prev = curr;
            }
          /* Propagate the disfavor of hardreg from conflict_a to the
-            allocnos connecting with conflict_a via copies.  */
+            allocnos connecting with conflict_a via copies.
+            Note: once the hardreg is assigned to a, it will not be
+            changed, so we don't need to record this change. */
          update_costs_from_allocno (conflict_a, hardreg,
-                                    1, false, true, true);
+                                    1, false, false, true);
        }
     }
 }
@@ -1601,7 +1603,7 @@ restore_costs_from_conflicts (ira_allocn
    update increases chances to remove some copies.  */
 static void
 update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
-                                 bool decr_p)
+                                 bool decr_p, bool conflict)
 {
   int i, cost, class_size, freq, mult, div, divisor;
   int index, hard_regno;
@@ -1682,7 +1684,16 @@ update_conflict_hard_regno_costs (int *c
                cont_p = true;
                if (decr_p)
                  cost = -cost;
-               costs[index] += cost;
+               /* conflict being true indicates this is updating costs[]
+                  according to preferences of allocnos connected by copies
+                  to the conflict allocnos.
+                  The fact conflict allocno disfavors hard_regno doesn't
+                  necessarily mean current allocno should prefer hard_regno
+                  (actually only a little), so we update costs[] only
+                  when conflict allocno prefers hard_regno, .i.e, when
+                  conflict_costs[i] < 0. */
+               if (conflict && conflict_costs [i] < 0)
+                 costs[index] += cost;
              }
          }
        /* Probably 5 hops will be enough.  */
@@ -1934,7 +1945,6 @@ assign_hard_reg (ira_allocno_t a, bool r
                }
            }
          else if (! retry_p
-                  && ! ALLOCNO_COLOR_DATA (conflict_a)->may_be_spilled_p
                   /* Don't process the conflict allocno twice.  */
                   && (ALLOCNO_COLOR_DATA (conflict_a)->last_process
                       != curr_allocno_process))
@@ -1967,7 +1977,13 @@ assign_hard_reg (ira_allocno_t a, bool r
                                              ->new_conflict_hard_regs,
                                              hard_regno))
                      continue;
-                   full_costs[j] -= conflict_costs[k];
+                   /* The fact conflict_a disfavors hard_regno doesn't
+                      necessarily mean current allocno should prefer
+                      hard_regno so much (only a little), so we only
+                      update full_costs[] when conflict_a prefers
+                      hard_regno, .i.e, when conflict_costs[k] < 0. */
+                   if (conflict_costs[k] < 0)
+                     full_costs[j] -= conflict_costs[k];
                  }
              queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR);
 
@@ -1977,7 +1993,7 @@ assign_hard_reg (ira_allocno_t a, bool r
   if (! retry_p)
     /* Take into account preferences of allocnos connected by copies to
        the conflict allocnos.  */
-    update_conflict_hard_regno_costs (full_costs, aclass, true);
+    update_conflict_hard_regno_costs (full_costs, aclass, true, true);
 
   /* Take preferences of allocnos connected by copies into
      account.  */
@@ -1985,7 +2001,7 @@ assign_hard_reg (ira_allocno_t a, bool r
     {
       start_update_cost ();
       queue_update_cost (a, NULL,  COST_HOP_DIVISOR);
-      update_conflict_hard_regno_costs (full_costs, aclass, false);
+      update_conflict_hard_regno_costs (full_costs, aclass, false, false);
     }
   min_cost = min_full_cost = INT_MAX;
   /* We don't care about giving callee saved registers to allocnos no

Reply via email to