diff gcc/ira-color.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/ira-color.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/ira-color.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* IRA allocation based on graph coloring.
-   Copyright (C) 2006-2018 Free Software Foundation, Inc.
+   Copyright (C) 2006-2020 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -151,6 +151,8 @@
   ira_allocno_t next_thread_allocno;
   /* All thread frequency.  Defined only for first thread allocno.  */
   int thread_freq;
+  /* Sum of frequencies of hard register preferences of the allocno.  */
+  int hard_reg_prefs;
 };
 
 /* See above.  */
@@ -218,7 +220,7 @@
 allocno_hard_regs_hasher::equal (const allocno_hard_regs *hv1,
 				 const allocno_hard_regs *hv2)
 {
-  return hard_reg_set_equal_p (hv1->set, hv2->set);
+  return hv1->set == hv2->set;
 }
 
 /* Hash table of unique allocno hard registers.  */
@@ -261,14 +263,14 @@
   allocno_hard_regs_t hv;
 
   gcc_assert (! hard_reg_set_empty_p (set));
-  COPY_HARD_REG_SET (temp.set, set);
+  temp.set = set;
   if ((hv = find_hard_regs (&temp)) != NULL)
     hv->cost += cost;
   else
     {
       hv = ((struct allocno_hard_regs *)
 	    ira_allocate (sizeof (struct allocno_hard_regs)));
-      COPY_HARD_REG_SET (hv->set, set);
+      hv->set = set;
       hv->cost = cost;
       allocno_hard_regs_vec.safe_push (hv);
       insert_hard_regs (hv);
@@ -371,7 +373,7 @@
   start = hard_regs_node_vec.length ();
   for (node = *roots; node != NULL; node = node->next)
     {
-      if (hard_reg_set_equal_p (hv->set, node->hard_regs->set))
+      if (hv->set == node->hard_regs->set)
 	return;
       if (hard_reg_set_subset_p (hv->set, node->hard_regs->set))
 	{
@@ -382,8 +384,7 @@
 	hard_regs_node_vec.safe_push (node);
       else if (hard_reg_set_intersect_p (hv->set, node->hard_regs->set))
 	{
-	  COPY_HARD_REG_SET (temp_set, hv->set);
-	  AND_HARD_REG_SET (temp_set, node->hard_regs->set);
+	  temp_set = hv->set & node->hard_regs->set;
 	  hv2 = add_allocno_hard_regs (temp_set, hv->cost);
 	  add_allocno_hard_regs_to_forest (&node->first, hv2);
 	}
@@ -398,7 +399,7 @@
 	   i++)
 	{
 	  node = hard_regs_node_vec[i];
-	  IOR_HARD_REG_SET (temp_set, node->hard_regs->set);
+	  temp_set |= node->hard_regs->set;
 	}
       hv = add_allocno_hard_regs (temp_set, hv->cost);
       new_node = create_new_allocno_hard_regs_node (hv);
@@ -479,24 +480,26 @@
 static void
 print_hard_reg_set (FILE *f, HARD_REG_SET set, bool new_line_p)
 {
-  int i, start;
-
-  for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+  int i, start, end;
+
+  for (start = end = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      if (TEST_HARD_REG_BIT (set, i))
+      bool reg_included = TEST_HARD_REG_BIT (set, i);
+
+      if (reg_included)
 	{
-	  if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1))
+	  if (start == -1)
 	    start = i;
+	  end = i;
 	}
-      if (start >= 0
-	  && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i)))
+      if (start >= 0 && (!reg_included || i == FIRST_PSEUDO_REGISTER - 1))
 	{
-	  if (start == i - 1)
+	  if (start == end)
 	    fprintf (f, " %d", start);
-	  else if (start == i - 2)
-	    fprintf (f, " %d %d", start, start + 1);
+	  else if (start == end + 1)
+	    fprintf (f, " %d %d", start, end);
 	  else
-	    fprintf (f, " %d-%d", start, i - 1);
+	    fprintf (f, " %d-%d", start, end);
 	  start = -1;
 	}
     }
@@ -717,8 +720,7 @@
 	    (allocno_data->profitable_hard_regs,
 	     ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
     }
