tree.c (gimple_canonical_types_compatible_p): Do not compare function attributes.
[gcc.git] / gcc / lra-assigns.c
index 03c2506d826a56ba9abaf69ea0b89fe038c1c911..994b04fc643db6b6b241defd1acb6ecef61cc921 100644 (file)
@@ -1,5 +1,5 @@
 /* Assign reload pseudos.
-   Copyright (C) 2010-2014 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,8 +87,33 @@ 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"
@@ -97,6 +122,15 @@ along with GCC; see the file COPYING3.      If not see
 #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;
@@ -457,17 +491,20 @@ adjust_hard_regno_cost (int hard_regno, int incr)
    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,
-                    bool first_p)
+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 offset, val, biggest_nregs, nregs_diff;
   enum reg_class rclass;
@@ -475,7 +512,13 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno,
   bool *rclass_intersect_p;
   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++;
@@ -646,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;
@@ -763,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;
 
@@ -836,10 +906,11 @@ 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;
 
@@ -858,6 +929,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
   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.  */
@@ -879,13 +951,16 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
        }
       /* 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_subreg_reload_pseudos, 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);
@@ -893,6 +968,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
        {
          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)
@@ -951,27 +1028,31 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
            }
          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++)
@@ -992,6 +1073,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
   /* 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",
                 pseudo_prefix_title (spill_regno),
@@ -1040,7 +1123,7 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap
   unsigned int k, conflict_regno;
   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 ();
@@ -1053,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];
@@ -1101,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);
@@ -1221,7 +1312,7 @@ static void
 assign_by_spills (void)
 {
   int i, n, nfails, iter, regno, hard_regno, cost, restore_regno;
-  rtx insn;
+  rtx_insn *insn;
   bitmap_head changed_insns, do_not_assign_nonreload_pseudos;
   unsigned int u, conflict_regno;
   bitmap_iterator bi;
@@ -1286,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;
 
@@ -1299,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],
@@ -1331,8 +1422,12 @@ 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
@@ -1361,7 +1456,10 @@ assign_by_spills (void)
       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;
+           {
+             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,
@@ -1420,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);
@@ -1449,18 +1573,23 @@ 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
-  if (!flag_use_caller_save)
+  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
@@ -1502,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;
 }