Daily bump.
[gcc.git] / gcc / ira-costs.c
index 38d0e0edeee82e788a924dd806163c5968a1b8e6..122815b80ffe6253d1e176ef6a4c4c954c70c57c 100644 (file)
@@ -28,6 +28,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "tm_p.h"
 #include "flags.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "regs.h"
 #include "addresses.h"
@@ -118,7 +127,7 @@ struct cost_classes
   /* Container of the cost classes.  */
   enum reg_class classes[N_REG_CLASSES];
   /* Map reg class -> index of the reg class in the previous array.
-     -1 if it is not a cost classe.  */
+     -1 if it is not a cost class.  */
   int index[N_REG_CLASSES];
   /* Map hard regno index of first class in array CLASSES containing
      the hard regno, -1 otherwise.  */
@@ -176,6 +185,31 @@ static cost_classes_t cost_classes_aclass_cache[N_REG_CLASSES];
 /* Map mode -> cost classes for pseudo of give mode.  */
 static cost_classes_t cost_classes_mode_cache[MAX_MACHINE_MODE];
 
+/* Cost classes that include all classes in ira_important_classes.  */
+static cost_classes all_cost_classes;
+
+/* Use the array of classes in CLASSES_PTR to fill out the rest of
+   the structure.  */
+static void
+complete_cost_classes (cost_classes_t classes_ptr)
+{
+  for (int i = 0; i < N_REG_CLASSES; i++)
+    classes_ptr->index[i] = -1;
+  for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    classes_ptr->hard_regno_index[i] = -1;
+  for (int i = 0; i < classes_ptr->num; i++)
+    {
+      enum reg_class cl = classes_ptr->classes[i];
+      classes_ptr->index[cl] = i;
+      for (int j = ira_class_hard_regs_num[cl] - 1; j >= 0; j--)
+       {
+         unsigned int hard_regno = ira_class_hard_regs[cl][j];
+         if (classes_ptr->hard_regno_index[hard_regno] < 0)
+           classes_ptr->hard_regno_index[hard_regno] = i;
+       }
+    }
+}
+
 /* Initialize info about the cost classes for each pseudo.  */
 static void
 initiate_regno_cost_classes (void)
@@ -189,6 +223,10 @@ initiate_regno_cost_classes (void)
   memset (cost_classes_mode_cache, 0,
          sizeof (cost_classes_t) * MAX_MACHINE_MODE);
   cost_classes_htab = new hash_table<cost_classes_hasher> (200);
