2008-11-15 Vladimir Makarov <vmakarov@redhat.com>
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Nov 2008 21:20:44 +0000 (21:20 +0000)
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Nov 2008 21:20:44 +0000 (21:20 +0000)
PR bootstrap/37790
* ira-int.h (ira_copy_allocno_live_range_list,
ira_merge_allocno_live_ranges,
ira_allocno_live_ranges_intersect_p,
ira_finish_allocno_live_range_list): New prototypes.
(ira_allocno_live_ranges_intersect_p,
ira_pseudo_live_ranges_intersect_p): Remove.

* ira-conflicts.c (ira_allocno_live_ranges_intersect_p,
ira_pseudo_live_ranges_intersect_p): Rename to
allocnos_have_intersected_live_ranges_p and
pseudos_have_intersected_live_ranges_p.  Move them from here to
...

* ira-color.c: ... here
(coalesced_allocno_conflict_p): Use
allocnos_have_intersected_live_ranges_p.
(coalesced_allocnos_living_at_program_points,
coalesced_allocnos_live_at_points_p,
set_coalesced_allocnos_live_points): Remove.
(slot_coalesced_allocnos_live_ranges,
slot_coalesced_allocno_live_ranges_intersect_p,
setup_slot_coalesced_allocno_live_ranges): New.
(coalesce_spill_slots): Use ranges of coalesced allocnos.
(ira_sort_regnos_for_alter_reg): Use
allocnos_have_intersected_live_ranges_p.
(ira_reuse_stack_slot): Use
pseudos_have_intersected_live_ranges_p.

* global.c (pseudo_for_reload_consideration_p): Check
flag_ira_share_spill_slots too.

* ira-build.c (copy_allocno_live_range_list): Rename to
ira_copy_allocno_live_range_list.  Make it external.
(merge_ranges): Rename to ira_merge_allocno_live_ranges.  Make it
external.
(ira_allocno_live_ranges_intersect_p): New.
(ira_finish_allocno_live_range_list): New.
(finish_allocno): Use it.
(remove_unnecessary_allocnos): Use ira_merge_allocno_live_ranges.
(copy_info_to_removed_store_destinations): Ditto.  Use
ira_copy_allocno_live_range_list.
(ira_flattening): Use ira_merge_allocno_live_ranges.

* ira.c (too_high_register_pressure_p): New function.
(ira): Switch off sharing spill slots if the pressure is too high.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142017 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/global.c
gcc/ira-build.c
gcc/ira-color.c
gcc/ira-conflicts.c
gcc/ira-int.h
gcc/ira.c

index 6b972ee..eacb5e0 100644 (file)
@@ -1,3 +1,52 @@
+2008-11-15  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR bootstrap/37790
+       * ira-int.h (ira_copy_allocno_live_range_list,
+       ira_merge_allocno_live_ranges,
+       ira_allocno_live_ranges_intersect_p,
+       ira_finish_allocno_live_range_list): New prototypes.
+       (ira_allocno_live_ranges_intersect_p,
+       ira_pseudo_live_ranges_intersect_p): Remove.
+       
+       * ira-conflicts.c (ira_allocno_live_ranges_intersect_p,
+       ira_pseudo_live_ranges_intersect_p): Rename to
+       allocnos_have_intersected_live_ranges_p and
+       pseudos_have_intersected_live_ranges_p.  Move them from here to
+       ...
+
+       * ira-color.c: ... here
+       (coalesced_allocno_conflict_p): Use
+       allocnos_have_intersected_live_ranges_p.
+       (coalesced_allocnos_living_at_program_points,
+       coalesced_allocnos_live_at_points_p,
+       set_coalesced_allocnos_live_points): Remove.
+       (slot_coalesced_allocnos_live_ranges,
+       slot_coalesced_allocno_live_ranges_intersect_p,
+       setup_slot_coalesced_allocno_live_ranges): New.
+       (coalesce_spill_slots): Use ranges of coalesced allocnos.
+       (ira_sort_regnos_for_alter_reg): Use
+       allocnos_have_intersected_live_ranges_p.
+       (ira_reuse_stack_slot): Use
+       pseudos_have_intersected_live_ranges_p.
+
+       * global.c (pseudo_for_reload_consideration_p): Check
+       flag_ira_share_spill_slots too.
+
+       * ira-build.c (copy_allocno_live_range_list): Rename to
+       ira_copy_allocno_live_range_list.  Make it external.
+       (merge_ranges): Rename to ira_merge_allocno_live_ranges.  Make it
+       external.
+       (ira_allocno_live_ranges_intersect_p): New.
+       (ira_finish_allocno_live_range_list): New.
+       (finish_allocno): Use it.
+       (remove_unnecessary_allocnos): Use ira_merge_allocno_live_ranges.
+       (copy_info_to_removed_store_destinations): Ditto.  Use
+       ira_copy_allocno_live_range_list.
+       (ira_flattening): Use ira_merge_allocno_live_ranges.
+       
+       * ira.c (too_high_register_pressure_p): New function.
+       (ira): Switch off sharing spill slots if the pressure is too high.
+
 2008-11-19  Richard Guenther  <rguenther@suse.de>
 
        * tree.c (build2_stat): Allow non-POINTER_PLUS_EXPRs with
