tree.c (gimple_canonical_types_compatible_p): Do not compare function attributes.
[gcc.git] / gcc / lra-assigns.c
index b2045138b91d99e3411032dae7f3d04ba76069d8..994b04fc643db6b6b241defd1acb6ecef61cc921 100644 (file)
@@ -1,5 +1,5 @@
 /* Assign reload pseudos.
-   Copyright (C) 2010-2013 Free Software Foundation, Inc.
+   Copyright (C) 2010-2015 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -87,15 +87,50 @@ along with GCC; see the file COPYING3.      If not see
 #include "recog.h"
 #include "output.h"
 #include "regs.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "input.h"
 #include "function.h"
+#include "symtab.h"
+#include "flags.h"
+#include "statistics.h"
+#include "double-int.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "alias.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
 #include "expr.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "except.h"
 #include "df.h"
 #include "ira.h"
 #include "sparseset.h"
+#include "params.h"
 #include "lra-int.h"
 
+/* Current iteration number of the pass and current iteration number
+   of the pass after the latest spill pass when any former reload
+   pseudo was spilled.  */
+int lra_assignment_iter;
+int lra_assignment_iter_after_spill;
+
+/* Flag of spilling former reload pseudos on this pass.  */
+static bool former_reload_pseudo_spill_p;
+
 /* Array containing corresponding values of function
    lra_get_allocno_class.  It is used to speed up the code.  */
 static enum reg_class *regno_allocno_class_array;
@@ -116,6 +151,11 @@ struct regno_assign_info
 /* Map regno to the corresponding regno assignment info.  */
 static struct regno_assign_info *regno_assign_info;
 
+/* All inherited, subreg or optional pseudos created before last spill
+   sub-pass.  Such pseudos are permitted to get memory instead of hard
+   regs.  */
+static bitmap_head non_reload_pseudos;
+
 /* Process a pseudo copy with execution frequency COPY_FREQ connecting
    REGNO1 and REGNO2 to form threads.  */
 static void
@@ -194,6 +234,15 @@ reload_pseudo_compare_func (const void *v1p, const void *v2p)
   if ((diff = (ira_class_hard_regs_num[cl1]
               - ira_class_hard_regs_num[cl2])) != 0)
     return diff;
+  if ((diff
+       = (ira_reg_class_max_nregs[cl2][lra_reg_info[r2].biggest_mode]
+         - ira_reg_class_max_nregs[cl1][lra_reg_info[r1].biggest_mode])) != 0
+      /* The code below executes rarely as nregs == 1 in most cases.
+        So we should not worry about using faster data structures to
+        check reload pseudos.  */
+      && ! bitmap_bit_p (&non_reload_pseudos, r1)
+      && ! bitmap_bit_p (&non_reload_pseudos, r2))
+    return diff;
   if ((diff = (regno_assign_info[regno_assign_info[r2].first].freq
               - regno_assign_info[regno_assign_info[r1].first].freq)) != 0)
     return diff;
@@ -436,25 +485,40 @@ adjust_hard_regno_cost (int hard_regno, int incr)
    that register.  (If several registers have equal cost, the one with
    the highest priority wins.)  Return -1 on failure.
 
+   If FIRST_P, return the first available hard reg ignoring other
+   criteria, e.g. allocation cost.  This approach results in less hard
+   reg pool fragmentation and permit to allocate hard regs to reload
+   pseudos in complicated situations where pseudo sizes are different.
+
    If TRY_ONLY_HARD_REGNO >= 0, consider only that hard register,
-   otherwise consider all hard registers in REGNO's class.  */
+   otherwise consider all hard registers in REGNO's class.
+
+   If REGNO_SET is not empty, only hard registers from the set are
+   considered.  */
 static int
-find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
+find_hard_regno_for_1 (int regno, int *cost, int try_only_hard_regno,
+                      bool first_p, HARD_REG_SET regno_set)
 {
   HARD_REG_SET conflict_set;
   int best_cost = INT_MAX, best_priority = INT_MIN, best_usage = INT_MAX;
   lra_live_range_t r;
   int p, i, j, rclass_size, best_hard_regno, priority, hard_regno;
   int hr, conflict_hr, nregs;
-  enum machine_mode biggest_mode;
+  machine_mode biggest_mode;
   unsigned int k, conflict_regno;
-  int val, biggest_nregs, nregs_diff;
+  int offset, val, biggest_nregs, nregs_diff;
   enum reg_class rclass;
   bitmap_iterator bi;
   bool *rclass_intersect_p;
-  HARD_REG_SET impossible_start_hard_regs;
+  HARD_REG_SET impossible_start_hard_regs, available_regs;
 
-  COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
+  if (hard_reg_set_empty_p (regno_set))
+    COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
+  else
+    {
+      COMPL_HARD_REG_SET (conflict_set, regno_set);
+      IOR_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
+    }
   rclass = regno_allocno_class_array[regno];
   rclass_intersect_p = ira_reg_classes_intersect_p[rclass];
   curr_hard_regno_costs_check++;
@@ -508,9 +572,10 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
 #endif
   sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno);
   val = lra_reg_info[regno].val;
