Index: ira.c
===================================================================
--- ira.c	(revision 160634)
+++ ira.c	(working copy)
@@ -461,7 +461,7 @@ short ira_class_hard_regs[N_REG_CLASSES]
    the hard register numbers.  */
 short ira_non_ordered_class_hard_regs[N_REG_CLASSES][FIRST_PSEUDO_REGISTER];
 
-/* The number of elements of the above array for given register
+/* The number of elements of the two above arrays for given register
    class.  */
 int ira_class_hard_regs_num[N_REG_CLASSES];
 
Index: ira-costs.c
===================================================================
--- ira-costs.c	(revision 160634)
+++ ira-costs.c	(working copy)
@@ -125,6 +125,9 @@ struct cost_classes
   /* Map reg class -> index of the reg class in the previous array.
      -1 if it is not a cost classe.  */
   int index[N_REG_CLASSES];
+  /* Map hard regno index of first class in array CLASSES containing
+     the hard regno, -1 otherwise.  */
+  int hard_regno_index[FIRST_PSEUDO_REGISTER];
 };
 
 /* Types of pointers to the structure above.  */
@@ -187,6 +190,35 @@ initiate_regno_cost_classes (void)
     = htab_create (200, cost_classes_hash, cost_classes_eq, cost_classes_del);
 }
 
+/* Create new classes from FROM and set up memebrs index and
+   hard_regno_index.  Return the new classes.  */
+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++)
+    {
+      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--)
+	{
+	  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;
+	}
+    }
+  return classes_ptr;
+}
+
 /* Setup cost classes for REGNO whose allocno class ACLASS.  */
 static void
 setup_regno_cost_classes_by_aclass (int regno, enum reg_class aclass)