index edc2a42..824fcf0 100644 (file)
@@ -1393,7 +1393,8 @@ pseudo_for_reload_consideration_p (int regno)
 {
   /* Consider spilled pseudos too for IRA because they still have a
      chance to get hard-registers in the reload when IRA is used.  */
-  return reg_renumber[regno] >= 0 || (flag_ira && optimize);
+  return (reg_renumber[regno] >= 0
+         || (flag_ira && optimize && flag_ira_share_spill_slots));
 }
 
 /* Walk the insns of the current function and build reload_insn_chain,
index 110da63..af1d174 100644 (file)
@@ -826,8 +826,8 @@ copy_allocno_live_range (allocno_live_range_t r)
 
 /* Copy allocno live range list given by its head R and return the
    result.  */
-static allocno_live_range_t
-copy_allocno_live_range_list (allocno_live_range_t r)
+allocno_live_range_t
+ira_copy_allocno_live_range_list (allocno_live_range_t r)
 {
   allocno_live_range_t p, first, last;
 
@@ -845,6 +845,103 @@ copy_allocno_live_range_list (allocno_live_range_t r)
   return first;
 }
 
+/* Merge ranges R1 and R2 and returns the result.  The function
+   maintains the order of ranges and tries to minimize number of the
+   result ranges.  */
+allocno_live_range_t 
+ira_merge_allocno_live_ranges (allocno_live_range_t r1,
+                              allocno_live_range_t r2)
+{
+  allocno_live_range_t first, last, temp;
+
+  if (r1 == NULL)
+    return r2;
+  if (r2 == NULL)
+    return r1;
+  for (first = last = NULL; r1 != NULL && r2 != NULL;)
+    {
+      if (r1->start < r2->start)
+       {
+         temp = r1;
+         r1 = r2;
+         r2 = temp;
+       }
+      if (r1->start <= r2->finish + 1)
+       {
+         /* Intersected ranges: merge r1 and r2 into r1.  */
+         r1->start = r2->start;
+         if (r1->finish < r2->finish)
+           r1->finish = r2->finish;
+         temp = r2;
+         r2 = r2->next;
+         ira_finish_allocno_live_range (temp);
+         if (r2 == NULL)
+           {
+             /* To try to merge with subsequent ranges in r1.  */
+             r2 = r1->next;
+             r1->next = NULL;
+           }
+       }
+      else
+       {
+         /* Add r1 to the result.  */
+         if (first == NULL)
+           first = last = r1;
+         else
+           {
+             last->next = r1;
+             last = r1;
+           }
+         r1 = r1->next;
+         if (r1 == NULL)
+           {
+             /* To try to merge with subsequent ranges in r2.  */
+             r1 = r2->next;
+             r2->next = NULL;
+           }
+       }
+    }
+  if (r1 != NULL)
+    {
+      if (first == NULL)
+       first = r1;
+      else
+       last->next = r1;
+      ira_assert (r1->next == NULL);
+    }
+  else if (r2 != NULL)
+    {
+      if (first == NULL)
+       first = r2;
+      else
+       last->next = r2;
+      ira_assert (r2->next == NULL);
+    }
+  else
+    {
+      ira_assert (last->next == NULL);
+    }
+  return first;
+}
+
+/* Return TRUE if live ranges R1 and R2 intersect.  */
+bool
+ira_allocno_live_ranges_intersect_p (allocno_live_range_t r1,
+                                    allocno_live_range_t r2)
+{
+  /* Remember the live ranges are always kept ordered.  */
+  while (r1 != NULL && r2 != NULL)
+    {
+      if (r1->start > r2->finish)
+       r1 = r1->next;
+      else if (r2->start > r1->finish)
+       r2 = r2->next;
+      else
+       return true;
+    }
+  return false;
+}
+
 /* Free allocno live range R.  */
 void
 ira_finish_allocno_live_range (allocno_live_range_t r)
