OSDN Git Service

* opts.c (decode_options): Disable whpr incompatible passes.
[pf3gnuchains/gcc-fork.git] / gcc / ira-costs.c
index 7749020..491b86b 100644 (file)
@@ -1,5 +1,5 @@
-/* IRA hard register and memory cost calculation for allocnos.
-   Copyright (C) 2006, 2007, 2008
+/* IRA hard register and memory cost calculation for allocnos or pseudos.
+   Copyright (C) 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
@@ -38,18 +38,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "ira-int.h"
 
-/* The file contains code is similar to one in regclass but the code
-   works on the allocno basis.  */
+/* The flags is set up every time when we calculate pseudo register
+   classes through function ira_set_pseudo_classes.  */
+static bool pseudo_classes_defined_p = false;
+
+/* TRUE if we work with allocnos.  Otherwise we work with pseudos.  */
+static bool allocno_p;
+
+/* Number of elements in arrays `in_inc_dec' and `costs'.  */
+static int cost_elements_num;
 
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-/* Indexed by n, is TRUE if allocno with number N is used in an
-   auto-inc or auto-dec context.  */
+/* Indexed by n, is TRUE if allocno or pseudo with number N is used in
+   an auto-inc or auto-dec context.  */
 static bool *in_inc_dec;
 #endif
 
 /* The `costs' struct records the cost of using hard registers of each
    class considered for the calculation and of using memory for each
-   allocno.  */
+   allocno or pseudo.  */
 struct costs
 {
   int mem_cost;
@@ -74,8 +81,11 @@ static struct costs *temp_costs;
 static struct costs *op_costs[MAX_RECOG_OPERANDS];
 static struct costs *this_op_costs[MAX_RECOG_OPERANDS];
 
-/* Original and accumulated costs of each class for each allocno.  */
-static struct costs *allocno_costs, *total_costs;
+/* Costs of each class for each allocno or pseudo.  */
+static struct costs *costs;
+
+/* Accumulated costs of each class for each allocno.  */
+static struct costs *total_allocno_costs;
 
 /* Classes used for cost calculation.  They may be different on
    different iterations of the cost calculations or in different
@@ -86,24 +96,32 @@ static enum reg_class *cost_classes;
 static int cost_classes_num;
 
 /* Map: cost class -> order number (they start with 0) of the cost
-   class.  */
+   class.  The order number is negative for non-cost classes.  */
 static int cost_class_nums[N_REG_CLASSES];
 
 /* It is the current size of struct costs.  */
 static int struct_costs_size;
 
-/* Return pointer to structure containing costs of allocno with given
-   NUM in array ARR.  */
-#define COSTS_OF_ALLOCNO(arr, num) \
+/* Return pointer to structure containing costs of allocno or pseudo
+   with given NUM in array ARR.  */
+#define COSTS(arr, num) \
   ((struct costs *) ((char *) (arr) + (num) * struct_costs_size))
 
-/* Record register class preferences of each allocno.  Null value
-   means no preferences.  It happens on the 1st iteration of the cost
-   calculation.  */
-static enum reg_class *allocno_pref;
+/* Return index in COSTS when processing reg with REGNO.  */
+#define COST_INDEX(regno) (allocno_p                                         \
+                           ? ALLOCNO_NUM (ira_curr_regno_allocno_map[regno])  \
+                          : (int) regno)
+
+/* Record register class preferences of each allocno or pseudo.  Null
+   value means no preferences.  It happens on the 1st iteration of the
+   cost calculation.  */
+static enum reg_class *pref;
 
-/* Allocated buffers for allocno_pref.  */
-static enum reg_class *allocno_pref_buffer;
+/* Allocated buffers for pref.  */
+static enum reg_class *pref_buffer;
+
+/* Record cover register class of each allocno with the same regno.  */
+static enum reg_class *regno_cover_class;
 
 /* Execution frequency of the current insn.  */
 static int frequency;
@@ -135,12 +153,13 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p,
   sri.extra_cost = 0;
   secondary_class = targetm.secondary_reload (to_p, x, rclass, mode, &sri);
 
-  if (ira_register_move_cost[mode] == NULL)
-    ira_init_register_move_cost (mode);
-
   if (secondary_class != NO_REGS)
-    return (move_cost[mode][secondary_class][rclass] + sri.extra_cost
-           + copy_cost (x, mode, secondary_class, to_p, &sri));
+    {
+      if (!move_cost[mode])
+        init_move_cost (mode);
+      return (move_cost[mode][secondary_class][rclass] + sri.extra_cost
+             + copy_cost (x, mode, secondary_class, to_p, &sri));
+    }
 
   /* For memory, use the memory move cost, for (hard) registers, use
      the cost to move between the register classes, and use 2 for
@@ -148,8 +167,11 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, bool to_p,
   if (MEM_P (x) || rclass == NO_REGS)
     return sri.extra_cost + ira_memory_move_cost[mode][rclass][to_p != 0];
   else if (REG_P (x))
-    return
-      (sri.extra_cost + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]);
+    {
+      if (!move_cost[mode])
+        init_move_cost (mode);
+      return (sri.extra_cost + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]);
+    }
   else
     /* If this is a constant, we may eventually want to call rtx_cost
        here.  */