-  SET_HARD_REG_SET (temp);
-  AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
+  temp = ~ira_no_alloc_regs;
   add_allocno_hard_regs (temp, 0);
   qsort (allocno_hard_regs_vec.address () + start,
 	 allocno_hard_regs_vec.length () - start,
@@ -833,10 +835,10 @@
   nobj = ALLOCNO_NUM_OBJECTS (a);
   data = ALLOCNO_COLOR_DATA (a);
   subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
-  COPY_HARD_REG_SET (profitable_hard_regs, data->profitable_hard_regs);
+  profitable_hard_regs = data->profitable_hard_regs;
   node = data->hard_regs_node;
   node_preorder_num = node->preorder_num;
-  COPY_HARD_REG_SET (node_set, node->hard_regs->set);
+  node_set = node->hard_regs->set;
   node_check_tick++;
   for (k = 0; k < nobj; k++)
     {
@@ -859,7 +861,7 @@
 					     ->profitable_hard_regs))
 	    continue;
 	  conflict_node = conflict_data->hard_regs_node;
-	  COPY_HARD_REG_SET (conflict_node_set, conflict_node->hard_regs->set);
+	  conflict_node_set = conflict_node->hard_regs->set;
 	  if (hard_reg_set_subset_p (node_set, conflict_node_set))
 	    temp_node = node;
 	  else
@@ -897,8 +899,7 @@
 	  int j, n, hard_regno;
 	  enum reg_class aclass;
 	  
-	  COPY_HARD_REG_SET (temp_set, temp_node->hard_regs->set);
-	  AND_HARD_REG_SET (temp_set, profitable_hard_regs);
+	  temp_set = temp_node->hard_regs->set & profitable_hard_regs;
 	  aclass = ALLOCNO_CLASS (a);
 	  for (n = 0, j = ira_class_hard_regs_num[aclass] - 1; j >= 0; j--)
 	    {
@@ -1042,15 +1043,15 @@
       else
 	{
 	  mode = ALLOCNO_MODE (a);
-	  COPY_HARD_REG_SET (data->profitable_hard_regs,
-			     ira_useful_class_mode_regs[aclass][mode]);
+	  data->profitable_hard_regs
+	    = ira_useful_class_mode_regs[aclass][mode];
 	  nobj = ALLOCNO_NUM_OBJECTS (a);
 	  for (k = 0; k < nobj; k++)
 	    {
 	      ira_object_t obj = ALLOCNO_OBJECT (a, k);
 	      
-	      AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
-				      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
+	      data->profitable_hard_regs
+		&= ~OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
 	    }
 	}
     }
@@ -1091,9 +1092,8 @@
 		       hard_regno + num);
 		}
 	      else
-		AND_COMPL_HARD_REG_SET
-		  (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
-		   ira_reg_mode_hard_regset[hard_regno][mode]);
+		ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs
+		  &= ~ira_reg_mode_hard_regset[hard_regno][mode];
 	    }
 	}
     }
@@ -1108,7 +1108,6 @@
 	  || empty_profitable_hard_regs (a))
 	continue;
       data = ALLOCNO_COLOR_DATA (a);