@@ -852,6 +949,19 @@ ira_finish_allocno_live_range (allocno_live_range_t r)
   pool_free (allocno_live_range_pool, r);
 }
 
+/* Free list of allocno live ranges starting with R.  */
+void
+ira_finish_allocno_live_range_list (allocno_live_range_t r)
+{
+  allocno_live_range_t next_r;
+
+  for (; r != NULL; r = next_r)
+    {
+      next_r = r->next;
+      ira_finish_allocno_live_range (r);
+    }
+}
+
 /* Free updated register costs of allocno A.  */
 void
 ira_free_allocno_updated_costs (ira_allocno_t a)
@@ -872,7 +982,6 @@ ira_free_allocno_updated_costs (ira_allocno_t a)
 static void
 finish_allocno (ira_allocno_t a)
 {
-  allocno_live_range_t r, next_r;
   enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
 
   ira_allocnos[ALLOCNO_NUM (a)] = NULL;
@@ -888,11 +997,7 @@ finish_allocno (ira_allocno_t a)
   if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
     ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
                          cover_class);
-  for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = next_r)
-    {
-      next_r = r->next;
-      ira_finish_allocno_live_range (r);
-    }
+  ira_finish_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
   pool_free (allocno_pool, a);
 }
 
@@ -1543,84 +1648,6 @@ create_allocnos (void)
    will hardly improve the result.  As a result we speed up regional
    register allocation.  */
 
-/* Merge ranges R1 and R2 and returns the result.  The function
-   maintains the order of ranges and tries to minimize number of the
-   result ranges.  */
-static allocno_live_range_t 
-merge_ranges (allocno_live_range_t r1, allocno_live_range_t r2)
-{
-  allocno_live_range_t first, last, temp;
-
-  if (r1 == NULL)
-    return r2;
-  if (r2 == NULL)
-    return r1;
-  for (first = last = NULL; r1 != NULL && r2 != NULL;)
-    {
-      if (r1->start < r2->start)
-       {
-         temp = r1;
-         r1 = r2;
-         r2 = temp;
-       }
-      if (r1->start <= r2->finish + 1)
-       {
-         /* Intersected ranges: merge r1 and r2 into r1.  */
-         r1->start = r2->start;
-         if (r1->finish < r2->finish)
-           r1->finish = r2->finish;
-         temp = r2;
-         r2 = r2->next;
-         ira_finish_allocno_live_range (temp);
-         if (r2 == NULL)
-           {
-             /* To try to merge with subsequent ranges in r1.  */
-             r2 = r1->next;
-             r1->next = NULL;
-           }
-       }
-      else
-       {
-         /* Add r1 to the result.  */
-         if (first == NULL)
-           first = last = r1;
-         else
-           {
-             last->next = r1;
-             last = r1;
-           }
-         r1 = r1->next;
-         if (r1 == NULL)
-           {
-             /* To try to merge with subsequent ranges in r2.  */
-             r1 = r2->next;
-             r2->next = NULL;
-           }
-       }
-    }
-  if (r1 != NULL)
-    {
-      if (first == NULL)
-       first = r1;
-      else
-       last->next = r1;
-      ira_assert (r1->next == NULL);
-    }
-  else if (r2 != NULL)
-    {
-      if (first == NULL)
-       first = r2;
-      else
-       last->next = r2;
-      ira_assert (r2->next == NULL);
-    }
-  else
-    {
-      ira_assert (last->next == NULL);
-    }
-  return first;
-}
-
 /* The function changes allocno in range list given by R onto A.  */
 static void
 change_allocno_in_range_list (allocno_live_range_t r, ira_allocno_t a)