@@ -182,11 +204,15 @@ static void
 record_reg_classes (int n_alts, int n_ops, rtx *ops,
                    enum machine_mode *modes, const char **constraints,
                    rtx insn, struct costs **op_costs,
-                   enum reg_class *allocno_pref)
+                   enum reg_class *pref)
 {
   int alt;
   int i, j, k;
   rtx set;
+  int insn_allows_mem[MAX_RECOG_OPERANDS];
+
+  for (i = 0; i < n_ops; i++)
+    insn_allows_mem[i] = 0;
 
   /* Process each alternative, each time minimizing an operand's cost
      with the cost for each operand in that alternative.  */
@@ -194,10 +220,18 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
     {
       enum reg_class classes[MAX_RECOG_OPERANDS];
       int allows_mem[MAX_RECOG_OPERANDS];
-      int rclass;
+      enum reg_class rclass;
       int alt_fail = 0;
       int alt_cost = 0, op_cost_add;
 
+      if (!recog_data.alternative_enabled_p[alt])
+       {
+         for (i = 0; i < recog_data.n_operands; i++)
+           constraints[i] = skip_alternative (constraints[i]);
+
+         continue;
+       }
+
       for (i = 0; i < n_ops; i++)
        {
          unsigned char c;
@@ -236,6 +270,8 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
              j = p[0] - '0';
              classes[i] = classes[j];
              allows_mem[i] = allows_mem[j];
+             if (allows_mem[i])
+               insn_allows_mem[i] = 1;
 
              if (! REG_P (op) || REGNO (op) < FIRST_PSEUDO_REGISTER)
                {
@@ -278,19 +314,17 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                     needs to do a copy, which is one insn.  */
                  struct costs *pp = this_op_costs[i];
 
-                 if (ira_register_move_cost[mode] == NULL)
-                   ira_init_register_move_cost (mode);
-
                  for (k = 0; k < cost_classes_num; k++)
                    {
                      rclass = cost_classes[k];
                      pp->cost[k]
-                       = ((recog_data.operand_type[i] != OP_OUT
-                           ? ira_may_move_in_cost[mode][rclass]
-                             [classes[i]] * frequency : 0)
-                          + (recog_data.operand_type[i] != OP_IN
-                             ? ira_may_move_out_cost[mode][classes[i]]
-                               [rclass] * frequency : 0));
+                       = (((recog_data.operand_type[i] != OP_OUT
+                            ? ira_get_may_move_cost (mode, rclass,
+                                                     classes[i], true) : 0)
+                           + (recog_data.operand_type[i] != OP_IN
+                              ? ira_get_may_move_cost (mode, classes[i],
+                                                       rclass, false) : 0))
+                          * frequency);
                    }
 
                  /* If the alternative actually allows memory, make
@@ -302,18 +336,16 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                       + (recog_data.operand_type[i] != OP_OUT
                          ? ira_memory_move_cost[mode][classes[i]][1] : 0)
                       - allows_mem[i]) * frequency;
+
                  /* If we have assigned a class to this allocno in our
                     first pass, add a cost to this alternative
                     corresponding to what we would add if this allocno
                     were not in the appropriate class.  We could use
                     cover class here but it is less accurate
                     approximation.  */
-                 if (allocno_pref)
+                 if (pref)
                    {
-                     enum reg_class pref_class
-                       = allocno_pref[ALLOCNO_NUM
-                                      (ira_curr_regno_allocno_map
-                                       [REGNO (op)])];
+                     enum reg_class pref_class = pref[COST_INDEX (REGNO (op))];
 
                      if (pref_class == NO_REGS)
                        alt_cost
@@ -325,8 +357,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                                 : 0));
                      else if (ira_reg_class_intersect
                               [pref_class][classes[i]] == NO_REGS)
-                       alt_cost += (ira_register_move_cost
-                                    [mode][pref_class][classes[i]]);
+                       alt_cost += ira_get_register_move_cost (mode,
+                                                               pref_class,
+                                                               classes[i]);
                    }
                  if (REGNO (ops[i]) != REGNO (ops[j])
                      && ! find_reg_note (insn, REG_DEAD, op))
@@ -342,7 +375,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  continue;
                }
            }
-         
+
          /* Scan all the constraint letters.  See if the operand
             matches any of the constraints.  Collect the valid
             register classes and see if this operand accepts
@@ -380,7 +413,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  /* It doesn't seem worth distinguishing between
                     offsettable and non-offsettable addresses
                     here.  */
-                 allows_mem[i] = 1;
+                 insn_allows_mem[i] = allows_mem[i] = 1;
                  if (MEM_P (op))
                    win = 1;
                  break;
@@ -416,7 +449,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  break;
 
                case 's':