+  offset = lra_reg_info[regno].offset;
   CLEAR_HARD_REG_SET (impossible_start_hard_regs);
   EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
-    if (val == lra_reg_info[conflict_regno].val)
+    if (lra_reg_val_equal_p (conflict_regno, val, offset))
       {
        conflict_hr = live_pseudos_reg_renumber[conflict_regno];
        nregs = (hard_regno_nregs[conflict_hr]
@@ -538,7 +603,7 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
       }
   EXECUTE_IF_SET_IN_SPARSESET (conflict_reload_and_inheritance_pseudos,
                               conflict_regno)
-    if (val != lra_reg_info[conflict_regno].val)
+    if (!lra_reg_val_equal_p (conflict_regno, val, offset))
       {
        lra_assert (live_pseudos_reg_renumber[conflict_regno] < 0);
        if ((hard_regno
@@ -564,6 +629,8 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
   biggest_nregs = hard_regno_nregs[hard_regno][biggest_mode];
   nregs_diff = (biggest_nregs
                - hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (regno)]);
+  COPY_HARD_REG_SET (available_regs, reg_class_contents[rclass]);
+  AND_COMPL_HARD_REG_SET (available_regs, lra_no_alloc_regs);
   for (i = 0; i < rclass_size; i++)
     {
       if (try_only_hard_regno >= 0)
@@ -579,9 +646,9 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
          && (nregs_diff == 0
              || (WORDS_BIG_ENDIAN
                  ? (hard_regno - nregs_diff >= 0
-                    && TEST_HARD_REG_BIT (reg_class_contents[rclass],
+                    && TEST_HARD_REG_BIT (available_regs,
                                           hard_regno - nregs_diff))
-                 : TEST_HARD_REG_BIT (reg_class_contents[rclass],
+                 : TEST_HARD_REG_BIT (available_regs,
                                       hard_regno + nregs_diff))))
        {
          if (hard_regno_costs_check[hard_regno]
@@ -597,16 +664,14 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
                && ! df_regs_ever_live_p (hard_regno + j))
              /* It needs save restore.  */
              hard_regno_costs[hard_regno]
-               += 2 * ENTRY_BLOCK_PTR->next_bb->frequency;
+               += (2
+                   * REG_FREQ_FROM_BB (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb)
+                   + 1);
          priority = targetm.register_priority (hard_regno);
          if (best_hard_regno < 0 || hard_regno_costs[hard_regno] < best_cost
              || (hard_regno_costs[hard_regno] == best_cost
                  && (priority > best_priority
-                     /* Hard register usage leveling actually results
-                        in bigger code for targets with conditional
-                        execution like ARM because it reduces chance
-                        of if-conversion after LRA.  */
-                     || (! targetm.have_conditional_execution ()
+                     || (targetm.register_usage_leveling_p ()
                          && priority == best_priority
                          && best_usage > lra_hard_reg_usage[hard_regno]))))
            {
@@ -616,7 +681,7 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
              best_usage = lra_hard_reg_usage[hard_regno];
            }
        }
-      if (try_only_hard_regno >= 0)
+      if (try_only_hard_regno >= 0 || (first_p && best_hard_regno >= 0))
        break;
     }
   if (best_hard_regno >= 0)
@@ -624,6 +689,33 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
   return best_hard_regno;
 }
 
+/* A wrapper for find_hard_regno_for_1 (see comments for that function
+   description).  This function tries to find a hard register for
+   preferred class first if it is worth.  */
+static int
+find_hard_regno_for (int regno, int *cost, int try_only_hard_regno, bool first_p)
+{
+  int hard_regno;
+  HARD_REG_SET regno_set;
+
+  /* Only original pseudos can have a different preferred class.  */
+  if (try_only_hard_regno < 0 && regno < lra_new_regno_start)
+    {
+      enum reg_class pref_class = reg_preferred_class (regno);
+      
+      if (regno_allocno_class_array[regno] != pref_class)
+       {
+         hard_regno = find_hard_regno_for_1 (regno, cost, -1, first_p,
+                                             reg_class_contents[pref_class]);
+         if (hard_regno >= 0)
+           return hard_regno;
+       }
+    }
+  CLEAR_HARD_REG_SET (regno_set);
+  return find_hard_regno_for_1 (regno, cost, try_only_hard_regno, first_p,
+                               regno_set);
+}
+
 /* Current value used for checking elements in
    update_hard_regno_preference_check. */
 static int curr_update_hard_regno_preference_check;
@@ -675,6 +767,19 @@ update_hard_regno_preference (int regno, int hard_regno, int div)
     }
 }
 
+/* Return prefix title for pseudo REGNO.  */
+static const char *
+pseudo_prefix_title (int regno)
+{
+  return
+    (regno < lra_constraint_new_regno_start ? ""
+     : bitmap_bit_p (&lra_inheritance_pseudos, regno) ? "inheritance "
+     : bitmap_bit_p (&lra_split_regs, regno) ? "split "
+     : bitmap_bit_p (&lra_optional_reload_pseudos, regno) ? "optional reload "
+     : bitmap_bit_p (&lra_subreg_reload_pseudos, regno) ? "subreg reload "
+     : "reload ");
+}
+
 /* Update REG_RENUMBER and other pseudo preferences by assignment of
    HARD_REGNO to pseudo REGNO and print about it if PRINT_P.  */
 void
@@ -695,13 +800,7 @@ lra_setup_reg_renumber (int regno, int hard_regno, bool print_p)
       lra_hard_reg_usage[hr + i] += lra_reg_info[regno].freq;
   if (print_p && lra_dump_file != NULL)
     fprintf (lra_dump_file, "     Assign %d to %sr%d (freq=%d)\n",
-            reg_renumber[regno],
-            regno < lra_constraint_new_regno_start
-            ? ""
-            : bitmap_bit_p (&lra_inheritance_pseudos, regno) ? "inheritance "
-            : bitmap_bit_p (&lra_split_regs, regno) ? "split "
-            : bitmap_bit_p (&lra_optional_reload_pseudos, regno)
-            ? "optional reload ": "reload ",
+            reg_renumber[regno], pseudo_prefix_title (regno),
             regno, lra_reg_info[regno].freq);
   if (hard_regno >= 0)
     {
@@ -734,7 +833,7 @@ static void
 setup_try_hard_regno_pseudos (int p, enum reg_class rclass)
 {
   int i, hard_regno;
-  enum machine_mode mode;
+  machine_mode mode;
   unsigned int spill_regno;
   bitmap_iterator bi;
 
@@ -795,16 +894,23 @@ static int *sorted_reload_pseudos;
    to be spilled), we take into account not only how REGNO will
    benefit from the spills but also how other reload pseudos not yet
    assigned to hard registers benefit from the spills too.  In very
-   rare cases, the function can fail and return -1.  */
+   rare cases, the function can fail and return -1.
+
+   If FIRST_P, return the first available hard reg ignoring other
+   criteria, e.g. allocation cost and cost of spilling non-reload
+   pseudos.  This approach results in less hard reg pool fragmentation
+   and permit to allocate hard regs to reload pseudos in complicated
+   situations where pseudo sizes are different.  */
 static int
-spill_for (int regno, bitmap spilled_pseudo_bitmap)
+spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
 {
   int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size;
   int reload_hard_regno, reload_cost;
-  enum machine_mode mode;
+  machine_mode mode;
   enum reg_class rclass;
   unsigned int spill_regno, reload_regno, uid;
   int insn_pseudos_num, best_insn_pseudos_num;
+  int bad_spills_num, smallest_bad_spills_num;
   lra_live_range_t r;
   bitmap_iterator bi;
 
@@ -823,6 +929,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
   best_hard_regno = -1;
   best_cost = INT_MAX;
   best_insn_pseudos_num = INT_MAX;
+  smallest_bad_spills_num = INT_MAX;
   rclass_size = ira_class_hard_regs_num[rclass];
   mode = PSEUDO_REGNO_MODE (regno);
   /* Invalidate try_hard_reg_pseudos elements.  */
@@ -844,12 +951,16 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
        }
       /* Spill pseudos.         */
       EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
-       if ((int) spill_regno >= lra_constraint_new_regno_start
-           && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
-           && ! bitmap_bit_p (&lra_split_regs, spill_regno)
-           && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))
+       if ((pic_offset_table_rtx != NULL
+            && spill_regno == REGNO (pic_offset_table_rtx))
+           || ((int) spill_regno >= lra_constraint_new_regno_start
+               && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
+               && ! bitmap_bit_p (&lra_split_regs, spill_regno)
+               && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno)
+               && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)))
          goto fail;
       insn_pseudos_num = 0;