@@ -1762,7 +1789,8 @@ remove_unnecessary_allocnos (void)
                r = ALLOCNO_LIVE_RANGES (a);
                change_allocno_in_range_list (r, parent_a);
                ALLOCNO_LIVE_RANGES (parent_a)
-                 = merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a));
+                 = ira_merge_allocno_live_ranges
+                   (r, ALLOCNO_LIVE_RANGES (parent_a));
                merged_p = true;
                ALLOCNO_LIVE_RANGES (a) = NULL;
                IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a),
@@ -2155,10 +2183,10 @@ copy_info_to_removed_store_destinations (int regno)
          ira_print_live_range_list (ira_dump_file,
                                     ALLOCNO_LIVE_RANGES (a));
        }
-      r = copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
+      r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
       change_allocno_in_range_list (r, parent_a);
       ALLOCNO_LIVE_RANGES (parent_a)
-       = merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a));
+       = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (parent_a));
       IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
                        ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
 #ifdef STACK_REGS
@@ -2255,8 +2283,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
                }
              change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a);
              ALLOCNO_LIVE_RANGES (parent_a)
-               = merge_ranges (ALLOCNO_LIVE_RANGES (a),
-                               ALLOCNO_LIVE_RANGES (parent_a));
+               = ira_merge_allocno_live_ranges
+                 (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a));
              merged_p = true;
              ALLOCNO_LIVE_RANGES (a) = NULL;
              ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
index eea3b2c..7343e0c 100644 (file)
@@ -84,6 +84,49 @@ static VEC(ira_allocno_t,heap) *removed_splay_allocno_vec;
 
 \f
 
+/* This page contains functions used to find conflicts using allocno
+   live ranges.  */
+
+/* Return TRUE if live ranges of allocnos A1 and A2 intersect.  It is
+   used to find a conflict for new allocnos or allocnos with the
+   different cover classes.  */
+static bool
+allocnos_have_intersected_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
+{
+  if (a1 == a2)
+    return false;
+  if (ALLOCNO_REG (a1) != NULL && ALLOCNO_REG (a2) != NULL
+      && (ORIGINAL_REGNO (ALLOCNO_REG (a1))
+         == ORIGINAL_REGNO (ALLOCNO_REG (a2))))
+    return false;
+  return ira_allocno_live_ranges_intersect_p (ALLOCNO_LIVE_RANGES (a1),
+                                             ALLOCNO_LIVE_RANGES (a2));
+}
+
+#ifdef ENABLE_IRA_CHECKING
+
+/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
+   intersect.  This should be used when there is only one region.
+   Currently this is used during reload.  */
+static bool
+pseudos_have_intersected_live_ranges_p (int regno1, int regno2)
+{
+  ira_allocno_t a1, a2;
+
+  ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
+             && regno2 >= FIRST_PSEUDO_REGISTER);
+  /* Reg info caclulated by dataflow infrastructure can be different
+     from one calculated by regclass.  */
+  if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
+      || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
+    return false;
+  return allocnos_have_intersected_live_ranges_p (a1, a2);
+}
+
+#endif
+
+\f
+
 /* This page contains functions used to choose hard registers for
    allocnos.  */
 