-                 if (GET_CODE (op) == CONST_INT
+                 if (CONST_INT_P (op)
                      || (GET_CODE (op) == CONST_DOUBLE
                          && GET_MODE (op) == VOIDmode))
                    break;
@@ -428,7 +461,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  break;
 
                case 'n':
-                 if (GET_CODE (op) == CONST_INT
+                 if (CONST_INT_P (op)
                      || (GET_CODE (op) == CONST_DOUBLE
                          && GET_MODE (op) == VOIDmode))
                    win = 1;
@@ -442,7 +475,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                case 'N':
                case 'O':
                case 'P':
-                 if (GET_CODE (op) == CONST_INT
+                 if (CONST_INT_P (op)
                      && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
                    win = 1;
                  break;
@@ -456,7 +489,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                      || (CONSTANT_P (op)
                          && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))))
                    win = 1;
-                 allows_mem[i] = 1;
+                 insn_allows_mem[i] = allows_mem[i] = 1;
                case 'r':
                  classes[i] = ira_reg_class_union[classes[i]][GENERAL_REGS];
                  break;
@@ -472,7 +505,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  if (EXTRA_MEMORY_CONSTRAINT (c, p))
                    {
                      /* Every MEM can be reloaded to fit.  */
-                     allows_mem[i] = 1;
+                     insn_allows_mem[i] = allows_mem[i] = 1;
                      if (MEM_P (op))
                        win = 1;
                    }
@@ -523,19 +556,17 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                {
                  struct costs *pp = this_op_costs[i];
 
-                 if (ira_register_move_cost[mode] == NULL)
-                   ira_init_register_move_cost (mode);
-
                  for (k = 0; k < cost_classes_num; k++)
                    {
                      rclass = cost_classes[k];
                      pp->cost[k]
-                       = ((recog_data.operand_type[i] != OP_OUT
-                           ? ira_may_move_in_cost[mode][rclass]
-                             [classes[i]] * frequency : 0)
-                          + (recog_data.operand_type[i] != OP_IN
-                             ? ira_may_move_out_cost[mode][classes[i]]
-                               [rclass] * frequency : 0));
+                       = (((recog_data.operand_type[i] != OP_OUT
+                            ? ira_get_may_move_cost (mode, rclass,
+                                                     classes[i], true) : 0)
+                           + (recog_data.operand_type[i] != OP_IN
+                              ? ira_get_may_move_cost (mode, classes[i],
+                                                       rclass, false) : 0))
+                          * frequency);
                    }
 
                  /* If the alternative actually allows memory, make
@@ -553,12 +584,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                     were not in the appropriate class.  We could use
                     cover class here but it is less accurate
                     approximation.  */
-                 if (allocno_pref)
+                 if (pref)
                    {
-                     enum reg_class pref_class
-                       = allocno_pref[ALLOCNO_NUM
-                                      (ira_curr_regno_allocno_map
-                                       [REGNO (op)])];
+                     enum reg_class pref_class = pref[COST_INDEX (REGNO (op))];
 
                      if (pref_class == NO_REGS)
                        alt_cost
@@ -570,8 +598,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                                 : 0));
                      else if (ira_reg_class_intersect[pref_class][classes[i]]
                               == NO_REGS)
-                       alt_cost += (ira_register_move_cost
-                                    [mode][pref_class][classes[i]]);
+                       alt_cost += ira_get_register_move_cost (mode,
+                                                               pref_class,
+                                                               classes[i]);
                    }
                }
            }
@@ -625,6 +654,19 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
          }
     }
 
+  if (allocno_p)
+    for (i = 0; i < n_ops; i++)
+      {
+       ira_allocno_t a;
+       rtx op = ops[i];
+
+       if (! REG_P (op) || REGNO (op) < FIRST_PSEUDO_REGISTER)
+         continue;
+       a = ira_curr_regno_allocno_map [REGNO (op)];
+       if (! ALLOCNO_BAD_SPILL_P (a) && insn_allows_mem[i] == 0)
+         ALLOCNO_BAD_SPILL_P (a) = true;
+      }
+
   /* If this insn is a single set copying operand 1 to operand 0 and
      one operand is an allocno with the other a hard reg or an allocno
      that prefers a hard register that is in its own register class
@@ -648,7 +690,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
        {
          unsigned int regno = REGNO (ops[!i]);
          enum machine_mode mode = GET_MODE (ops[!i]);
-         int rclass;
+         enum reg_class rclass;
          unsigned int nr;
 
          if (regno < FIRST_PSEUDO_REGISTER)
@@ -669,7 +711,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                          if (! TEST_HARD_REG_BIT (reg_class_contents[rclass],
                                                   regno + nr))
                            break;
-                       
+
                        if (nr == (unsigned) hard_regno_nregs[regno][mode])
                          op_costs[i]->cost[k] = -frequency;
                      }
@@ -853,8 +895,7 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
 #ifdef FORBIDDEN_INC_DEC_CLASSES
       if (REG_P (XEXP (x, 0))
          && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
-       in_inc_dec[ALLOCNO_NUM (ira_curr_regno_allocno_map
-                               [REGNO (XEXP (x, 0))])] = true;
+       in_inc_dec[COST_INDEX (REGNO (XEXP (x, 0)))] = true;
 #endif
       record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
       break;
@@ -862,22 +903,21 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
     case REG:
       {
        struct costs *pp;
-       int i, k;
+       enum reg_class i;
+       int k;
 
        if (REGNO (x) < FIRST_PSEUDO_REGISTER)
          break;
 
-       pp = COSTS_OF_ALLOCNO (allocno_costs,
-                              ALLOCNO_NUM (ira_curr_regno_allocno_map
-                                           [REGNO (x)]));
+       if (allocno_p)
+         ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[REGNO (x)]) = true;
+       pp = COSTS (costs, COST_INDEX (REGNO (x)));
        pp->mem_cost += (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2;
-       if (ira_register_move_cost[Pmode] == NULL)
-         ira_init_register_move_cost (Pmode);
        for (k = 0; k < cost_classes_num; k++)
          {
            i = cost_classes[k];
            pp->cost[k]
-             += (ira_may_move_in_cost[Pmode][i][rclass] * scale) / 2;
+             += (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2;
          }
       }
       break;
@@ -898,8 +938,7 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
 
 /* Calculate the costs of insn operands.  */
 static void