+      bad_spills_num = 0;
       if (lra_dump_file != NULL)
        fprintf (lra_dump_file, "        Trying %d:", hard_regno);
       sparseset_clear (live_range_reload_inheritance_pseudos);
@@ -857,6 +968,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
        {
          if (bitmap_bit_p (&insn_conflict_pseudos, spill_regno))
            insn_pseudos_num++;
+         if (spill_regno >= (unsigned int) lra_bad_spill_regno_start)
+           bad_spills_num++;
          for (r = lra_reg_info[spill_regno].live_ranges;
               r != NULL;
               r = r->next)
@@ -875,14 +988,16 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
            }
        }
       n = 0;
-      EXECUTE_IF_SET_IN_SPARSESET (live_range_reload_inheritance_pseudos,
-                                  reload_regno)
-       if ((int) reload_regno != regno
-           && (ira_reg_classes_intersect_p
-               [rclass][regno_allocno_class_array[reload_regno]])
-           && live_pseudos_reg_renumber[reload_regno] < 0
-           && find_hard_regno_for (reload_regno, &cost, -1) < 0)
-         sorted_reload_pseudos[n++] = reload_regno;
+      if (sparseset_cardinality (live_range_reload_inheritance_pseudos)
+         <= (unsigned)LRA_MAX_CONSIDERED_RELOAD_PSEUDOS)
+       EXECUTE_IF_SET_IN_SPARSESET (live_range_reload_inheritance_pseudos,
+                                    reload_regno)
+         if ((int) reload_regno != regno
+             && (ira_reg_classes_intersect_p
+                 [rclass][regno_allocno_class_array[reload_regno]])
+             && live_pseudos_reg_renumber[reload_regno] < 0
+             && find_hard_regno_for (reload_regno, &cost, -1, first_p) < 0)
+           sorted_reload_pseudos[n++] = reload_regno;
       EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
        {
          update_lives (spill_regno, true);
@@ -890,7 +1005,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
            fprintf (lra_dump_file, " spill %d(freq=%d)",
                     spill_regno, lra_reg_info[spill_regno].freq);
        }