@@ -216,16 +248,7 @@ setup_regno_cost_classes_by_aclass (int 
       slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
       if (*slot == NULL)
 	{
-	  classes_ptr
-	    = (cost_classes_t) ira_allocate (sizeof (struct cost_classes));
-	  classes_ptr->num = classes.num;
-	  for (i = 0; i < N_REG_CLASSES; i++)
-	    classes_ptr->index[i] = -1;
-	  for (i = 0; i < classes.num; i++)
-	    {
-	      cl = classes_ptr->classes[i] = classes.classes[i];
-	      classes_ptr->index[cl] = i;
-	    }
+	  classes_ptr = setup_cost_classes (&classes);
 	  *slot = classes_ptr;
 	}
       cost_classes_aclass_cache[aclass] = (cost_classes_t) *slot;
@@ -259,16 +282,7 @@ setup_regno_cost_classes_by_mode (int re
       slot = htab_find_slot (cost_classes_htab, &classes, INSERT);
       if (*slot == NULL)
 	{
-	  classes_ptr
-	    = (cost_classes_t) ira_allocate (sizeof (struct cost_classes));
-	  classes_ptr->num = classes.num;
-	  for (i = 0; i < N_REG_CLASSES; i++)
-	    classes_ptr->index[i] = -1;
-	  for (i = 0; i < classes.num; i++)
-	    {
-	      cl = classes_ptr->classes[i] = classes.classes[i];
-	      classes_ptr->index[cl] = i;
-	    }
+	  classes_ptr = setup_cost_classes (&classes);
 	  *slot = classes_ptr;
 	}
       cost_classes_mode_cache[mode] = (cost_classes_t) *slot;
@@ -1114,8 +1128,7 @@ record_address_regs (enum machine_mode m
 	struct costs *pp;
 	int *pp_costs;
 	enum reg_class i;
-	int k, regno;
-	bool plus_p;
+	int k, regno, add_cost;
 	cost_classes_t cost_classes_ptr;
 	enum reg_class *cost_classes;
 	move_table *move_in_cost;
@@ -1126,10 +1139,11 @@ record_address_regs (enum machine_mode m
 	if (allocno_p)
 	  ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[regno]) = true;
 	pp = COSTS (costs, COST_INDEX (regno));
-	plus_p = pp->mem_cost > 0;
-	pp->mem_cost += (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2;
-	if (pp->mem_cost < 0 && plus_p)
+	add_cost = (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2;
+	if (INT_MAX - add_cost < pp->mem_cost)
 	  pp->mem_cost = INT_MAX;
+	else
+	  pp->mem_cost += add_cost;
 	cost_classes_ptr = regno_cost_classes[regno];
 	cost_classes = cost_classes_ptr->classes;
 	pp_costs = pp->cost;
@@ -1138,10 +1152,11 @@ record_address_regs (enum machine_mode m
 	for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 	  {
 	    i = cost_classes[k];
-	    plus_p = pp_costs[k] > 0;
-	    pp_costs[k] += (move_in_cost[i][rclass] * scale) / 2;
-	    if (pp_costs[k] < 0 && plus_p)
+	    add_cost = (move_in_cost[i][rclass] * scale) / 2;
+	    if (INT_MAX - add_cost < pp_costs[k])
 	      pp_costs[k] = INT_MAX;
+	    else 
+	      pp_costs[k] += add_cost;
 	  }
       }
       break;
@@ -1274,18 +1289,20 @@ scan_one_insn (rtx insn)
 	struct costs *q = op_costs[i];
 	int *p_costs = p->cost, *q_costs = q->cost;
 	cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
-	bool plus_p;
+	int add_cost;
 
-	plus_p = p->mem_cost > 0 && q->mem_cost > 0;
-	p->mem_cost += q->mem_cost;
-	if (p->mem_cost < 0 && plus_p)
+	add_cost = q->mem_cost;
+	if (add_cost > 0 && INT_MAX - add_cost < p->mem_cost)
 	  p->mem_cost = INT_MAX;
+	else
+	  p->mem_cost += add_cost;
 	for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 	  {
-	    plus_p = p_costs[k] > 0 && q_costs[k] > 0;
-	    p_costs[k] += q_costs[k];
-	    if (p_costs[k] < 0 && plus_p)
+	    add_cost = q_costs[k];
+	    if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
 	      p_costs[k] = INT_MAX;
+	    else
+	      p_costs[k] += add_cost;
 	  }
       }
 
@@ -1419,13 +1436,17 @@ find_costs_and_classes (FILE *dump_file)
   int i, k, start, max_cost_classes_num;
   int pass;
   basic_block bb;
-  enum reg_class pref_cl;
+  enum reg_class *regno_best_class;
 
   init_recog ();
 #ifdef FORBIDDEN_INC_DEC_CLASSES
   in_inc_dec = ira_allocate (sizeof (bool) * cost_elements_num);
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
-
+  regno_best_class
+    = (enum reg_class *) ira_allocate (max_reg_num ()
+				       * sizeof (enum reg_class));
+  for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
+    regno_best_class[i] = NO_REGS;
   if (!resize_reg_info () && allocno_p
       && pseudo_classes_defined_p && flag_expensive_optimizations)
     {
@@ -1468,6 +1489,18 @@ find_costs_and_classes (FILE *dump_file)
       if ((!allocno_p || internal_flag_ira_verbose > 0) && dump_file)
 	fprintf (dump_file,
 		 "\nPass %i for finding pseudo/allocno costs\n\n", pass);
+
+      if (pass != start)
+	{
+	  max_cost_classes_num = 1;
+	  for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
+	    {
+	      setup_regno_cost_classes_by_aclass (i, regno_best_class[i]);
+	      max_cost_classes_num
+		= MAX (max_cost_classes_num, regno_cost_classes[i]->num);
+	    }
+	}
+
       struct_costs_size
 	= sizeof (struct costs) + sizeof (int) * (max_cost_classes_num - 1);
       /* Zero out our accumulation of the cost of each class for each
@@ -1477,7 +1510,6 @@ find_costs_and_classes (FILE *dump_file)
       memset (in_inc_dec, 0, cost_elements_num * sizeof (bool));
 #endif
 
-      max_cost_classes_num = 1;
       if (allocno_p)
 	{
 	  /* Scan the instructions and record each time it would save code
@@ -1504,14 +1536,13 @@ find_costs_and_classes (FILE *dump_file)
       for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
 	{
 	  ira_allocno_t a, parent_a;
-	  int rclass, a_num, parent_a_num;
+	  int rclass, a_num, parent_a_num, add_cost;
 	  ira_loop_tree_node_t parent;
 	  int best_cost, allocno_cost;
 	  enum reg_class best, alt_class;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 	  int inc_dec_p = false;
 #endif
-	  bool plus_p;
 	  cost_classes_t cost_classes_ptr = regno_cost_classes[i];
 	  enum reg_class *cost_classes = cost_classes_ptr->classes;
 	  int *i_costs = temp_costs->cost;
@@ -1557,34 +1588,38 @@ find_costs_and_classes (FILE *dump_file)
 		      p_costs = COSTS (total_allocno_costs, parent_a_num)->cost;
 		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 			{
-			  plus_p = p_costs[k] > 0 && a_costs[k] > 0;
-			  p_costs[k] += a_costs[k];
-			  if (p_costs[k] < 0 && plus_p)
+			  add_cost = a_costs[k];
+			  if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
 			    p_costs[k] = INT_MAX;
+			  else
+			    p_costs[k] += add_cost;
 			}
-		      plus_p = (COSTS (total_allocno_costs,
-				       parent_a_num)->mem_cost > 0
-				&& COSTS (total_allocno_costs,
-					  a_num)->mem_cost > 0);
-		      COSTS (total_allocno_costs, parent_a_num)->mem_cost
-			+= COSTS (total_allocno_costs, a_num)->mem_cost;
-		      if (COSTS (total_allocno_costs, parent_a_num)->mem_cost < 0
-			  && plus_p)
+		      add_cost = COSTS (total_allocno_costs, a_num)->mem_cost;
+		      if (add_cost > 0
+			  && (INT_MAX - add_cost
+			      < COSTS (total_allocno_costs,
+				       parent_a_num)->mem_cost))
 			COSTS (total_allocno_costs, parent_a_num)->mem_cost
 			  = INT_MAX;
+		      else
+			COSTS (total_allocno_costs, parent_a_num)->mem_cost
+			  += add_cost;
+
 		    }
 		  a_costs = COSTS (costs, a_num)->cost;
 		  for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 		    {
-		      plus_p = i_costs[k] > 0 && a_costs[k] > 0;
-		      i_costs[k] += a_costs[k];
-		      if (i_costs[k] < 0 && plus_p)
+		      add_cost = a_costs[k];
+		      if (add_cost > 0 && INT_MAX - add_cost < i_costs[k])
 			i_costs[k] = INT_MAX;
+		      else
+			i_costs[k] += add_cost;
 		    }
-		  plus_p = i_mem_cost > 0 && COSTS (costs, a_num)->mem_cost > 0;
-		  i_mem_cost += COSTS (costs, a_num)->mem_cost;
-		  if (i_mem_cost < 0 && plus_p)
+		  add_cost = COSTS (costs, a_num)->mem_cost;
+		  if (add_cost && INT_MAX - add_cost < i_mem_cost)
 		    i_mem_cost = INT_MAX;
+		  else
+		    i_mem_cost += add_cost;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 		  if (in_inc_dec[a_num])
 		    inc_dec_p = true;
@@ -1650,16 +1685,10 @@ find_costs_and_classes (FILE *dump_file)
 			 i, reg_class_names[best], reg_class_names[alt_class],
 			 reg_class_names[regno_aclass[i]]);
 	    }
-	  pref_cl = best;
+	  regno_best_class[i] = best;
 	  if (! allocno_p)
 	    {
 	      pref[i] = best_cost > i_mem_cost ? NO_REGS : best;
-	      if (pass < flag_expensive_optimizations)
-		{
-		  setup_regno_cost_classes_by_aclass (i, pref_cl);
-		  max_cost_classes_num
-		    = MAX (max_cost_classes_num, regno_cost_classes[i]->num);
-		}
 	      continue;
 	    }
 	  for (a = ira_regno_allocno_map[i];
@@ -1673,7 +1702,7 @@ find_costs_and_classes (FILE *dump_file)
 		{
 		  int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
 		  int *a_costs = COSTS (costs, a_num)->cost;
-
+		  
 		  /* Finding best class which is subset of the common
 		     class.  */
 		  best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
@@ -1726,11 +1755,8 @@ find_costs_and_classes (FILE *dump_file)
 		}
 	      pref[a_num] = best;
 	    }
-	  setup_regno_cost_classes_by_aclass (i, pref_cl);
-	  max_cost_classes_num
-	    = MAX (max_cost_classes_num, regno_cost_classes[i]->num);
 	}
-
+      
       if (internal_flag_ira_verbose > 4 && dump_file)
 	{
 	  if (allocno_p)
@@ -1740,6 +1766,7 @@ find_costs_and_classes (FILE *dump_file)
 	  fprintf (dump_file,"\n");
 	}
     }
+  ira_free (regno_best_class);
 #ifdef FORBIDDEN_INC_DEC_CLASSES
   ira_free (in_inc_dec);
 #endif
@@ -1862,12 +1889,8 @@ setup_allocno_class_and_costs (void)
 		  num = cost_classes_ptr->index[rclass];
 		  if (num < 0)
 		    {
-		      /* The hard register class is not an allocno
-			 class or a class not fully inside in an
-			 allocno class -- use the allocno class.  */
-		      ira_assert (ira_hard_regno_allocno_class[hard_regno]
-				  == aclass);
-		      num = cost_classes_ptr->index[aclass];
+		      num = cost_classes_ptr->hard_regno_index[hard_regno];
+		      ira_assert (num >= 0);
 		    }
 		  reg_costs[j] = COSTS (costs, i)->cost[num];
 		}
@@ -2022,7 +2045,6 @@ ira_tune_allocno_costs (void)
   enum machine_mode mode;
   ira_allocno_t a;
   ira_allocno_iterator ai;
-  bool plus_p;
 
   FOR_EACH_ALLOCNO (a, ai)
     {
@@ -2057,10 +2079,10 @@ ira_tune_allocno_costs (void)
 		       * ALLOCNO_FREQ (a)
 		       * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
 #endif
-	      plus_p = reg_costs[j] > 0 && cost > 0;
-	      reg_costs[j] += cost;
-	      if (reg_costs[j] < 0 && plus_p)
+	      if (INT_MAX - cost < reg_costs[j])
 		reg_costs[j] = INT_MAX;
+	      else
+		reg_costs[j] += cost;
 	      if (min_cost > reg_costs[j])
 		min_cost = reg_costs[j];
 	    }