-record_operand_costs (rtx insn, struct costs **op_costs,
-                     enum reg_class *allocno_pref)
+record_operand_costs (rtx insn, struct costs **op_costs, enum reg_class *pref)
 {
   const char *constraints[MAX_RECOG_OPERANDS];
   enum machine_mode modes[MAX_RECOG_OPERANDS];
@@ -952,11 +991,11 @@ record_operand_costs (rtx insn, struct costs **op_costs,
        xconstraints[i+1] = constraints[i];
        record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
                            recog_data.operand, modes,
-                           xconstraints, insn, op_costs, allocno_pref);
+                           xconstraints, insn, op_costs, pref);
       }
   record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
                      recog_data.operand, modes,
-                     constraints, insn, op_costs, allocno_pref);
+                     constraints, insn, op_costs, pref);
 }
 
 \f
@@ -971,7 +1010,7 @@ scan_one_insn (rtx insn)
   rtx set, note;
   int i, k;
 
-  if (!INSN_P (insn))
+  if (!NONDEBUG_INSN_P (insn))
     return insn;
 
   pat_code = GET_CODE (PATTERN (insn));
@@ -989,16 +1028,19 @@ scan_one_insn (rtx insn)
       && (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL_RTX
       && MEM_P (XEXP (note, 0)))
     {
-      COSTS_OF_ALLOCNO (allocno_costs,
-                       ALLOCNO_NUM (ira_curr_regno_allocno_map
-                                    [REGNO (SET_DEST (set))]))->mem_cost
-       -= (ira_memory_move_cost[GET_MODE (SET_DEST (set))][GENERAL_REGS][1]
-           * frequency);
+      enum reg_class cl = GENERAL_REGS;
+      rtx reg = SET_DEST (set);
+      int num = COST_INDEX (REGNO (reg));
+
+      if (pref)
+       cl = pref[num];
+      COSTS (costs, num)->mem_cost
+       -= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
       record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0),
                           0, MEM, SCRATCH, frequency * 2);
     }
 
-  record_operand_costs (insn, op_costs, allocno_pref);
+  record_operand_costs (insn, op_costs, pref);
 
   /* Now add the cost for each operand to the total costs for its
      allocno.  */
@@ -1007,9 +1049,7 @@ scan_one_insn (rtx insn)
        && REGNO (recog_data.operand[i]) >= FIRST_PSEUDO_REGISTER)
       {
        int regno = REGNO (recog_data.operand[i]);
-       struct costs *p
-         = COSTS_OF_ALLOCNO (allocno_costs,
-                             ALLOCNO_NUM (ira_curr_regno_allocno_map[regno]));
+       struct costs *p = COSTS (costs, COST_INDEX (regno));
        struct costs *q = op_costs[i];
 
        p->mem_cost += q->mem_cost;
@@ -1024,12 +1064,13 @@ scan_one_insn (rtx insn)
 
 /* Print allocnos costs to file F.  */
 static void
-print_costs (FILE *f)
+print_allocno_costs (FILE *f)
 {
   int k;
   ira_allocno_t a;
   ira_allocno_iterator ai;
 
+  ira_assert (allocno_p);
   fprintf (f, "\n");
   FOR_EACH_ALLOCNO (a, ai)
     {
@@ -1058,27 +1099,56 @@ print_costs (FILE *f)
              )
            {
              fprintf (f, " %s:%d", reg_class_names[rclass],
-                      COSTS_OF_ALLOCNO (allocno_costs, i)->cost[k]);
-             if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-                 || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
-               fprintf (f, ",%d", COSTS_OF_ALLOCNO (total_costs, i)->cost[k]);
+                      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\n", COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost);
+      fprintf (f, " MEM:%i\n", COSTS (costs, i)->mem_cost);
+    }
+}
+
+/* Print pseudo costs to file F.  */
+static void
+print_pseudo_costs (FILE *f)
+{
+  int regno, k;
+  int rclass;
+
+  ira_assert (! allocno_p);
+  fprintf (f, "\n");
+  for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--)
+    {
+      if (regno_reg_rtx[regno] == NULL_RTX)
+       continue;
+      fprintf (f, "  r%d costs:", regno);
+      for (k = 0; k < cost_classes_num; k++)
+       {
+         rclass = cost_classes[k];
+         if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)]
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+             && (! in_inc_dec[regno] || ! forbidden_inc_dec_class[rclass])
+#endif
+#ifdef CANNOT_CHANGE_MODE_CLASS
+             && ! invalid_mode_change_p (regno, (enum reg_class) rclass,
+                                         PSEUDO_REGNO_MODE (regno))
+#endif
+             )
+           fprintf (f, " %s:%d", reg_class_names[rclass],
+                    COSTS (costs, regno)->cost[k]);
+       }
+      fprintf (f, " MEM:%i\n", COSTS (costs, regno)->mem_cost);
     }
 }
 
 /* Traverse the BB represented by LOOP_TREE_NODE to update the allocno
    costs.  */
 static void
-process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node)
+process_bb_for_costs (basic_block bb)
 {
-  basic_block bb;
   rtx insn;
 
-  bb = loop_tree_node->bb;
-  if (bb == NULL)
-    return;
   frequency = REG_FREQ_FROM_BB (bb);
   if (frequency == 0)
     frequency = 1;
@@ -1086,32 +1156,62 @@ process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node)
     insn = scan_one_insn (insn);
 }
 