@@ -1489,7 +1532,8 @@ coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2,
               conflict_allocno
                 = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_allocno))
            {
-             if (ira_allocno_live_ranges_intersect_p (a, conflict_allocno))
+             if (allocnos_have_intersected_live_ranges_p (a,
+                                                          conflict_allocno))
                return true;
              if (conflict_allocno == a1)
                break;
@@ -2319,38 +2363,37 @@ collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n,
   return num;
 }
 
-/* Array of bitmaps of size IRA_MAX_POINT.  Bitmap for given point
-   contains numbers of coalesced allocnos living at this point.  */
-static regset_head *coalesced_allocnos_living_at_program_points;
+/* Array of live ranges of size IRA_ALLOCNOS_NUM.  Live range for
+   given slot contains live ranges of coalesced allocnos assigned to
+   given slot.  */
+static allocno_live_range_t *slot_coalesced_allocnos_live_ranges;
 
-/* Return TRUE if coalesced allocnos represented by ALLOCNO live at
-   program points of coalesced allocnos with number N.  */
+/* Return TRUE if coalesced allocnos represented by ALLOCNO has live
+   ranges intersected with live ranges of coalesced allocnos assigned
+   to slot with number N.  */
 static bool
-coalesced_allocnos_live_at_points_p (ira_allocno_t allocno, int n)
+slot_coalesced_allocno_live_ranges_intersect_p (ira_allocno_t allocno, int n)
 {
-  int i;
   ira_allocno_t a;
-  allocno_live_range_t r;
 
   for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
        a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
     {
-      for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
-       for (i = r->start; i <= r->finish; i++)
-         if (bitmap_bit_p (&coalesced_allocnos_living_at_program_points[i], n))
-             return true;
+      if (ira_allocno_live_ranges_intersect_p
+         (slot_coalesced_allocnos_live_ranges[n], ALLOCNO_LIVE_RANGES (a)))
+       return true;
       if (a == allocno)
        break;
     }
   return false;
 }
 
-/* Mark program points where coalesced allocnos represented by ALLOCNO
-   live.  */
+/* Update live ranges of slot to which coalesced allocnos represented
+   by ALLOCNO were assigned.  */
 static void
-set_coalesced_allocnos_live_points (ira_allocno_t allocno)
+setup_slot_coalesced_allocno_live_ranges (ira_allocno_t allocno)
 {
-  int i, n;
+  int n;
   ira_allocno_t a;
   allocno_live_range_t r;
 
@@ -2358,9 +2401,10 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
   for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
        a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
     {
-      for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
-       for (i = r->start; i <= r->finish; i++)
-         bitmap_set_bit (&coalesced_allocnos_living_at_program_points[i], n);
+      r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
+      slot_coalesced_allocnos_live_ranges[n]
+       = ira_merge_allocno_live_ranges
+         (slot_coalesced_allocnos_live_ranges[n], r);
       if (a == allocno)
        break;
     }
@@ -2374,14 +2418,15 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
 static bool
 coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
 {
-  int i, j, last_coalesced_allocno_num;
+  int i, j, n, last_coalesced_allocno_num;
   ira_allocno_t allocno, a;
   bool merged_p = false;
 
-  coalesced_allocnos_living_at_program_points
-    = (regset_head *) ira_allocate (sizeof (regset_head) * ira_max_point);
-  for (i = 0; i < ira_max_point; i++)
-    INIT_REG_SET (&coalesced_allocnos_living_at_program_points[i]);
+  slot_coalesced_allocnos_live_ranges
+    = (allocno_live_range_t *) ira_allocate (sizeof (allocno_live_range_t)
+                                            * ira_allocnos_num);
+  memset (slot_coalesced_allocnos_live_ranges, 0,
+         sizeof (allocno_live_range_t) * ira_allocnos_num);
   last_coalesced_allocno_num = 0;
   /* Coalesce non-conflicting spilled allocnos preferring most
      frequently used.  */
@@ -2390,18 +2435,18 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
       allocno = spilled_coalesced_allocnos[i];
       if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
          || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
-             && (ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)]
-                 || ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX)))
+             && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
+                 || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
        continue;
       for (j = 0; j < i; j++)
        {
          a = spilled_coalesced_allocnos[j];
+         n = ALLOCNO_TEMP (a);
          if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
              && (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
                  || (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
                      && ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX))
-             && ! coalesced_allocnos_live_at_points_p (allocno,
-                                                       ALLOCNO_TEMP (a)))
+             && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
            break;
        }
       if (j >= i)