-      hard_regno = find_hard_regno_for (regno, &cost, -1);
+      hard_regno = find_hard_regno_for (regno, &cost, -1, first_p);
       if (hard_regno >= 0)
        {
          assign_temporarily (regno, hard_regno);
@@ -902,7 +1017,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
              lra_assert (live_pseudos_reg_renumber[reload_regno] < 0);
              if ((reload_hard_regno
                   = find_hard_regno_for (reload_regno,
-                                         &reload_cost, -1)) >= 0)
+                                         &reload_cost, -1, first_p)) >= 0)
                {
                  if (lra_dump_file != NULL)
                    fprintf (lra_dump_file, " assign %d(cost=%d)",
@@ -913,27 +1028,31 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
            }
          EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
            {
-             rtx x;
+             rtx_insn_list *x;
 
              cost += lra_reg_info[spill_regno].freq;
              if (ira_reg_equiv[spill_regno].memory != NULL
                  || ira_reg_equiv[spill_regno].constant != NULL)
                for (x = ira_reg_equiv[spill_regno].init_insns;
                     x != NULL;
-                    x = XEXP (x, 1))
-                 cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (XEXP (x, 0)));
+                    x = x->next ())
+                 cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (x->insn ()));
            }
          if (best_insn_pseudos_num > insn_pseudos_num
              || (best_insn_pseudos_num == insn_pseudos_num
-                 && best_cost > cost))
+                 && (bad_spills_num < smallest_bad_spills_num
+                     || (bad_spills_num == smallest_bad_spills_num
+                         && best_cost > cost))))
            {
              best_insn_pseudos_num = insn_pseudos_num;
+             smallest_bad_spills_num = bad_spills_num;
              best_cost = cost;
              best_hard_regno = hard_regno;
              bitmap_copy (&best_spill_pseudos_bitmap, &spill_pseudos_bitmap);
              if (lra_dump_file != NULL)
-               fprintf (lra_dump_file, "        Now best %d(cost=%d)\n",
-                        hard_regno, cost);
+               fprintf (lra_dump_file,
+                        "       Now best %d(cost=%d, bad_spills=%d, insn_pseudos=%d)\n",
+                        hard_regno, cost, bad_spills_num, insn_pseudos_num);
            }
          assign_temporarily (regno, -1);
          for (j = 0; j < n; j++)