-/* Find costs of register classes and memory for allocnos and their
-   best costs. */
+/* Traverse the BB represented by LOOP_TREE_NODE to update the allocno
+   costs.  */
 static void
-find_allocno_class_costs (void)
+process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node)
 {
-  int i, k;
+  basic_block bb;
+
+  bb = loop_tree_node->bb;
+  if (bb != NULL)
+    process_bb_for_costs (bb);
+}
+
+/* Find costs of register classes and memory for allocnos or pseudos
+   and their best costs.  Set up preferred, alternative and cover
+   classes for pseudos.  */
+static void
+find_costs_and_classes (FILE *dump_file)
+{
+  int i, k, start;
   int pass;
   basic_block bb;
 
   init_recog ();
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-  in_inc_dec = ira_allocate (sizeof (bool) * ira_allocnos_num);
+  in_inc_dec = ira_allocate (sizeof (bool) * cost_elements_num);
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
-  allocno_pref = NULL;
+  pref = NULL;
+  start = 0;
+  if (!resize_reg_info () && allocno_p && pseudo_classes_defined_p)
+    {
+      ira_allocno_t a;
+      ira_allocno_iterator ai;
+
+      pref = pref_buffer;
+      FOR_EACH_ALLOCNO (a, ai)
+       pref[ALLOCNO_NUM (a)] = reg_preferred_class (ALLOCNO_REGNO (a));
+      if (flag_expensive_optimizations)
+       start = 1;
+    }
+  if (allocno_p)
+    /* Clear the flag for the next compiled function.  */
+    pseudo_classes_defined_p = false;
   /* Normally we scan the insns once and determine the best class to
      use for each allocno.  However, if -fexpensive-optimizations are
      on, we do so twice, the second time using the tentative best
      classes to guide the selection.  */
-  for (pass = 0; pass <= flag_expensive_optimizations; pass++)
+  for (pass = start; pass <= flag_expensive_optimizations; pass++)
     {
-      if (internal_flag_ira_verbose > 0 && ira_dump_file)
-       fprintf (ira_dump_file, "\nPass %i for finding allocno costs\n\n",
-                pass);
+      if ((!allocno_p || internal_flag_ira_verbose > 0) && dump_file)
+       fprintf (dump_file,
+                "\nPass %i for finding pseudo/allocno costs\n\n", pass);
       /* We could use only cover classes.  Unfortunately it does not
         work well for some targets where some subclass of cover class
         is costly and wrong cover class is chosen.  */
+      for (i = 0; i < N_REG_CLASSES; i++)
+       cost_class_nums[i] = -1;
       for (cost_classes_num = 0;
           cost_classes_num < ira_important_classes_num;
           cost_classes_num++)
@@ -1125,20 +1225,31 @@ find_allocno_class_costs (void)
        = sizeof (struct costs) + sizeof (int) * (cost_classes_num - 1);
       /* Zero out our accumulation of the cost of each class for each
         allocno.  */
-      memset (allocno_costs, 0, ira_allocnos_num * struct_costs_size);
+      memset (costs, 0, cost_elements_num * struct_costs_size);
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-      memset (in_inc_dec, 0, ira_allocnos_num * sizeof (bool));
+      memset (in_inc_dec, 0, cost_elements_num * sizeof (bool));
 #endif
 
-      /* Scan the instructions and record each time it would save code
-        to put a certain allocno in a certain class.  */
-      ira_traverse_loop_tree (true, ira_loop_tree_root,
-                             process_bb_node_for_costs, NULL);
+      if (allocno_p)
+       {
+         /* Scan the instructions and record each time it would save code
+            to put a certain allocno in a certain class.  */
+         ira_traverse_loop_tree (true, ira_loop_tree_root,
+                                 process_bb_node_for_costs, NULL);
+
+         memcpy (total_allocno_costs, costs,
+                 max_struct_costs_size * ira_allocnos_num);
+       }
+      else
+       {
+         basic_block bb;
+
+         FOR_EACH_BB (bb)
+           process_bb_for_costs (bb);
+       }
 
-      memcpy (total_costs, allocno_costs,
-             max_struct_costs_size * ira_allocnos_num);
       if (pass == 0)
-       allocno_pref = allocno_pref_buffer;
+       pref = pref_buffer;
 
       /* Now for each allocno look at how desirable each class is and
         find which class is preferred.  */
@@ -1147,47 +1258,58 @@ find_allocno_class_costs (void)
          ira_allocno_t a, parent_a;
          int rclass, a_num, parent_a_num;
          ira_loop_tree_node_t parent;
-         int best_cost;
-         enum reg_class best, alt_class, common_class;
+         int best_cost, allocno_cost;
+         enum reg_class best, alt_class;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
          int inc_dec_p = false;
 #endif
 
-         if (ira_regno_allocno_map[i] == NULL)
-           continue;
-         memset (temp_costs, 0, struct_costs_size);
-         /* Find cost of all allocnos with the same regno.  */
-         for (a = ira_regno_allocno_map[i];
-              a != NULL;
-              a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
+         if (! allocno_p)
            {
-             a_num = ALLOCNO_NUM (a);
-             if ((flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-                  || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
-                 && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL
-                 && (parent_a = parent->regno_allocno_map[i]) != NULL
-                 /* There are no caps yet.  */
-                 && bitmap_bit_p (ALLOCNO_LOOP_TREE_NODE (a)->border_allocnos,
-                                  ALLOCNO_NUM (a)))
+             if (regno_reg_rtx[i] == NULL_RTX)
+               continue;
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+             inc_dec_p = in_inc_dec[i];
+#endif
+             memcpy (temp_costs, COSTS (costs, i), struct_costs_size);
+           }
+         else
+           {
+             if (ira_regno_allocno_map[i] == NULL)
+               continue;
+             memset (temp_costs, 0, struct_costs_size);
+             /* Find cost of all allocnos with the same regno.  */
+             for (a = ira_regno_allocno_map[i];
+                  a != NULL;
+                  a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
                {
-                 /* Propagate costs to upper levels in the region
-                    tree.  */
-                 parent_a_num = ALLOCNO_NUM (parent_a);
+                 a_num = ALLOCNO_NUM (a);
+                 if ((flag_ira_region == IRA_REGION_ALL
+                      || flag_ira_region == IRA_REGION_MIXED)
+                     && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL
+                     && (parent_a = parent->regno_allocno_map[i]) != NULL
+                     /* There are no caps yet.  */
+                     && bitmap_bit_p (ALLOCNO_LOOP_TREE_NODE
+                                      (a)->border_allocnos,
+                                      ALLOCNO_NUM (a)))
+                   {
+                     /* Propagate costs to upper levels in the region
+                        tree.  */
+                     parent_a_num = ALLOCNO_NUM (parent_a);
+                     for (k = 0; k < cost_classes_num; k++)
+                       COSTS (total_allocno_costs, parent_a_num)->cost[k]
+                         += COSTS (total_allocno_costs, a_num)->cost[k];
+                     COSTS (total_allocno_costs, parent_a_num)->mem_cost
+                       += COSTS (total_allocno_costs, a_num)->mem_cost;
+                   }
                  for (k = 0; k < cost_classes_num; k++)
-                   COSTS_OF_ALLOCNO (total_costs, parent_a_num)->cost[k]
-                     += COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k];
-                 COSTS_OF_ALLOCNO (total_costs, parent_a_num)->mem_cost
-                   += COSTS_OF_ALLOCNO (total_costs, a_num)->mem_cost;
-               }
-             for (k = 0; k < cost_classes_num; k++)
-               temp_costs->cost[k]
-                 += COSTS_OF_ALLOCNO (allocno_costs, a_num)->cost[k];
-             temp_costs->mem_cost
-               += COSTS_OF_ALLOCNO (allocno_costs, a_num)->mem_cost;
+                   temp_costs->cost[k] += COSTS (costs, a_num)->cost[k];
+                 temp_costs->mem_cost += COSTS (costs, a_num)->mem_cost;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-             if (in_inc_dec[a_num])
-               inc_dec_p = true;
+                 if (in_inc_dec[a_num])
+                   inc_dec_p = true;
 #endif
+               }
            }
          best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
          best = ALL_REGS;
@@ -1222,42 +1344,55 @@ find_allocno_class_costs (void)
                      > reg_class_size[alt_class]))
                alt_class = reg_class_subunion[alt_class][rclass];
            }