@@ -2409,7 +2454,7 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
          /* No coalescing: set up number for coalesced allocnos
             represented by ALLOCNO.  */
          ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++;
-         set_coalesced_allocnos_live_points (allocno);
+         setup_slot_coalesced_allocno_live_ranges (allocno);
        }
       else
        {
@@ -2421,14 +2466,15 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
                     ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
                     ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
          ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a);
-         set_coalesced_allocnos_live_points (allocno);
+         setup_slot_coalesced_allocno_live_ranges (allocno);
          merge_allocnos (a, allocno);
          ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a);
        }
     }
-  for (i = 0; i < ira_max_point; i++)
-    CLEAR_REG_SET (&coalesced_allocnos_living_at_program_points[i]);
-  ira_free (coalesced_allocnos_living_at_program_points);
+  for (i = 0; i < ira_allocnos_num; i++)
+    ira_finish_allocno_live_range_list
+      (slot_coalesced_allocnos_live_ranges[i]);
+  ira_free (slot_coalesced_allocnos_live_ranges);
   return merged_p;
 }
 
@@ -2499,8 +2545,8 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n,
       if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
          || ALLOCNO_HARD_REGNO (allocno) >= 0
          || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
-             && (ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)]
-                 || ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX)))
+             && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
+                 || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
        continue;
       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
        fprintf (ira_dump_file, "      Slot %d (freq,size):", slot_num);
@@ -2829,8 +2875,8 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
                                    FIRST_PSEUDO_REGISTER, i, bi)
            {
              another_allocno = ira_regno_allocno_map[i];
-             if (ira_allocno_live_ranges_intersect_p (allocno,
-                                                      another_allocno))
+             if (allocnos_have_intersected_live_ranges_p (allocno,
+                                                          another_allocno))
                goto cont;
            }
          for (cost = 0, cp = ALLOCNO_COPIES (allocno);
@@ -2878,7 +2924,7 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
       EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
                                FIRST_PSEUDO_REGISTER, i, bi)
        {
-         ira_assert (! ira_pseudo_live_ranges_intersect_p (regno, i));
+         ira_assert (! pseudos_have_intersected_live_ranges_p (regno, i));
        }
       SET_REGNO_REG_SET (&slot->spilled_regs, regno);
       if (internal_flag_ira_verbose > 3 && ira_dump_file)
index 66376b6..6e7d769 100644 (file)
@@ -532,52 +532,6 @@ propagate_copies (void)
     }
 }
 
-/* Return TRUE if live ranges of allocnos A1 and A2 intersect.  It is
-   used to find a conflict for new allocnos or allocnos with the
-   different cover classes.  */
-bool
-ira_allocno_live_ranges_intersect_p (ira_allocno_t a1, ira_allocno_t a2)
-{
-  allocno_live_range_t r1, r2;
-
-  if (a1 == a2)
-    return false;
-  if (ALLOCNO_REG (a1) != NULL && ALLOCNO_REG (a2) != NULL
-      && (ORIGINAL_REGNO (ALLOCNO_REG (a1))
-         == ORIGINAL_REGNO (ALLOCNO_REG (a2))))
-    return false;
-  /* Remember the ranges are always kept ordered.  */
-  for (r1 = ALLOCNO_LIVE_RANGES (a1), r2 = ALLOCNO_LIVE_RANGES (a2);
-       r1 != NULL && r2 != NULL;)
-    {
-      if (r1->start > r2->finish)
-       r1 = r1->next;
-      else if (r2->start > r1->finish)
-       r2 = r2->next;
-      else
-       return true;
-    }
-  return false;
-}
-
-/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
-   intersect.  This should be used when there is only one region.
-   Currently this is used during reload.  */
-bool
-ira_pseudo_live_ranges_intersect_p (int regno1, int regno2)
-{
-  ira_allocno_t a1, a2;
-
-  ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
-             && regno2 >= FIRST_PSEUDO_REGISTER);
-  /* Reg info caclulated by dataflow infrastructure can be different
-     from one calculated by regclass.  */
-  if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
-      || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
-    return false;
-  return ira_allocno_live_ranges_intersect_p (a1, a2);
-}
-
 /* Array used to collect all conflict allocnos for given allocno.  */
 static ira_allocno_t *collected_conflict_allocnos;
 