@@ -954,16 +1073,11 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
   /* Spill: */
   EXECUTE_IF_SET_IN_BITMAP (&best_spill_pseudos_bitmap, 0, spill_regno, bi)
     {
+      if ((int) spill_regno >= lra_constraint_new_regno_start)
+       former_reload_pseudo_spill_p = true;
       if (lra_dump_file != NULL)
        fprintf (lra_dump_file, "      Spill %sr%d(hr=%d, freq=%d) for r%d\n",
-                ((int) spill_regno < lra_constraint_new_regno_start
-                 ? ""
-                 : bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
-                 ? "inheritance "
-                 : bitmap_bit_p (&lra_split_regs, spill_regno)
-                 ? "split "
-                 : bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)
-                 ? "optional reload " : "reload "),
+                pseudo_prefix_title (spill_regno),
                 spill_regno, reg_renumber[spill_regno],
                 lra_reg_info[spill_regno].freq, regno);
       update_lives (spill_regno, true);
@@ -1007,9 +1121,9 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
 {
   int p, i, j, n, regno, hard_regno;
   unsigned int k, conflict_regno;
-  int val;
+  int val, offset;
   HARD_REG_SET conflict_set;
-  enum machine_mode mode;
+  machine_mode mode;
   lra_live_range_t r;
   bitmap_iterator bi;
   int max_regno = max_reg_num ();
@@ -1022,9 +1136,15 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
       return;
     }
   for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    if (reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0)
+    if ((pic_offset_table_rtx == NULL_RTX
+        || i != (int) REGNO (pic_offset_table_rtx))
+       && reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0)
       sorted_pseudos[n++] = i;
   qsort (sorted_pseudos, n, sizeof (int), pseudo_compare_func);
+  if (pic_offset_table_rtx != NULL_RTX
+      && (regno = REGNO (pic_offset_table_rtx)) >= FIRST_PSEUDO_REGISTER
+      && reg_renumber[regno] >= 0 && lra_reg_info[regno].nrefs > 0)
+    sorted_pseudos[n++] = regno;
   for (i = n - 1; i >= 0; i--)
     {
       regno = sorted_pseudos[i];
@@ -1050,8 +1170,9 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
       COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
       IOR_HARD_REG_SET (conflict_set, lra_reg_info[regno].conflict_hard_regs);
       val = lra_reg_info[regno].val;
+      offset = lra_reg_info[regno].offset;
       EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
-       if (val != lra_reg_info[conflict_regno].val
+       if (!lra_reg_val_equal_p (conflict_regno, val, offset)
            /* If it is multi-register pseudos they should start on
               the same hard register.  */
            || hard_regno != reg_renumber[conflict_regno])
@@ -1069,6 +1190,8 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
           j++)
        lra_hard_reg_usage[hard_regno + j] -= lra_reg_info[regno].freq;
       reg_renumber[regno] = -1;
+      if (regno >= lra_constraint_new_regno_start)
+       former_reload_pseudo_spill_p = true;
       if (lra_dump_file != NULL)
        fprintf (lra_dump_file, "    Spill r%d after risky transformations\n",
                 regno);
@@ -1130,8 +1253,8 @@ improve_inheritance (bitmap changed_pseudos)
                   regno, hard_regno, another_regno, another_hard_regno);
              update_lives (another_regno, true);
              lra_setup_reg_renumber (another_regno, -1, false);
-             if (hard_regno
-                 == find_hard_regno_for (another_regno, &cost, hard_regno))
+             if (hard_regno == find_hard_regno_for (another_regno, &cost,
+                                                    hard_regno, false))
                assign_hard_regno (hard_regno, another_regno);
              else
                assign_hard_regno (another_hard_regno, another_regno);
@@ -1148,16 +1271,50 @@ static bitmap_head all_spilled_pseudos;
 /* All pseudos whose allocation was changed.  */
 static bitmap_head changed_pseudo_bitmap;
 