+         alt_class = ira_class_translate[alt_class];
+         if (best_cost > temp_costs->mem_cost)
+           regno_cover_class[i] = NO_REGS;
+         else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+           /* Make the common class the biggest class of best and
+              alt_class.  */
+           regno_cover_class[i] = alt_class == NO_REGS ? best : alt_class;
+         else
+           /* Make the common class a cover class.  Remember all
+              allocnos with the same regno should have the same cover
+              class.  */
+           regno_cover_class[i] = ira_class_translate[best];
          if (pass == flag_expensive_optimizations)
            {
              if (best_cost > temp_costs->mem_cost)
                best = alt_class = NO_REGS;
              else if (best == alt_class)
                alt_class = NO_REGS;
-             setup_reg_classes (i, best, alt_class);
-             if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
-               fprintf (ira_dump_file,
-                        "    r%d: preferred %s, alternative %s\n",
-                        i, reg_class_names[best], reg_class_names[alt_class]);
+             setup_reg_classes (i, best, alt_class, regno_cover_class[i]);
+             if ((!allocno_p || internal_flag_ira_verbose > 2)
+                 && dump_file != NULL)
+               fprintf (dump_file,
+                        "    r%d: preferred %s, alternative %s, cover %s\n",
+                        i, reg_class_names[best], reg_class_names[alt_class],
+                        reg_class_names[regno_cover_class[i]]);
+           }
+         if (! allocno_p)
+           {
+             pref[i] = best_cost > temp_costs->mem_cost ? NO_REGS : best;
+             continue;
            }