-      mode = ALLOCNO_MODE (a);
       if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
 	  || (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
 	{
@@ -1377,6 +1376,7 @@
 	     e.g. DImode for AREG on x86.  For such cases the
 	     register move cost will be maximal.  */
 	  mode = narrower_subreg_mode (mode, ALLOCNO_MODE (cp->second));
+	  ira_init_register_move_cost_if_necessary (mode);
 	  
 	  cost = (cp->second == allocno
 		  ? ira_register_move_cost[mode][rclass][aclass]
@@ -1575,7 +1575,7 @@
 /* Set up conflicting (through CONFLICT_REGS) for each object of
    allocno A and the start allocno profitable regs (through
    START_PROFITABLE_REGS).  Remember that the start profitable regs
-   exclude hard regs which can not hold value of mode of allocno A.
+   exclude hard regs which cannot hold value of mode of allocno A.
    This covers mostly cases when multi-register value should be
    aligned.  */
 static inline void
@@ -1590,20 +1590,15 @@
   for (i = 0; i < nwords; i++)
     {
       obj = ALLOCNO_OBJECT (a, i);
-      COPY_HARD_REG_SET (conflict_regs[i],
-			 OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
+      conflict_regs[i] = OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
     }
   if (retry_p)
-    {
-      COPY_HARD_REG_SET (*start_profitable_regs,
-			 reg_class_contents[ALLOCNO_CLASS (a)]);
-      AND_COMPL_HARD_REG_SET (*start_profitable_regs,
-			      ira_prohibited_class_mode_regs
-			      [ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]);
-    }
+    *start_profitable_regs
+      = (reg_class_contents[ALLOCNO_CLASS (a)]
+	 &~ (ira_prohibited_class_mode_regs
+	     [ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]));
   else
-    COPY_HARD_REG_SET (*start_profitable_regs,
-		       ALLOCNO_COLOR_DATA (a)->profitable_hard_regs);
+    *start_profitable_regs = ALLOCNO_COLOR_DATA (a)->profitable_hard_regs;
 }
 
 /* Return true if HARD_REGNO is ok for assigning to allocno A with
@@ -1660,7 +1655,7 @@
   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)
+	&& !crtl->abi->clobbers_full_reg_p (hard_regno + i)
 	&& !LOCAL_REGNO (hard_regno + i))
       nregs++;
   return nregs;
@@ -1804,9 +1799,8 @@
 					  hard_regno + num);
 		    }
 		  else
-		    IOR_HARD_REG_SET
-		      (conflicting_regs[word],
-		       ira_reg_mode_hard_regset[hard_regno][mode]);
+		    conflicting_regs[word]
+		      |= ira_reg_mode_hard_regset[hard_regno][mode];
 		  if (hard_reg_set_subset_p (profitable_hard_regs,
 					     conflicting_regs[word]))
 		    goto fail;
@@ -2183,6 +2177,7 @@
   ira_allocno_t a;
   unsigned int j;
   bitmap_iterator bi;
+  ira_pref_t pref;
 
   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
     {
@@ -2191,6 +2186,9 @@
       ALLOCNO_COLOR_DATA (a)->first_thread_allocno
 	= ALLOCNO_COLOR_DATA (a)->next_thread_allocno = a;
       ALLOCNO_COLOR_DATA (a)->thread_freq = ALLOCNO_FREQ (a);
+      ALLOCNO_COLOR_DATA (a)->hard_reg_prefs = 0;
+      for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
+	ALLOCNO_COLOR_DATA (a)->hard_reg_prefs += pref->freq;
     }
 }
 
@@ -2261,6 +2259,16 @@
   ira_allocno_t t2 = ALLOCNO_COLOR_DATA (a2)->first_thread_allocno;
   int cl1 = ALLOCNO_CLASS (a1), cl2 = ALLOCNO_CLASS (a2);
 
+  /* Push allocnos with minimal hard_reg_prefs first.  */
+  pref1 = ALLOCNO_COLOR_DATA (a1)->hard_reg_prefs;
+  pref2 = ALLOCNO_COLOR_DATA (a2)->hard_reg_prefs;
+  if ((diff = pref1 - pref2) != 0)
+    return diff;
+  /* Push allocnos with minimal conflict_allocno_hard_prefs first.  */
+  pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs;
+  pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs;
+  if ((diff = pref1 - pref2) != 0)
+    return diff;
   freq1 = ALLOCNO_COLOR_DATA (t1)->thread_freq;
   freq2 = ALLOCNO_COLOR_DATA (t2)->thread_freq;
   if ((diff = freq1 - freq2) != 0)
@@ -2272,7 +2280,7 @@
   /* Push pseudos requiring less hard registers first.  It means that
      we will assign pseudos requiring more hard registers first
      avoiding creation small holes in free hard register file into
-     which the pseudos requiring more hard registers can not fit.  */
+     which the pseudos requiring more hard registers cannot fit.  */
   if ((diff = (ira_reg_class_max_nregs[cl1][ALLOCNO_MODE (a1)]
 	       - ira_reg_class_max_nregs[cl2][ALLOCNO_MODE (a2)])) != 0)
     return diff;
@@ -2286,11 +2294,6 @@
   a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
   if ((diff = a2_num - a1_num) != 0)
     return diff;
-  /* Push allocnos with minimal conflict_allocno_hard_prefs first.  */
-  pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs;
-  pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs;
-  if ((diff = pref1 - pref2) != 0)
-    return diff;
   return ALLOCNO_NUM (a2) - ALLOCNO_NUM (a1);
 }
 
@@ -2699,8 +2702,7 @@
      reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
   print_hard_reg_set (ira_dump_file, data->profitable_hard_regs, false);
   fprintf (ira_dump_file, ", %snode: ",
-	   hard_reg_set_equal_p (data->profitable_hard_regs,
-				 data->hard_regs_node->hard_regs->set)
+	   data->profitable_hard_regs == data->hard_regs_node->hard_regs->set
 	   ? "" : "^");
   print_hard_reg_set (ira_dump_file,
 		      data->hard_regs_node->hard_regs->set, false);
@@ -2829,6 +2831,7 @@
 	}
       else
 	gcc_unreachable ();
+      ira_init_register_move_cost_if_necessary (allocno_mode);
       cost += cp->freq * ira_register_move_cost[allocno_mode][rclass][rclass];
     }
   return cost;