+  all_cost_classes.num = ira_important_classes_num;
+  for (int i = 0; i < ira_important_classes_num; i++)
+    all_cost_classes.classes[i] = ira_important_classes[i];
+  complete_cost_classes (&all_cost_classes);
 }
 
 /* Create new cost classes from cost classes FROM and set up members
@@ -200,27 +238,105 @@ static cost_classes_t
 setup_cost_classes (cost_classes_t from)
 {
   cost_classes_t classes_ptr;
-  enum reg_class cl;
-  int i, j, hard_regno;
 
   classes_ptr = (cost_classes_t) ira_allocate (sizeof (struct cost_classes));
   classes_ptr->num = from->num;
-  for (i = 0; i < N_REG_CLASSES; i++)
-    classes_ptr->index[i] = -1;
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    classes_ptr->hard_regno_index[i] = -1;
-  for (i = 0; i < from->num; i++)
+  for (int i = 0; i < from->num; i++)
+    classes_ptr->classes[i] = from->classes[i];
+  complete_cost_classes (classes_ptr);
+  return classes_ptr;
+}
+
+/* Return a version of FULL that only considers registers in REGS that are
+   valid for mode MODE.  Both FULL and the returned class are globally
+   allocated.  */
+static cost_classes_t
+restrict_cost_classes (cost_classes_t full, machine_mode mode,
+                      const HARD_REG_SET &regs)
+{
+  static struct cost_classes narrow;
+  int map[N_REG_CLASSES];
+  narrow.num = 0;
+  for (int i = 0; i < full->num; i++)
     {
-      cl = classes_ptr->classes[i] = from->classes[i];
-      classes_ptr->index[cl] = i;
-      for (j = ira_class_hard_regs_num[cl] - 1; j >= 0; j--)
+      /* Assume that we'll drop the class.  */
+      map[i] = -1;
+
+      /* Ignore classes that are too small for the mode.  */
+      enum reg_class cl = full->classes[i];
+      if (!contains_reg_of_mode[cl][mode])
+       continue;
+
+      /* Calculate the set of registers in CL that belong to REGS and
+        are valid for MODE.  */
+      HARD_REG_SET valid_for_cl;
+      COPY_HARD_REG_SET (valid_for_cl, reg_class_contents[cl]);
+      AND_HARD_REG_SET (valid_for_cl, regs);
+      AND_COMPL_HARD_REG_SET (valid_for_cl,
+                             ira_prohibited_class_mode_regs[cl][mode]);
+      AND_COMPL_HARD_REG_SET (valid_for_cl, ira_no_alloc_regs);
+      if (hard_reg_set_empty_p (valid_for_cl))
+       continue;
+
+      /* Don't use this class if the set of valid registers is a subset
+        of an existing class.  For example, suppose we have two classes
+        GR_REGS and FR_REGS and a union class GR_AND_FR_REGS.  Suppose
+        that the mode changes allowed by FR_REGS are not as general as
+        the mode changes allowed by GR_REGS.
+
+        In this situation, the mode changes for GR_AND_FR_REGS could
+        either be seen as the union or the intersection of the mode
+        changes allowed by the two subclasses.  The justification for
+        the union-based definition would be that, if you want a mode
+        change that's only allowed by GR_REGS, you can pick a register
+        from the GR_REGS subclass.  The justification for the
+        intersection-based definition would be that every register
+        from the class would allow the mode change.
+
+        However, if we have a register that needs to be in GR_REGS,
+        using GR_AND_FR_REGS with the intersection-based definition
+        would be too pessimistic, since it would bring in restrictions
+        that only apply to FR_REGS.  Conversely, if we have a register
+        that needs to be in FR_REGS, using GR_AND_FR_REGS with the
+        union-based definition would lose the extra restrictions
+        placed on FR_REGS.  GR_AND_FR_REGS is therefore only useful
+        for cases where GR_REGS and FP_REGS are both valid.  */
+      int pos;
+      for (pos = 0; pos < narrow.num; ++pos)
        {
-         hard_regno = ira_class_hard_regs[cl][j];
-         if (classes_ptr->hard_regno_index[hard_regno] < 0)
-           classes_ptr->hard_regno_index[hard_regno] = i;
+         enum reg_class cl2 = narrow.classes[pos];
+         if (hard_reg_set_subset_p (valid_for_cl, reg_class_contents[cl2]))
+           break;
+       }
+      map[i] = pos;
+      if (pos == narrow.num)
+       {
+         /* If several classes are equivalent, prefer to use the one
+            that was chosen as the allocno class.  */
+         enum reg_class cl2 = ira_allocno_class_translate[cl];
+         if (ira_class_hard_regs_num[cl] == ira_class_hard_regs_num[cl2])
+           cl = cl2;
+         narrow.classes[narrow.num++] = cl;
        }
     }
-  return classes_ptr;
+  if (narrow.num == full->num)
+    return full;
+
+  cost_classes **slot = cost_classes_htab->find_slot (&narrow, INSERT);
+  if (*slot == NULL)
+    {
+      cost_classes_t classes = setup_cost_classes (&narrow);
+      /* Map equivalent classes to the representative that we chose above.  */
+      for (int i = 0; i < ira_important_classes_num; i++)
+       {
+         enum reg_class cl = ira_important_classes[i];
+         int index = full->index[cl];
+         if (index >= 0)
+           classes->index[cl] = map[index];
+       }
+      *slot = classes;
+    }
+  return *slot;
 }
 
 /* Setup cost classes for pseudo REGNO whose allocno class is ACLASS.
@@ -270,6 +386,19 @@ setup_regno_cost_classes_by_aclass (int regno, enum reg_class aclass)
        }
       classes_ptr = cost_classes_aclass_cache[aclass] = (cost_classes_t) *slot;
     }
+  if (regno_reg_rtx[regno] != NULL_RTX)
+    {
+      /* Restrict the classes to those that are valid for REGNO's mode
+        (which might for example exclude singleton classes if the mode
+        requires two registers).  Also restrict the classes to those that
+        are valid for subregs of REGNO.  */
+      const HARD_REG_SET *valid_regs = valid_mode_changes_for_regno (regno);
+      if (!valid_regs)
+       valid_regs = &reg_class_contents[ALL_REGS];
+      classes_ptr = restrict_cost_classes (classes_ptr,
+                                          PSEUDO_REGNO_MODE (regno),
+                                          *valid_regs);
+    }
   regno_cost_classes[regno] = classes_ptr;
 }
 
@@ -277,44 +406,25 @@ setup_regno_cost_classes_by_aclass (int regno, enum reg_class aclass)
    decrease number of cost classes for the pseudo, if hard registers
    of some important classes can not hold a value of MODE.  So the
    pseudo can not get hard register of some important classes and cost
-   calculation for such important classes is only waisting CPU
+   calculation for such important classes is only wasting CPU
    time.  */
 static void