-         if (best_cost > temp_costs->mem_cost)
-           common_class = NO_REGS;
-         else
-           /* Make the common class a cover class.  Remember all
-              allocnos with the same regno should have the same cover
-              class.  */
-           common_class = ira_class_translate[best];
          for (a = ira_regno_allocno_map[i];
               a != NULL;
               a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
            {
              a_num = ALLOCNO_NUM (a);
-             if (common_class == NO_REGS)
+             if (regno_cover_class[i] == NO_REGS)
                best = NO_REGS;
              else
-               {             
+               {
                  /* Finding best class which is subset of the common
                     class.  */
                  best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
+                 allocno_cost = best_cost;
                  best = ALL_REGS;
                  for (k = 0; k < cost_classes_num; k++)
                    {
                      rclass = cost_classes[k];
-                     if (! ira_class_subset_p[rclass][common_class])
+                     if (! ira_class_subset_p[rclass][regno_cover_class[i]])
                        continue;
                      /* Ignore classes that are too small for this
                         operand or invalid for an operand that was
@@ -1272,39 +1407,50 @@ find_allocno_class_costs (void)
 #endif
                          )
                        ;
-                     else if (COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k]
+                     else if (COSTS (total_allocno_costs, a_num)->cost[k]
                               < best_cost)
                        {
                          best_cost
-                           = COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k];
+                           = COSTS (total_allocno_costs, a_num)->cost[k];
+                         allocno_cost = COSTS (costs, a_num)->cost[k];
                          best = (enum reg_class) rclass;
                        }
-                     else if (COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k]
+                     else if (COSTS (total_allocno_costs, a_num)->cost[k]
                               == best_cost)
-                       best = ira_reg_class_union[best][rclass];
+                       {
+                         best = ira_reg_class_union[best][rclass];
+                         allocno_cost
+                           = MAX (allocno_cost, COSTS (costs, a_num)->cost[k]);
+                       }
                    }
+                 ALLOCNO_COVER_CLASS_COST (a) = allocno_cost;
                }
-             if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL
-                 && (pass == 0 || allocno_pref[a_num] != best))
+             ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY
+                         || ira_class_translate[best] == regno_cover_class[i]);
+             if (internal_flag_ira_verbose > 2 && dump_file != NULL
+                 && (pass == 0 || pref[a_num] != best))
                {
-                 fprintf (ira_dump_file, "    a%d (r%d,", a_num, i);
+                 fprintf (dump_file, "    a%d (r%d,", a_num, i);
                  if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL)
-                   fprintf (ira_dump_file, "b%d", bb->index);
+                   fprintf (dump_file, "b%d", bb->index);
                  else
-                   fprintf (ira_dump_file, "l%d",
+                   fprintf (dump_file, "l%d",
                             ALLOCNO_LOOP_TREE_NODE (a)->loop->num);
-                 fprintf (ira_dump_file, ") best %s, cover %s\n",
+                 fprintf (dump_file, ") best %s, cover %s\n",
                           reg_class_names[best],
-                          reg_class_names[ira_class_translate[best]]);
+                          reg_class_names[regno_cover_class[i]]);
                }
-             allocno_pref[a_num] = best;
+             pref[a_num] = best;
            }
        }
-      
-      if (internal_flag_ira_verbose > 4 && ira_dump_file)
+
+      if (internal_flag_ira_verbose > 4 && dump_file)
        {
-         print_costs (ira_dump_file);
-         fprintf (ira_dump_file,"\n");
+         if (allocno_p)
+           print_allocno_costs (dump_file);
+         else
+           print_pseudo_costs (dump_file);
+         fprintf (dump_file,"\n");
        }
     }
 #ifdef FORBIDDEN_INC_DEC_CLASSES
@@ -1338,7 +1484,7 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
     freq = 1;
   FOR_BB_INSNS (bb, insn)
     {
-      if (! INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
        continue;
       set = single_set (insn);
       if (set == NULL_RTX)
@@ -1373,8 +1519,9 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
        continue;
       mode = ALLOCNO_MODE (a);
       hard_reg_class = REGNO_REG_CLASS (hard_regno);
-      cost = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
-             : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
+      cost
+       = (to_p ? ira_get_register_move_cost (mode, hard_reg_class, rclass)
+          : ira_get_register_move_cost (mode, rclass, hard_reg_class)) * freq;
       ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
                                  ALLOCNO_COVER_CLASS_COST (a));
       ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
@@ -1392,29 +1539,24 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
 static void
 setup_allocno_cover_class_and_costs (void)
 {
-  int i, j, n, regno;
+  int i, j, n, regno, num;
   int *reg_costs;
   enum reg_class cover_class, rclass;
-  enum machine_mode mode;
   ira_allocno_t a;
   ira_allocno_iterator ai;
 
+  ira_assert (allocno_p);
   FOR_EACH_ALLOCNO (a, ai)
     {
       i = ALLOCNO_NUM (a);
-      mode = ALLOCNO_MODE (a);
-      cover_class = ira_class_translate[allocno_pref[i]];
-      ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS);
-      ALLOCNO_MEMORY_COST (a) = ALLOCNO_UPDATED_MEMORY_COST (a)
-       = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost;
+      cover_class = regno_cover_class[ALLOCNO_REGNO (a)];
+      ira_assert (pref[i] == NO_REGS || cover_class != NO_REGS);
+      ALLOCNO_MEMORY_COST (a) = COSTS (costs, i)->mem_cost;
       ira_set_allocno_cover_class (a, cover_class);
       if (cover_class == NO_REGS)
        continue;
       ALLOCNO_AVAILABLE_REGS_NUM (a) = ira_available_class_regs[cover_class];
-      ALLOCNO_COVER_CLASS_COST (a)
-       = (COSTS_OF_ALLOCNO (allocno_costs, i)
-          ->cost[cost_class_nums[allocno_pref[i]]]);
-      if (optimize && ALLOCNO_COVER_CLASS (a) != allocno_pref[i])
+      if (optimize && ALLOCNO_COVER_CLASS (a) != pref[i])
        {
          n = ira_class_hard_regs_num[cover_class];
          ALLOCNO_HARD_REG_COSTS (a)
@@ -1422,9 +1564,23 @@ setup_allocno_cover_class_and_costs (void)
          for (j = n - 1; j >= 0; j--)
            {
              regno = ira_class_hard_regs[cover_class][j];
-             rclass = REGNO_REG_CLASS (regno);
-             reg_costs[j] = (COSTS_OF_ALLOCNO (allocno_costs, i)
-                              ->cost[cost_class_nums[rclass]]);
+             if (TEST_HARD_REG_BIT (reg_class_contents[pref[i]], regno))
+               reg_costs[j] = ALLOCNO_COVER_CLASS_COST (a);
+             else
+               {
+                 rclass = REGNO_REG_CLASS (regno);
+                 num = cost_class_nums[rclass];
+                 if (num < 0)
+                   {
+                     /* The hard register class is not a cover class or a
+                        class not fully inside in a cover class -- use
+                        the allocno cover class.  */
+                     ira_assert (ira_hard_regno_cover_class[regno]
+                                 == cover_class);
+                     num = cost_class_nums[cover_class];
+                   }
+                 reg_costs[j] = COSTS (costs, i)->cost[num];
+               }
            }
        }
     }