@@ -4388,11 +4391,10 @@
   for (i = 0; i < n; i++)
     {
       ira_object_t obj = ALLOCNO_OBJECT (a, i);
-      COPY_HARD_REG_SET (saved[i], OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
-      IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), forbidden_regs);
+      saved[i] = OBJECT_TOTAL_CONFLICT_HARD_REGS (obj);
+      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= forbidden_regs;
       if (! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
-	IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
-			  call_used_reg_set);
+	OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= ira_need_caller_save_regs (a);
     }
   ALLOCNO_ASSIGNED_P (a) = false;
   aclass = ALLOCNO_CLASS (a);
@@ -4411,9 +4413,7 @@
 	       ? ALLOCNO_CLASS_COST (a)
 	       : ALLOCNO_HARD_REG_COSTS (a)[ira_class_hard_reg_index
 					    [aclass][hard_regno]]));
-      if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
-	  && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
-					      call_used_reg_set))
+      if (ira_need_caller_save_p (a, hard_regno))
 	{
 	  ira_assert (flag_caller_saves);
 	  caller_save_needed = 1;
@@ -4435,7 +4435,7 @@
   for (i = 0; i < n; i++)
     {
       ira_object_t obj = ALLOCNO_OBJECT (a, i);
-      COPY_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), saved[i]);
+      OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) = saved[i];
     }
   return reg_renumber[regno] >= 0;
 }
@@ -4520,9 +4520,9 @@
   for (i = 0; i < num; i++)
     {
       regno = spilled_pseudo_regs[i];
-      COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
-      IOR_HARD_REG_SET (forbidden_regs, pseudo_forbidden_regs[regno]);
-      IOR_HARD_REG_SET (forbidden_regs, pseudo_previous_regs[regno]);
+      forbidden_regs = (bad_spill_regs
+			| pseudo_forbidden_regs[regno]
+			| pseudo_previous_regs[regno]);
       gcc_assert (reg_renumber[regno] < 0);
       a = ira_regno_allocno_map[regno];
       ira_mark_allocation_change (regno);
@@ -4558,7 +4558,7 @@
   ira_allocno_t another_allocno, allocno = ira_regno_allocno_map[regno];
   rtx x;
   bitmap_iterator bi;
-  struct ira_spilled_reg_stack_slot *slot = NULL;
+  class ira_spilled_reg_stack_slot *slot = NULL;
 
   ira_assert (! ira_use_lra_p);
 
@@ -4670,7 +4670,7 @@
 void
 ira_mark_new_stack_slot (rtx x, int regno, poly_uint64 total_size)
 {
-  struct ira_spilled_reg_stack_slot *slot;
+  class ira_spilled_reg_stack_slot *slot;
   int slot_num;
   ira_allocno_t allocno;
 
@@ -4700,16 +4700,16 @@
    given IN and OUT for INSN.  Return also number points (through
    EXCESS_PRESSURE_LIVE_LENGTH) where the pseudo-register lives and
    the register pressure is high, number of references of the
-   pseudo-registers (through NREFS), number of callee-clobbered
-   hard-registers occupied by the pseudo-registers (through
-   CALL_USED_COUNT), and the first hard regno occupied by the
+   pseudo-registers (through NREFS), the number of psuedo registers
+   whose allocated register wouldn't need saving in the prologue
+   (through CALL_USED_COUNT), and the first hard regno occupied by the
    pseudo-registers (through FIRST_HARD_REGNO).  */
 static int
 calculate_spill_cost (int *regnos, rtx in, rtx out, rtx_insn *insn,
 		      int *excess_pressure_live_length,
 		      int *nrefs, int *call_used_count, int *first_hard_regno)
 {
-  int i, cost, regno, hard_regno, j, count, saved_cost, nregs;
+  int i, cost, regno, hard_regno, count, saved_cost;
   bool in_p, out_p;
   int length;
   ira_allocno_t a;
@@ -4726,11 +4726,8 @@
       a = ira_regno_allocno_map[regno];
       length += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) / ALLOCNO_NUM_OBJECTS (a);
       cost += ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a);
-      nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (a));
-      for (j = 0; j < nregs; j++)
-	if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j))
-	  break;
-      if (j == nregs)
+      if (in_hard_reg_set_p (crtl->abi->full_reg_clobbers (),
+			     ALLOCNO_MODE (a), hard_regno))
 	count++;
       in_p = in && REG_P (in) && (int) REGNO (in) == hard_regno;
       out_p = out && REG_P (out) && (int) REGNO (out) == hard_regno;