-setup_regno_cost_classes_by_mode (int regno, enum machine_mode mode)
+setup_regno_cost_classes_by_mode (int regno, machine_mode mode)
 {
-  static struct cost_classes classes;
-  cost_classes_t classes_ptr;
-  enum reg_class cl;
-  int i;
-  cost_classes **slot;
-  HARD_REG_SET temp;
-
-  if ((classes_ptr = cost_classes_mode_cache[mode]) == NULL)
+  if (const HARD_REG_SET *valid_regs = valid_mode_changes_for_regno (regno))
+    regno_cost_classes[regno] = restrict_cost_classes (&all_cost_classes,
+                                                      mode, *valid_regs);
+  else
     {
-      classes.num = 0;
-      for (i = 0; i < ira_important_classes_num; i++)
-       {
-         cl = ira_important_classes[i];
-         COPY_HARD_REG_SET (temp, ira_prohibited_class_mode_regs[cl][mode]);
-         IOR_HARD_REG_SET (temp, ira_no_alloc_regs);
-         if (hard_reg_set_subset_p (reg_class_contents[cl], temp))
-           continue;
-         classes.classes[classes.num++] = cl;
-       }
-      slot = cost_classes_htab->find_slot (&classes, INSERT);
-      if (*slot == NULL)
-       {
-         classes_ptr = setup_cost_classes (&classes);
-         *slot = classes_ptr;
-       }
-      else
-       classes_ptr = (cost_classes_t) *slot;
-      cost_classes_mode_cache[mode] = (cost_classes_t) *slot;
+      if (cost_classes_mode_cache[mode] == NULL)
+       cost_classes_mode_cache[mode]
+         = restrict_cost_classes (&all_cost_classes, mode,
+                                  reg_class_contents[ALL_REGS]);
+      regno_cost_classes[regno] = cost_classes_mode_cache[mode];
     }
-  regno_cost_classes[regno] = classes_ptr;
 }
 
-/* Finilize info about the cost classes for each pseudo.  */
+/* Finalize info about the cost classes for each pseudo.  */
 static void
 finish_regno_cost_classes (void)
 {
@@ -329,7 +439,7 @@ finish_regno_cost_classes (void)
    TO_P is FALSE) a register of class RCLASS in mode MODE.  X must not
    be a pseudo register.  */
 static int