index 0b2e928..7f5479b 100644 (file)
@@ -862,7 +862,14 @@ extern void ira_add_allocno_conflict (ira_allocno_t, ira_allocno_t);
 extern void ira_print_expanded_allocno (ira_allocno_t);
 extern allocno_live_range_t ira_create_allocno_live_range
                            (ira_allocno_t, int, int, allocno_live_range_t);
+extern allocno_live_range_t ira_copy_allocno_live_range_list
+                            (allocno_live_range_t);
+extern allocno_live_range_t ira_merge_allocno_live_ranges
+                            (allocno_live_range_t, allocno_live_range_t);
+extern bool ira_allocno_live_ranges_intersect_p (allocno_live_range_t,
+                                                allocno_live_range_t);
 extern void ira_finish_allocno_live_range (allocno_live_range_t);
+extern void ira_finish_allocno_live_range_list (allocno_live_range_t);
 extern void ira_free_allocno_updated_costs (ira_allocno_t);
 extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
                                   int, bool, rtx, ira_loop_tree_node_t);
@@ -898,8 +905,6 @@ extern void ira_compress_allocno_live_ranges (void);
 extern void ira_finish_allocno_live_ranges (void);
 
 /* ira-conflicts.c */
-extern bool ira_allocno_live_ranges_intersect_p (ira_allocno_t, ira_allocno_t);
-extern bool ira_pseudo_live_ranges_intersect_p (int, int);
 extern void ira_debug_conflicts (bool);
 extern void ira_build_conflicts (void);
 
index d0232f7..d7f4e3d 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1695,6 +1695,23 @@ expand_reg_info (int old_size)
     }
 }
 
+/* Return TRUE if there is too high register pressure in the function.
+   It is used to decide when stack slot sharing is worth to do.  */
+static bool
+too_high_register_pressure_p (void)
+{
+  int i;
+  enum reg_class cover_class;
+  
+  for (i = 0; i < ira_reg_class_cover_size; i++)
+    {
+      cover_class = ira_reg_class_cover[i];
+      if (ira_loop_tree_root->reg_pressure[cover_class] > 10000)
+       return true;
+    }
+  return false;
+}
+
 \f
 
 /* All natural loops.  */
@@ -1709,6 +1726,7 @@ ira (FILE *f)
   int max_regno_before_ira, ira_max_point_before_emit;
   int rebuild_p;
   int saved_flag_ira_algorithm;
+  int saved_flag_ira_share_spill_slots;
   basic_block bb;
 
   timevar_push (TV_IRA);
@@ -1792,6 +1810,13 @@ ira (FILE *f)
   loops_p = ira_build (optimize
                       && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
                           || flag_ira_algorithm == IRA_ALGORITHM_MIXED));
+
+  saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
+  if (too_high_register_pressure_p ())
+    /* It is just wasting compiler's time to pack spilled pseudos into
+       stack slots in this case -- prohibit it.  */ 
+    flag_ira_share_spill_slots = FALSE;
+
   ira_color ();
       
   ira_max_point_before_emit = ira_max_point;
@@ -1902,6 +1927,8 @@ ira (FILE *f)
     fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost);
   ira_destroy ();
   
+  flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
+
   flow_loops_free (&ira_loops);
   free_dominance_info (CDI_DOMINATORS);
   FOR_ALL_BB (bb)