@@ -4852,7 +4849,8 @@
 static void
 fast_allocation (void)
 {
-  int i, j, k, num, class_size, hard_regno;
+  int i, j, k, num, class_size, hard_regno, best_hard_regno, cost, min_cost;
+  int *costs;
 #ifdef STACK_REGS
   bool no_stack_reg_p;
 #endif
@@ -4886,11 +4884,10 @@
       for (l = 0; l < nr; l++)
 	{
 	  ira_object_t obj = ALLOCNO_OBJECT (a, l);
-	  IOR_HARD_REG_SET (conflict_hard_regs,
-			    OBJECT_CONFLICT_HARD_REGS (obj));
+	  conflict_hard_regs |= OBJECT_CONFLICT_HARD_REGS (obj);
 	  for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
 	    for (j = r->start; j <= r->finish; j++)
-	      IOR_HARD_REG_SET (conflict_hard_regs, used_hard_regs[j]);
+	      conflict_hard_regs |= used_hard_regs[j];
 	}
       aclass = ALLOCNO_CLASS (a);
       ALLOCNO_ASSIGNED_P (a) = true;
@@ -4903,6 +4900,9 @@
       no_stack_reg_p = ALLOCNO_NO_STACK_REG_P (a);
 #endif
       class_size = ira_class_hard_regs_num[aclass];
+      costs = ALLOCNO_HARD_REG_COSTS (a);
+      min_cost = INT_MAX;
+      best_hard_regno = -1;
       for (j = 0; j < class_size; j++)
 	{
 	  hard_regno = ira_class_hard_regs[aclass][j];
@@ -4915,16 +4915,27 @@
 	      || (TEST_HARD_REG_BIT
 		  (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
 	    continue;
-	  ALLOCNO_HARD_REGNO (a) = hard_regno;
-	  for (l = 0; l < nr; l++)
+	  if (costs == NULL)
+	    {
+	      best_hard_regno = hard_regno;
+	      break;
+	    }
+	  cost = costs[j];
+	  if (min_cost > cost)
 	    {
-	      ira_object_t obj = ALLOCNO_OBJECT (a, l);
-	      for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
-		for (k = r->start; k <= r->finish; k++)
-		  IOR_HARD_REG_SET (used_hard_regs[k],
-				    ira_reg_mode_hard_regset[hard_regno][mode]);
+	      min_cost = cost;
+	      best_hard_regno = hard_regno;
 	    }
-	  break;
+	}
+      if (best_hard_regno < 0)
+	continue;
+      ALLOCNO_HARD_REGNO (a) = hard_regno = best_hard_regno;
+      for (l = 0; l < nr; l++)
+	{
+	  ira_object_t obj = ALLOCNO_OBJECT (a, l);
+	  for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+	    for (k = r->start; k <= r->finish; k++)
+	      used_hard_regs[k] |= ira_reg_mode_hard_regset[hard_regno][mode];
 	}
     }
   ira_free (sorted_allocnos);