+
+/* Add to LIVE_RANGE_HARD_REG_PSEUDOS all pseudos conflicting with
+   REGNO and whose hard regs can be assigned to REGNO.  */
+static void
+find_all_spills_for (int regno)
+{
+  int p;
+  lra_live_range_t r;
+  unsigned int k;
+  bitmap_iterator bi;
+  enum reg_class rclass;
+  bool *rclass_intersect_p;
+
+  rclass = regno_allocno_class_array[regno];
+  rclass_intersect_p = ira_reg_classes_intersect_p[rclass];
+  for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
+    {
+      EXECUTE_IF_SET_IN_BITMAP (&live_hard_reg_pseudos[r->start], 0, k, bi)
+       if (rclass_intersect_p[regno_allocno_class_array[k]])
+         sparseset_set_bit (live_range_hard_reg_pseudos, k);
+      for (p = r->start + 1; p <= r->finish; p++)
+       {
+         lra_live_range_t r2;
+
+         for (r2 = start_point_ranges[p];
+              r2 != NULL;
+              r2 = r2->start_next)
+           {
+             if (live_pseudos_reg_renumber[r2->regno] >= 0
+                 && rclass_intersect_p[regno_allocno_class_array[r2->regno]])
+               sparseset_set_bit (live_range_hard_reg_pseudos, r2->regno);
+           }
+       }
+    }
+}
+
 /* Assign hard registers to reload pseudos and other pseudos.  */
 static void
 assign_by_spills (void)
 {
   int i, n, nfails, iter, regno, hard_regno, cost, restore_regno;
-  rtx insn;
-  basic_block bb;
+  rtx_insn *insn;
   bitmap_head changed_insns, do_not_assign_nonreload_pseudos;
-  bitmap_head non_reload_pseudos;
-  unsigned int u;
+  unsigned int u, conflict_regno;
   bitmap_iterator bi;
   bool reload_p;
   int max_regno = max_reg_num ();
@@ -1178,6 +1335,7 @@ assign_by_spills (void)
   bitmap_initialize (&changed_insns, &reg_obstack);
   bitmap_initialize (&non_reload_pseudos, &reg_obstack);
   bitmap_ior (&non_reload_pseudos, &lra_inheritance_pseudos, &lra_split_regs);
+  bitmap_ior_into (&non_reload_pseudos, &lra_subreg_reload_pseudos);
   bitmap_ior_into (&non_reload_pseudos, &lra_optional_reload_pseudos);
   for (iter = 0; iter <= 1; iter++)
     {
@@ -1193,10 +1351,10 @@ assign_by_spills (void)
                     ORIGINAL_REGNO (regno_reg_rtx[regno]),
                     lra_reg_info[regno].freq, regno_assign_info[regno].first,
                     regno_assign_info[regno_assign_info[regno].first].freq);
-         hard_regno = find_hard_regno_for (regno, &cost, -1);
+         hard_regno = find_hard_regno_for (regno, &cost, -1, iter == 1);
          reload_p = ! bitmap_bit_p (&non_reload_pseudos, regno);
          if (hard_regno < 0 && reload_p)
-           hard_regno = spill_for (regno, &all_spilled_pseudos);
+           hard_regno = spill_for (regno, &all_spilled_pseudos, iter == 1);
          if (hard_regno < 0)
            {
              if (reload_p)
@@ -1219,9 +1377,9 @@ assign_by_spills (void)
        break;
       if (iter > 0)
        {
-         /* We did not assign hard regs to reload pseudos after two
-            iteration.  It means something is wrong with asm insn
-            constraints.  Report it.  */
+         /* We did not assign hard regs to reload pseudos after two iterations.
+            Either it's an asm and something is wrong with the constraints, or
+            we have run out of spill registers; error out in either case.  */
          bool asm_p = false;
          bitmap_head failed_reload_insns;
 
@@ -1232,7 +1390,7 @@ assign_by_spills (void)
              bitmap_ior_into (&failed_reload_insns,
                               &lra_reg_info[regno].insn_bitmap);
              /* Assign an arbitrary hard register of regno class to
-                avoid further trouble with the asm insns.  */
+                avoid further trouble with this insn.  */
              bitmap_clear_bit (&all_spilled_pseudos, regno);
              assign_hard_regno
                (ira_class_hard_regs[regno_allocno_class_array[regno]][0],
@@ -1264,65 +1422,52 @@ assign_by_spills (void)
                      lra_set_insn_deleted (insn);
                    }
                }
+             else if (!asm_p)
+               {
+                 error ("unable to find a register to spill");
+                 fatal_insn ("this is the insn:", insn);
+               }
            }
-         lra_assert (asm_p);
          break;
        }