-copy_cost (rtx x, enum machine_mode mode, reg_class_t rclass, bool to_p,
+copy_cost (rtx x, machine_mode mode, reg_class_t rclass, bool to_p,
           secondary_reload_info *prev_sri)
 {
   secondary_reload_info sri;
@@ -402,7 +512,7 @@ copy_cost (rtx x, enum machine_mode mode, reg_class_t rclass, bool to_p,
    the alternatives.  */
 static void
 record_reg_classes (int n_alts, int n_ops, rtx *ops,
-                   enum machine_mode *modes, const char **constraints,
+                   machine_mode *modes, const char **constraints,
                    rtx_insn *insn, enum reg_class *pref)
 {
   int alt;
@@ -416,6 +526,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
 
   /* Process each alternative, each time minimizing an operand's cost
      with the cost for each operand in that alternative.  */
+  alternative_mask preferred = get_preferred_alternatives (insn);
   for (alt = 0; alt < n_alts; alt++)
     {
       enum reg_class classes[MAX_RECOG_OPERANDS];
@@ -424,7 +535,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
       int alt_fail = 0;
       int alt_cost = 0, op_cost_add;
 
-      if (!TEST_BIT (recog_data.enabled_alternatives, alt))
+      if (!TEST_BIT (preferred, alt))
        {
          for (i = 0; i < recog_data.n_operands; i++)
            constraints[i] = skip_alternative (constraints[i]);
@@ -437,7 +548,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
          unsigned char c;
          const char *p = constraints[i];
          rtx op = ops[i];
-         enum machine_mode mode = modes[i];
+         machine_mode mode = modes[i];
          int allows_addr = 0;
          int win = 0;
 
@@ -953,7 +1064,7 @@ ok_for_index_p_nonstrict (rtx reg)
    pseudo-registers should count as OK.  Arguments as for
    regno_ok_for_base_p.  */
 static inline bool
-ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as,
+ok_for_base_p_nonstrict (rtx reg, machine_mode mode, addr_space_t as,
                         enum rtx_code outer_code, enum rtx_code index_code)
 {
   unsigned regno = REGNO (reg);
@@ -976,7 +1087,7 @@ ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as,
    SCALE is twice the amount to multiply the cost by (it is twice so
    we can represent half-cost adjustments).  */
 static void
-record_address_regs (enum machine_mode mode, addr_space_t as, rtx x,
+record_address_regs (machine_mode mode, addr_space_t as, rtx x,
                     int context, enum rtx_code outer_code,
                     enum rtx_code index_code, int scale)
 {
@@ -1171,7 +1282,7 @@ static void
 record_operand_costs (rtx_insn *insn, enum reg_class *pref)
 {
   const char *constraints[MAX_RECOG_OPERANDS];
-  enum machine_mode modes[MAX_RECOG_OPERANDS];
+  machine_mode modes[MAX_RECOG_OPERANDS];
   rtx ops[MAX_RECOG_OPERANDS];
   rtx set;
   int i;
@@ -1238,7 +1349,7 @@ record_operand_costs (rtx_insn *insn, enum reg_class *pref)
      then we may want to adjust the cost of that register class to -1.
 
      Avoid the adjustment if the source does not die to avoid
-     stressing of register allocator by preferrencing two colliding
+     stressing of register allocator by preferencing two colliding
      registers into single class.
 
      Also avoid the adjustment if a copy between hard registers of the
@@ -1273,7 +1384,7 @@ record_operand_costs (rtx_insn *insn, enum reg_class *pref)
              || ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER
                  && (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER)))
        {
-         enum machine_mode mode = GET_MODE (src);
+         machine_mode mode = GET_MODE (src);
          cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
          enum reg_class *cost_classes = cost_classes_ptr->classes;
          reg_class_t rclass;
@@ -1437,15 +1548,11 @@ print_allocno_costs (FILE *f)
       for (k = 0; k < cost_classes_ptr->num; k++)
        {
          rclass = cost_classes[k];
-         if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)]
-             && ! invalid_mode_change_p (regno, (enum reg_class) rclass))
-           {
-             fprintf (f, " %s:%d", reg_class_names[rclass],
-                      COSTS (costs, i)->cost[k]);
-             if (flag_ira_region == IRA_REGION_ALL
-                 || flag_ira_region == IRA_REGION_MIXED)
-               fprintf (f, ",%d", COSTS (total_allocno_costs, i)->cost[k]);
-           }
+         fprintf (f, " %s:%d", reg_class_names[rclass],
+                  COSTS (costs, i)->cost[k]);
+         if (flag_ira_region == IRA_REGION_ALL
+             || flag_ira_region == IRA_REGION_MIXED)
+           fprintf (f, ",%d", COSTS (total_allocno_costs, i)->cost[k]);
        }
       fprintf (f, " MEM:%i", COSTS (costs, i)->mem_cost);
       if (flag_ira_region == IRA_REGION_ALL
@@ -1476,10 +1583,8 @@ print_pseudo_costs (FILE *f)
       for (k = 0; k < cost_classes_ptr->num; k++)
        {
          rclass = cost_classes[k];
-         if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)]
-             && ! invalid_mode_change_p (regno, (enum reg_class) rclass))
-           fprintf (f, " %s:%d", reg_class_names[rclass],
-                    COSTS (costs, regno)->cost[k]);
+         fprintf (f, " %s:%d", reg_class_names[rclass],
+                  COSTS (costs, regno)->cost[k]);
        }
       fprintf (f, " MEM:%i\n", COSTS (costs, regno)->mem_cost);
     }
@@ -1716,11 +1821,6 @@ find_costs_and_classes (FILE *dump_file)
          for (k = 0; k < cost_classes_ptr->num; k++)
            {
              rclass = cost_classes[k];
-             /* Ignore classes that are too small or invalid for this
-                operand.  */
-             if (! contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (i)]
-                 || invalid_mode_change_p (i, (enum reg_class) rclass))
-               continue;
              if (i_costs[k] < best_cost)
                {
                  best_cost = i_costs[k];
@@ -1810,12 +1910,7 @@ find_costs_and_classes (FILE *dump_file)
                      rclass = cost_classes[k];
                      if (! ira_class_subset_p[rclass][aclass])
                        continue;
-                     /* Ignore classes that are too small or invalid
-                        for this operand.  */
-                     if (! contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (i)]
-                         || invalid_mode_change_p (i, (enum reg_class) rclass))
-                       ;
-                     else if (total_a_costs[k] < best_cost)
+                     if (total_a_costs[k] < best_cost)
                        {
                          best_cost = total_a_costs[k];
                          allocno_cost = a_costs[k];
@@ -1944,7 +2039,7 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
       {
        int cost;
        enum reg_class hard_reg_class;
-       enum machine_mode mode;
+       machine_mode mode;
        
        mode = ALLOCNO_MODE (a);
        hard_reg_class = REGNO_REG_CLASS (hard_regno);
@@ -2154,7 +2249,7 @@ ira_tune_allocno_costs (void)
   int j, n, regno;
   int cost, min_cost, *reg_costs;
   enum reg_class aclass, rclass;
-  enum machine_mode mode;
+  machine_mode mode;
   ira_allocno_t a;
   ira_allocno_iterator ai;
   ira_allocno_object_iterator oi;