@@ -1510,32 +1666,59 @@ ira_finish_costs_once (void)
 
 \f
 
+/* Common initialization function for ira_costs and
+   ira_set_pseudo_classes.  */
+static void
+init_costs (void)
+{
+  init_subregs_of_mode ();
+  costs = (struct costs *) ira_allocate (max_struct_costs_size
+                                        * cost_elements_num);
+  pref_buffer
+    = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
+                                      * cost_elements_num);
+  regno_cover_class
+    = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
+                                      * max_reg_num ());
+}
+
+/* Common finalization function for ira_costs and
+   ira_set_pseudo_classes.  */
+static void
+finish_costs (void)
+{
+  ira_free (regno_cover_class);
+  ira_free (pref_buffer);
+  ira_free (costs);
+}
+
 /* Entry function which defines cover class, memory and hard register
    costs for each allocno.  */
 void
 ira_costs (void)
 {
-  ira_allocno_t a;
-  ira_allocno_iterator ai;
-
-  allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size
-                                              * ira_allocnos_num);
-  total_costs = (struct costs *) ira_allocate (max_struct_costs_size
-                                              * ira_allocnos_num);
-  allocno_pref_buffer
-    = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
-                                      * ira_allocnos_num);
-  find_allocno_class_costs ();
+  allocno_p = true;
+  cost_elements_num = ira_allocnos_num;
+  init_costs ();
+  total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size
+                                                      * ira_allocnos_num);
+  find_costs_and_classes (ira_dump_file);
   setup_allocno_cover_class_and_costs ();
-  /* Because we could process operands only as subregs, check mode of
-     the registers themselves too.  */
-  FOR_EACH_ALLOCNO (a, ai)
-    if (ira_register_move_cost[ALLOCNO_MODE (a)] == NULL
-       && have_regs_of_mode[ALLOCNO_MODE (a)])
-      ira_init_register_move_cost (ALLOCNO_MODE (a));
-  ira_free (allocno_pref_buffer);
-  ira_free (total_costs);
-  ira_free (allocno_costs);
+  finish_costs ();
+  ira_free (total_allocno_costs);
+}
+
+/* Entry function which defines classes for pseudos.  */
+void
+ira_set_pseudo_classes (FILE *dump_file)
+{
+  allocno_p = false;
+  internal_flag_ira_verbose = flag_ira_verbose;
+  cost_elements_num = max_reg_num ();
+  init_costs ();
+  find_costs_and_classes (dump_file);
+  pseudo_classes_defined_p = true;
+  finish_costs ();
 }
 
 \f
@@ -1572,8 +1755,8 @@ ira_tune_allocno_costs_and_cover_classes (void)
              regno = ira_class_hard_regs[cover_class][j];
              rclass = REGNO_REG_CLASS (regno);
              cost = 0;
-             /* ??? If only part is call clobbered.  */
-             if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set))
+             if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set)
+                 || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
                cost += (ALLOCNO_CALL_FREQ (a)
                         * (ira_memory_move_cost[mode][rclass][0]
                            + ira_memory_move_cost[mode][rclass][1]));
@@ -1590,5 +1773,32 @@ ira_tune_allocno_costs_and_cover_classes (void)
        }
       if (min_cost != INT_MAX)
        ALLOCNO_COVER_CLASS_COST (a) = min_cost;
+
+      /* Some targets allow pseudos to be allocated to unaligned
+         sequences of hard registers.  However, selecting an unaligned
+         sequence can unnecessarily restrict later allocations.  So
+         increase the cost of unaligned hard regs to encourage the use
+         of aligned hard regs.  */
+      {
+       int nregs, index;
+
+       if ((nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]) > 1)
+         {
+           ira_allocate_and_set_costs
+             (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
+              ALLOCNO_COVER_CLASS_COST (a));
+           reg_costs = ALLOCNO_HARD_REG_COSTS (a);
+           for (j = n - 1; j >= 0; j--)
+             {
+               if (j % nregs != 0)
+                 {
+                   regno = ira_non_ordered_class_hard_regs[cover_class][j];
+                   index = ira_class_hard_reg_index[cover_class][regno];
+                   ira_assert (index != -1);
+                   reg_costs[index] += ALLOCNO_FREQ (a);
+                 }
+             }
+         }
+      }
     }
 }