-      /* This is a very rare event.  We can not assign a hard
-        register to reload pseudo because the hard register was
-        assigned to another reload pseudo on a previous
-        assignment pass.  For x86 example, on the 1st pass we
-        assigned CX (although another hard register could be used
-        for this) to reload pseudo in an insn, on the 2nd pass we
-        need CX (and only this) hard register for a new reload
-        pseudo in the same insn.  */
+      /* This is a very rare event.  We can not assign a hard register
+        to reload pseudo because the hard register was assigned to
+        another reload pseudo on a previous assignment pass.  For x86
+        example, on the 1st pass we assigned CX (although another
+        hard register could be used for this) to reload pseudo in an
+        insn, on the 2nd pass we need CX (and only this) hard
+        register for a new reload pseudo in the same insn.  Another
+        possible situation may occur in assigning to multi-regs
+        reload pseudos when hard regs pool is too fragmented even
+        after spilling non-reload pseudos.
+
+        We should do something radical here to succeed.  Here we
+        spill *all* conflicting pseudos and reassign them.  */
       if (lra_dump_file != NULL)
        fprintf (lra_dump_file, "  2nd iter for reload pseudo assignments:\n");
+      sparseset_clear (live_range_hard_reg_pseudos);
       for (i = 0; i < nfails; i++)
        {
          if (lra_dump_file != NULL)
            fprintf (lra_dump_file, "    Reload r%d assignment failure\n",
                     sorted_pseudos[i]);
-         bitmap_ior_into (&changed_insns,
-                          &lra_reg_info[sorted_pseudos[i]].insn_bitmap);
+         find_all_spills_for (sorted_pseudos[i]);
+       }
+      EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
+       {
+         if ((int) conflict_regno >= lra_constraint_new_regno_start)
+           {
+             sorted_pseudos[nfails++] = conflict_regno;
+             former_reload_pseudo_spill_p = true;
+           }
+         if (lra_dump_file != NULL)
+           fprintf (lra_dump_file, "     Spill %s r%d(hr=%d, freq=%d)\n",
+                    pseudo_prefix_title (conflict_regno), conflict_regno,
+                    reg_renumber[conflict_regno],
+                    lra_reg_info[conflict_regno].freq);
+         update_lives (conflict_regno, true);
+         lra_setup_reg_renumber (conflict_regno, -1, false);
        }
-
-      /* FIXME: Look up the changed insns in the cached LRA insn data using
-        an EXECUTE_IF_SET_IN_BITMAP over changed_insns.  */
-      FOR_EACH_BB (bb)
-       FOR_BB_INSNS (bb, insn)
-       if (bitmap_bit_p (&changed_insns, INSN_UID (insn)))
-         {
-           lra_insn_recog_data_t data;
-           struct lra_insn_reg *r;
-
-           data = lra_get_insn_recog_data (insn);
-           for (r = data->regs; r != NULL; r = r->next)
-             {
-               regno = r->regno;
-               /* A reload pseudo did not get a hard register on the
-                  first iteration because of the conflict with
-                  another reload pseudos in the same insn.  So we
-                  consider only reload pseudos assigned to hard
-                  registers.  We shall exclude inheritance pseudos as
-                  they can occur in original insns (not reload ones).
-                  We can omit the check for split pseudos because
-                  they occur only in move insns containing non-reload
-                  pseudos.  */
-               if (regno < lra_constraint_new_regno_start
-                   || bitmap_bit_p (&lra_inheritance_pseudos, regno)
-                   || reg_renumber[regno] < 0)
-                 continue;
-               sorted_pseudos[nfails++] = regno;
-               if (lra_dump_file != NULL)
-                 fprintf (lra_dump_file,
-                          "      Spill reload r%d(hr=%d, freq=%d)\n",
-                          regno, reg_renumber[regno],
-                          lra_reg_info[regno].freq);
-               update_lives (regno, true);
-               lra_setup_reg_renumber (regno, -1, false);
-             }
-         }
       n = nfails;
     }
   improve_inheritance (&changed_pseudo_bitmap);
@@ -1352,6 +1497,7 @@ assign_by_spills (void)
                 && lra_reg_info[i].restore_regno >= 0)
             || (bitmap_bit_p (&lra_split_regs, i)
                 && lra_reg_info[i].restore_regno >= 0)
+            || bitmap_bit_p (&lra_subreg_reload_pseudos, i)
             || bitmap_bit_p (&lra_optional_reload_pseudos, i))
            && reg_renumber[i] < 0 && lra_reg_info[i].nrefs != 0
            && regno_allocno_class_array[i] != NO_REGS)
@@ -1363,7 +1509,7 @@ assign_by_spills (void)
       for (i = 0; i < n; i++)
        {
          regno = sorted_pseudos[i];
-         hard_regno = find_hard_regno_for (regno, &cost, -1);
+         hard_regno = find_hard_regno_for (regno, &cost, -1, false);
          if (hard_regno >= 0)
            {
              assign_hard_regno (hard_regno, regno);
@@ -1372,6 +1518,32 @@ assign_by_spills (void)
                 alternatives of insns containing the pseudo.  */
              bitmap_set_bit (&changed_pseudo_bitmap, regno);
            }
+         else
+           {
+             enum reg_class rclass = lra_get_allocno_class (regno);
+             enum reg_class spill_class;
+             
+             if (targetm.spill_class == NULL
+                 || lra_reg_info[regno].restore_regno < 0
+                 || ! bitmap_bit_p (&lra_inheritance_pseudos, regno)
+                 || (spill_class
+                     = ((enum reg_class)
+                        targetm.spill_class
+                        ((reg_class_t) rclass,
+                         PSEUDO_REGNO_MODE (regno)))) == NO_REGS)
+               continue;
+             regno_allocno_class_array[regno] = spill_class;
+             hard_regno = find_hard_regno_for (regno, &cost, -1, false);
+             if (hard_regno < 0)
+               regno_allocno_class_array[regno] = rclass;
+             else
+               {
+                 setup_reg_classes
+                   (regno, spill_class, spill_class, spill_class);
+                 assign_hard_regno (hard_regno, regno);
+                 bitmap_set_bit (&changed_pseudo_bitmap, regno);
+               }
+           }
        }
     }
   free (update_hard_regno_preference_check);
@@ -1401,23 +1573,29 @@ lra_assign (void)
   int max_regno = max_reg_num ();
 
   timevar_push (TV_LRA_ASSIGN);
+  lra_assignment_iter++;
+  if (lra_dump_file != NULL)
+    fprintf (lra_dump_file, "\n********** Assignment #%d: **********\n\n",
+            lra_assignment_iter);
   init_lives ();
   sorted_pseudos = XNEWVEC (int, max_regno);
   sorted_reload_pseudos = XNEWVEC (int, max_regno);
   regno_allocno_class_array = XNEWVEC (enum reg_class, max_regno);
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     regno_allocno_class_array[i] = lra_get_allocno_class (i);
+  former_reload_pseudo_spill_p = false;
   init_regno_assign_info ();
   bitmap_initialize (&all_spilled_pseudos, &reg_obstack);
   create_live_range_start_chains ();
   setup_live_pseudos_and_spill_after_risky_transforms (&all_spilled_pseudos);
 #ifdef ENABLE_CHECKING
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
-       && lra_reg_info[i].call_p
-       && overlaps_hard_reg_set_p (call_used_reg_set,
-                                   PSEUDO_REGNO_MODE (i), reg_renumber[i]))
-      gcc_unreachable ();
+  if (!flag_ipa_ra)
+    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+      if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
+         && lra_reg_info[i].call_p
+         && overlaps_hard_reg_set_p (call_used_reg_set,
+                                     PSEUDO_REGNO_MODE (i), reg_renumber[i]))
+       gcc_unreachable ();
 #endif
   /* Setup insns to process on the next constraint pass.  */
   bitmap_initialize (&changed_pseudo_bitmap, &reg_obstack);
@@ -1453,5 +1631,11 @@ lra_assign (void)
   free (sorted_reload_pseudos);
   finish_lives ();
   timevar_pop (TV_LRA_ASSIGN);
+  if (former_reload_pseudo_spill_p)
+    lra_assignment_iter_after_spill++;
+  if (lra_assignment_iter_after_spill > LRA_MAX_ASSIGNMENT_ITERATION_NUMBER)
+    internal_error
+      ("Maximum number of LRA assignment passes is achieved (%d)\n",
+       LRA_MAX_ASSIGNMENT_ITERATION_NUMBER);
   return no_spills_p;
 }