This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

IRA improvements 4/4


  This is the last patch to speed up IRA.  The big part of the patch
decreases allocno structure footprint (more than 2 times) improving
data locality.  The patch also contains manual optimizations of some
critical loops.

Is the patch ok to commit the patch to the trunk?

2010-07-07 Vladimir Makarov <vmakarov@redhat.com>

* ira-build.c: (ira_create_allocno): Remove initialization of
ALLOCNO_MEM_OPTIMIZED_DEST, ALLOCNO_MEM_OPTIMIZED_DEST_P,
ALLOCNO_SOMEWHERE_RENAMED_P, ALLOCNO_CHILD_RENAMED_P,
ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P, ALLOCNO_COLORABLE_P,
ALLOCNO_NEXT_BUCKET_ALLOCNO, ALLOCNO_PREV_BUCKET_ALLOCNO,
ALLOCNO_FIRST_COALESCED_ALLOCNO, ALLOCNO_NEXT_COALESCED_ALLOCNO,
ALLOCNO_PROFITABLE_HARD_REGS, ALLOCNO_HARD_REGS_NODE,
ALLOCNO_HARD_REGS_SUBNODES_START, ALLOCNO_HARD_REGS_SUBNODES_NUM.
Initialize ALLOCNO_ADD_DATA.
(copy_info_to_removed_store_destinations): Use ALLOCNO_EMIT_DATA
instead of ALLOCNO_MEM_OPTIMIZED_DEST_P and ALLOCNO_REG.
(ira_flattening): Ditto. Use ALLOCNO_EMIT_DATA instead of
ALLOCNO_MEM_OPTIMIZED_DEST and ALLOCNO_SOMEWHERE_RENAMED_P.
* ira.c (ira_reallocate): Remove.
(setup_pressure_classes): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(setup_allocno_assignment_flags): Use ALLOCNO_EMIT_DATA.
(ira): Call ira_initiate_emit_data and ira_finish_emit_data.
* ira-color.c: Use ALLOCNO_COLOR_DATA instead of
ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P, ALLOCNO_COLORABLE_P,
ALLOCNO_AVAILABLE_REGS_NUM, ALLOCNO_NEXT_BUCKET_ALLOCNO,
ALLOCNO_PREV_BUCKET_ALLOCNO. ALLOCNO_TEMP,
ALLOCNO_PROFITABLE_HARD_REGS, ALLOCNO_HARD_REGS_NODE,
ALLOCNO_HARD_REGS_SUBNODES_START, ALLOCNO_HARD_REGS_SUBNODES_NUM.
(allocno_hard_regs_t, allocno_hard_regs_node_t): Move from
ira-int.h.
(struct allocno_hard_regs, struct allocno_hard_regs_node): Ditto.
(struct color_data): New.
(color_data_t): New typedef.
(allocno_color_data): New definition.
(ALLOCNO_COLOR_DATA): New macro.
(update_copy_costs, calculate_allocno_spill_cost,
move_spill_restore, update_curr_costs): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(allocno_spill_priority): Make it inline.
(color_pass): Allocate and free allocno_color_data.
(struct coalesce_data): New.
(allocno_coalesce_data): New definition.
(ALLOCNO_COALESCE_DATA): New macro.
(merge_allocnos, coalesced_allocno_conflict_p, coalesce_allocnos,
setup_coalesced_allocno_costs_and_nums,
collect_spilled_coalesced_allocnos,
slot_coalesced_allocno_live_ranges_intersect_p,
setup_slot_coalesced_allocno_live_ranges, coalesce_spill_slots):
Use ALLOCNO_COALESCED_DATA instead of
ALLOCNO_FIRST_COALESCED_ALLOCNO, ALLOCNO_NEXT_COALESCED_ALLOCNO,
ALLOCNO_TEMP.
(ira_sort_regnos_for_alter_reg): Ditto. Allocate and free
allocno_coalesce_data.


   * ira-conflicts.c (build_conflict_bit_table): Optimize.
   (process_regs_for_copy): Call
   ira_init_register_move_cost_if_necessary.  Use
   ira_register_move_cost instead of ira_get_register_move_cost.
   (build_allocno_conflicts): Optimize.

* ira-costs.c (struct cost_classes): New member hard_regno_index.
(setup_cost_classes): New.
(setup_regno_cost_classes_by_aclass): Call setup_cost_classes.
(setup_regno_cost_classes_by_mode): Ditto.
(record_address_regs): Fix overflow code.
(scan_one_insn): Ditto.
(find_costs_and_classes): Ditto. Move setting cost classes to the
loop start.
(setup_allocno_class_and_costs): Use member hard_regno_index.
(ira_tune_allocno_costs): Fix overflow code.
* ira-costs.c (cost_classes, cost_classes_num): Remove.
(struct cost_classes, cost_classes_t, const_cost_classes_t,
regno_cost_classes, cost_classes_hash, cost_classes_eq,
cost_classes_del, cost_classes_htab, cost_classes_mode_cache,
initiate_regno_cost_classes, setup_regno_cost_classes_by_aclass,
setup_regno_cost_classes_by_mode, finish_regno_cost_classes): New.
(record_reg_classes): Optimize. Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost, ira_may_move_in_cost, and
ira_may_move_out_cost instead of ira_get_register_move_cost and
ira_get_may_move_cost.
(record_address_regs): Ditto.
(scan_one_insn): Optimize.
(find_costs_and_classes): Optimize. Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(process_bb_node_for_hard_reg_moves): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.


   * ira-emit.c: Use ALLOCNO_EMIT_DATA instead of ALLOCNO_REG,
   ALLOCNO_CHILD_RENAMED_P, ALLOCNO_MEM_OPTIMIZED_DEST,
   ALLOCNO_MEM_OPTIMIZED_DEST_P, and ALLOCNO_SOMEWHERE_RENAMED_P.
   (ira_allocno_emit_data, void_p, new_allocno_emit_data_vec): New
   definitions.
   (ira_initiate_emit_data, ira_finish_emit_data,
   create_new_allocno): New functions.
   (modify_move_list): Call create_new_alloc instead of
   ira_create_allocno.  Call ira_set_allocno_class instead of
   ira_set_allocno_cover_class.
   (emit_move_list): Call ira_init_register_move_cost_if_necessary.
   Use ira_register_move_cost instead of ira_get_register_move_cost.

   * ira-int.h (allocno_hard_regs_t, allocno_hard_regs_node_t): Move
   to ira-color.c.
   (struct allocno_hard_regs, struct allocno_hard_regs_node): Ditto.
   (struct ira_allocno): Make mode and aclass a bitfield.  Move other
   bitfield after mode.  Make hard_regno a short int.  Remove reg.
   Remove first_coalesced_allocno and next_coalesced_allocno.  Move
   mem_optimized_dest_p, somewhere_renamed_p, child_renamed_p, reg,
   and mem_optimized_dest into struct ira_emit_data.  Remove
   in_graph_p, may_be_spilled_p, splay_removed_p,
   left_conflicts_size, available_regs_num, next_bucket_allocno,
   prev_bucket_allocno, temp, colorable_p, profitable_hard_regs,
   hard_regs_node, hard_regs_subnodes_start, hard_regs_subnodes_num.
   Add new member add_data.
   (ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P,
   ALLOCNO_COLORABLE_P, ALLOCNO_AVAILABLE_REGS_NUM,
   ALLOCNO_NEXT_BUCKET_ALLOCNO, ALLOCNO_PREV_BUCKET_ALLOCNO,
   ALLOCNO_TEMP, ALLOCNO_FIRST_COALESCED_ALLOCNO,
   ALLOCNO_NEXT_COALESCED_ALLOCNO, ALLOCNO_PROFITABLE_HARD_REGS,
   ALLOCNO_HARD_REGS_SUBNODES_START, ALLOCNO_HARD_REGS_SUBNODES_NUM):
   Remove.
   (ALLOCNO_ADD_DATA): New macro.
   (ira_emit_data_t): New typedef.
   (struct ira_emit_data): New.  Move mem_optimized_dest_p,
   somewhere_renamed_p, child_renamed_p, reg, mem_optimized_dest from
   struct ira_allocno.
   (ALLOCNO_EMIT_DATA): New macro.
   (ira_allocno_emit_data): New.
   (ira_remove_allocno_copy_from_list, ira_reallocate): Remove.
   (ira_initiate_emit_data, ira_finish_emit_data): New.
   (ira_get_register_move_cost, ira_get_may_move_cost): Remove.
   (ira_init_register_move_cost_if_necessary): New.
   (ira_allocno_conflict_iter_next): Merge into
   ira_allocno_conflict_iter_cond.
   (FOR_EACH_ALLOCNO_CONFLICT): Don't use
   ira_allocno_conflict_iter_next.

   * ira-live.c: (process_single_reg_class_operands): Call
   ira_init_register_move_cost_if_necessary.  Use
   ira_register_move_cost instead of ira_get_register_move_cost.


--- ./ira-build.c	2010-07-06 11:37:23.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-build.c	2010-06-30 15:15:21.000000000 -0400
@@ -454,17 +454,10 @@ ira_create_allocno (int regno, bool cap_
   ALLOCNO_NO_STACK_REG_P (a) = false;
   ALLOCNO_TOTAL_NO_STACK_REG_P (a) = false;
 #endif
-  ALLOCNO_MEM_OPTIMIZED_DEST (a) = NULL;
-  ALLOCNO_MEM_OPTIMIZED_DEST_P (a) = false;
-  ALLOCNO_SOMEWHERE_RENAMED_P (a) = false;
-  ALLOCNO_CHILD_RENAMED_P (a) = false;
   ALLOCNO_DONT_REASSIGN_P (a) = false;
   ALLOCNO_BAD_SPILL_P (a) = false;
-  ALLOCNO_IN_GRAPH_P (a) = false;
   ALLOCNO_ASSIGNED_P (a) = false;
-  ALLOCNO_MAY_BE_SPILLED_P (a) = false;
   ALLOCNO_CONFLICT_VEC_P (a) = false;
-  ALLOCNO_COLORABLE_P (a) = false;
   ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
   ALLOCNO_COPIES (a) = NULL;
   ALLOCNO_HARD_REG_COSTS (a) = NULL;
@@ -477,18 +470,11 @@ ira_create_allocno (int regno, bool cap_
   ALLOCNO_MEMORY_COST (a) = 0;
   ALLOCNO_UPDATED_MEMORY_COST (a) = 0;
   ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) = 0;
-  ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = NULL;
-  ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
-  ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
-  ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
   ALLOCNO_LIVE_RANGES (a) = NULL;
   ALLOCNO_MIN (a) = INT_MAX;
   ALLOCNO_MAX (a) = -1;
   ALLOCNO_CONFLICT_ID (a) = ira_allocnos_num;
-  CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
-  ALLOCNO_HARD_REGS_NODE (a) = NULL;
-  ALLOCNO_HARD_REGS_SUBNODES_START (a) = 0;
-  ALLOCNO_HARD_REGS_SUBNODES_NUM (a) = 0;
+  ALLOCNO_ADD_DATA (a) = NULL;
   VEC_safe_push (ira_allocno_t, heap, allocno_vec, a);
   ira_allocnos = VEC_address (ira_allocno_t, allocno_vec);
   ira_allocnos_num = VEC_length (ira_allocno_t, allocno_vec);
@@ -2425,7 +2411,7 @@ copy_info_to_removed_store_destinations 
        a != NULL;
        a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
     {
-      if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))])
+      if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_EMIT_DATA (a)->reg)])
 	/* This allocno will be removed.  */
 	continue;
       /* Caps will be removed.  */
@@ -2434,9 +2420,10 @@ copy_info_to_removed_store_destinations 
 	   parent != NULL;
 	   parent = parent->parent)
 	if ((parent_a = parent->regno_allocno_map[regno]) == NULL
-	    || (parent_a == regno_top_level_allocno_map[REGNO (ALLOCNO_REG
-							       (parent_a))]
-		&& ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)))
+	    || (parent_a == regno_top_level_allocno_map[REGNO
+							(ALLOCNO_EMIT_DATA
+							 (parent_a)->reg)]
+		&& ALLOCNO_EMIT_DATA (parent_a)->mem_optimized_dest_p))
 	  break;
       if (parent == NULL || parent_a == NULL)
 	continue;
@@ -2502,28 +2489,31 @@ ira_flattening (int max_regno_before_emi
 	   a != NULL;
 	   a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
 	{
+	  ira_emit_data_t parent_data, data = ALLOCNO_EMIT_DATA (a);
+
 	  ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
-	  if (ALLOCNO_SOMEWHERE_RENAMED_P (a))
+	  if (data->somewhere_renamed_p)
 	    new_pseudos_p = true;
 	  parent_a = ira_parent_allocno (a);
 	  if (parent_a == NULL)
 	    {
 	      ALLOCNO_COPIES (a) = NULL;
-	      regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a;
+	      regno_top_level_allocno_map[REGNO (data->reg)] = a;
 	      continue;
 	    }
 	  ira_assert (ALLOCNO_CAP_MEMBER (parent_a) == NULL);
 
-	  if (ALLOCNO_MEM_OPTIMIZED_DEST (a) != NULL)
+	  if (data->mem_optimized_dest != NULL)
 	    mem_dest_p = true;
-	  if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a)))
+	  parent_data = ALLOCNO_EMIT_DATA (parent_a);
+	  if (REGNO (data->reg) == REGNO (parent_data->reg))
 	    {
 	      merge_hard_reg_conflicts (a, parent_a, true);
 	      move_allocno_live_ranges (a, parent_a);
 	      merged_p = true;
-	      ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
-		= (ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
-		   || ALLOCNO_MEM_OPTIMIZED_DEST_P (a));
+	      parent_data->mem_optimized_dest_p
+		= (parent_data->mem_optimized_dest_p
+		   || data->mem_optimized_dest_p);
 	      continue;
 	    }
 	  new_pseudos_p = true;
@@ -2559,7 +2549,7 @@ ira_flattening (int max_regno_before_emi
 		break;
 	    }
 	  ALLOCNO_COPIES (a) = NULL;
-	  regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a;
+	  regno_top_level_allocno_map[REGNO (data->reg)] = a;
 	}
       if (mem_dest_p && copy_info_to_removed_store_destinations (i))
 	merged_p = true;
@@ -2572,7 +2562,8 @@ ira_flattening (int max_regno_before_emi
       /* Rebuild conflicts.  */
       FOR_EACH_ALLOCNO (a, ai)
 	{
-	  if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+	  if (a != regno_top_level_allocno_map[REGNO
+					       (ALLOCNO_EMIT_DATA (a)->reg)]
 	      || ALLOCNO_CAP_MEMBER (a) != NULL)
 	    continue;
 	  for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
@@ -2585,7 +2576,8 @@ ira_flattening (int max_regno_before_emi
 	  for (r = ira_start_point_ranges[i]; r != NULL; r = r->start_next)
 	    {
 	      a = r->allocno;
-	      if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+	      if (a != regno_top_level_allocno_map[REGNO
+						   (ALLOCNO_EMIT_DATA (a)->reg)]
 		  || ALLOCNO_CAP_MEMBER (a) != NULL)
 		continue;
 	      num = ALLOCNO_NUM (a);
@@ -2620,14 +2612,18 @@ ira_flattening (int max_regno_before_emi
 	    fprintf
 	      (ira_dump_file, "      Remove cp%d:%c%dr%d-%c%dr%d\n",
 	       cp->num, ALLOCNO_CAP_MEMBER (cp->first) != NULL ? 'c' : 'a',
-	       ALLOCNO_NUM (cp->first), REGNO (ALLOCNO_REG (cp->first)),
+	       ALLOCNO_NUM (cp->first),
+	       REGNO (ALLOCNO_EMIT_DATA (cp->first)->reg),
 	       ALLOCNO_CAP_MEMBER (cp->second) != NULL ? 'c' : 'a',
-	       ALLOCNO_NUM (cp->second), REGNO (ALLOCNO_REG (cp->second)));
+	       ALLOCNO_NUM (cp->second),
+	       REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
 	  cp->loop_tree_node = NULL;
 	  continue;
 	}
-      first = regno_top_level_allocno_map[REGNO (ALLOCNO_REG (cp->first))];
-      second = regno_top_level_allocno_map[REGNO (ALLOCNO_REG (cp->second))];
+      first = regno_top_level_allocno_map[REGNO (ALLOCNO_EMIT_DATA
+						 (cp->first)->reg)];
+      second = regno_top_level_allocno_map[REGNO (ALLOCNO_EMIT_DATA
+						  (cp->second)->reg)];
       node = cp->loop_tree_node;
       if (node == NULL)
 	keep_p = true; /* It copy generated in ira-emit.c.  */
@@ -2637,10 +2633,10 @@ ira_flattening (int max_regno_before_emi
 	     which we will have different pseudos.  */
 	  node_first = node->regno_allocno_map[ALLOCNO_REGNO (cp->first)];
 	  node_second = node->regno_allocno_map[ALLOCNO_REGNO (cp->second)];
-	  keep_p = ((REGNO (ALLOCNO_REG (first))
-		     == REGNO (ALLOCNO_REG (node_first)))
-		     && (REGNO (ALLOCNO_REG (second))
-			 == REGNO (ALLOCNO_REG (node_second))));
+	  keep_p = ((REGNO (ALLOCNO_EMIT_DATA (first)->reg)
+		     == REGNO (ALLOCNO_EMIT_DATA (node_first)->reg))
+		     && (REGNO (ALLOCNO_EMIT_DATA (second)->reg)
+			 == REGNO (ALLOCNO_EMIT_DATA (node_second)->reg)));
 	}
       if (keep_p)
 	{
@@ -2654,24 +2650,25 @@ ira_flattening (int max_regno_before_emi
 	  if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
 	    fprintf (ira_dump_file, "      Remove cp%d:a%dr%d-a%dr%d\n",
 		     cp->num, ALLOCNO_NUM (cp->first),
-		     REGNO (ALLOCNO_REG (cp->first)), ALLOCNO_NUM (cp->second),
-		     REGNO (ALLOCNO_REG (cp->second)));
+		     REGNO (ALLOCNO_EMIT_DATA (cp->first)->reg),
+		     ALLOCNO_NUM (cp->second),
+		     REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
 	}
     }
   /* Remove unnecessary allocnos on lower levels of the loop tree.  */
   FOR_EACH_ALLOCNO (a, ai)
     {
-      if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+      if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_EMIT_DATA (a)->reg)]
 	  || ALLOCNO_CAP_MEMBER (a) != NULL)
 	{
 	  if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
 	    fprintf (ira_dump_file, "      Remove a%dr%d\n",
-		     ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)));
+		     ALLOCNO_NUM (a), REGNO (ALLOCNO_EMIT_DATA (a)->reg));
 	  finish_allocno (a);
 	  continue;
 	}
       ALLOCNO_LOOP_TREE_NODE (a) = ira_loop_tree_root;
-      ALLOCNO_REGNO (a) = REGNO (ALLOCNO_REG (a));
+      ALLOCNO_REGNO (a) = REGNO (ALLOCNO_EMIT_DATA (a)->reg);
       ALLOCNO_CAP (a) = NULL;
       /* Restore updated costs for assignments from reload.  */
       ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
--- ./ira.c	2010-07-06 11:37:23.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira.c	2010-07-01 14:43:11.000000000 -0400
@@ -697,20 +697,6 @@ ira_allocate (size_t len)
   return res;
 }
 
-/* Reallocate memory PTR of size LEN for IRA data.  */
-void *
-ira_reallocate (void *ptr, size_t len)
-{
-  void *res;
-
-#ifndef IRA_NO_OBSTACK
-  res = obstack_alloc (&ira_obstack, len);
-#else
-  res = xrealloc (ptr, len);
-#endif
-  return res;
-}
-
 /* Free memory ADDR allocated for IRA data.  */
 void
 ira_free (void *addr ATTRIBUTE_UNUSED)
@@ -880,9 +866,8 @@ setup_pressure_classes (void)
 				  ira_prohibited_class_mode_regs[cl][m]);
 	  if (hard_reg_set_empty_p (temp_hard_regset))
 	    continue;
-	  cost = ira_get_register_move_cost ((enum machine_mode) m,
-					     (enum reg_class) cl,
-					     (enum reg_class) cl);
+	  ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
+	  cost = ira_register_move_cost[m][cl][cl];
 	  if (cost <= ira_max_memory_move_cost[m][cl][1]
 	      || cost <= ira_max_memory_move_cost[m][cl][0])
 	    break;
@@ -1984,7 +1969,7 @@ setup_allocno_assignment_flags (void)
 	 allocnos because the cost info and info about intersected
 	 calls are incorrect for them.  */
       ALLOCNO_ASSIGNED_P (a) = (hard_regno >= 0
-				|| ALLOCNO_MEM_OPTIMIZED_DEST_P (a)
+				|| ALLOCNO_EMIT_DATA (a)->mem_optimized_dest_p
 				|| (ALLOCNO_MEMORY_COST (a)
 				    - ALLOCNO_CLASS_COST (a)) < 0);
       ira_assert (hard_regno < 0
@@ -3519,7 +3504,7 @@ ira (FILE *f)
   df_clear_flags (DF_NO_INSN_RESCAN);
   regstat_init_n_sets_and_refs ();
   regstat_compute_ri ();
-
+    
   /* If we are not optimizing, then this is the only place before
      register allocation where dataflow is done.  And that is needed
      to generate these warnings.  */
@@ -3591,6 +3576,8 @@ ira (FILE *f)
 
   ira_max_point_before_emit = ira_max_point;
 
+  ira_initiate_emit_data ();
+
   ira_emit (loops_p);
 
   if (ira_conflicts_p)
@@ -3623,6 +3610,8 @@ ira (FILE *f)
 	}
     }
 
+  ira_finish_emit_data ();
+
   setup_reg_renumber ();
 
   calculate_allocation_cost ();
--- ./ira-color.c	2010-07-06 11:37:23.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-color.c	2010-06-30 17:56:36.000000000 -0400
@@ -39,6 +39,104 @@ along with GCC; see the file COPYING3.  
 #include "df.h"
 #include "ira-int.h"
 
+/* See below.  */
+typedef struct allocno_hard_regs *allocno_hard_regs_t;
+
+/* The structure contains information about hard registers can be
+   assigned to allocnos.  Usually it is allocno profitable hard
+   registers but in some cases this set can be a bit different.  Major
+   reason of the difference is a requirement to use hard register sets
+   that form a tree or a forest (set of trees), i.e. hard register set
+   of a node should contain hard register sets of its subnodes.  */
+struct allocno_hard_regs
+{
+  /* Hard registers can be assigned to an allocno.  */
+  HARD_REG_SET set;
+  /* Overall (spilling) cost of all allocnos with given register
+     set.  */
+  long long int cost;
+};
+
+/* See below.  */
+typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
+
+/* A node representing allocno hard registers.  Such nodes form a
+   forest (set of trees).  Each subnode of given node in the forest
+   refers for hard register set (usually allocno profitable hard
+   register set) which is a subset of one referred from given
+   node.  */
+struct allocno_hard_regs_node
+{
+  /* Set up number of the node in preorder traversing of the forest.  */
+  int preorder_num;
+  /* Used for different calculation like finding conflict size of an
+     allocno.  */
+  int check;
+  /* Used for calculation of conflict size of an allocno.  The
+     conflict size of the allocno is maximal number of given allocno
+     hard registers needed for allocation of the conflicting allocnos.
+     Given allocno is trivially colored if this number plus the number
+     of hard registers needed for given allocno is not greater than
+     the number of given allocno hard register set.  */
+  int conflict_size;
+  /* The number of hard registers given by member hard_regs.  */
+  int hard_regs_num;
+  /* The following member is used to form the final forest.  */
+  bool used_p;
+  /* Pointer to the corresponding profitable hard registers.  */
+  allocno_hard_regs_t hard_regs;
+  /* Parent, first subnode, previous and next node with the same
+     parent in the forest.  */
+  allocno_hard_regs_node_t parent, first, prev, next;
+};
+
+/* To decrease footprint of ira_allocno structure we store all data
+   needed only for coloring in the following structure.  */
+struct color_data
+{
+  /* TRUE value means that the allocno was not removed yet from the
+     conflicting graph during colouring.  */
+  unsigned int in_graph_p : 1;
+  /* TRUE if it is put on the stack to make other allocnos
+     colorable.  */
+  unsigned int may_be_spilled_p : 1;
+  /* TRUE if the allocno is trivially colorable.  */
+  unsigned int colorable_p : 1;
+  /* Number of hard registers of the allocno class really
+     available for the allocno allocation.  It is number of the
+     profitable hard regs.  */
+  int available_regs_num;
+  /* Allocnos in a bucket (used in coloring) chained by the following
+     two members.  */
+  ira_allocno_t next_bucket_allocno;
+  ira_allocno_t prev_bucket_allocno;
+  /* Used for temporary purposes.  */
+  int temp;
+  /* Profitable hard regs available for this pseudo allocation.  It
+     means that the set excludes unavailable hard regs and hard regs
+     conflicting with given pseudo.  They should be of the allocno
+     class.  */
+  HARD_REG_SET profitable_hard_regs;
+  /* The allocno hard registers node.  */
+  allocno_hard_regs_node_t hard_regs_node;
+  /* Array of structures allocno_hard_regs_subnode representing
+     given allocno hard registers node (the 1st element in the array)
+     and all its subnodes in the tree (forest) of allocno hard
+     register nodes (see comments above).  */
+  int hard_regs_subnodes_start;
+  /* The length of the previous array. */
+  int hard_regs_subnodes_num;
+};
+
+/* See above.  */
+typedef struct color_data *color_data_t;
+
+/* Container for storing allocno data concerning coloring.  */
+static color_data_t allocno_color_data;
+
+/* Macro to access the data concerning coloring.  */
+#define ALLOCNO_COLOR_DATA(a) ((color_data_t) ALLOCNO_ADD_DATA (a))
+
 /* This file contains code for regional graph coloring, spill/restore
    code placement optimization, and code helping the reload pass to do
    a better job.  */
@@ -554,6 +652,7 @@ form_allocno_hard_regs_nodes_forest (voi
   bitmap_iterator bi;
   HARD_REG_SET temp;
   allocno_hard_regs_node_t node, allocno_hard_regs_node;
+  color_data_t data;
 
   node_check_tick = 0;
   init_allocno_hard_regs ();
@@ -572,10 +671,10 @@ form_allocno_hard_regs_nodes_forest (voi
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
-      if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+      if (hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs))
 	continue;
       hv = (add_allocno_hard_regs
-	    (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	    (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
 	     ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
     }
   SET_HARD_REG_SET (temp);
@@ -598,11 +697,12 @@ form_allocno_hard_regs_nodes_forest (voi
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
-      if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+      data = ALLOCNO_COLOR_DATA (a);
+      if (hard_reg_set_empty_p (data->profitable_hard_regs))
 	continue;
       VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, 0);
       collect_allocno_hard_regs_cover (hard_regs_roots,
-				       ALLOCNO_PROFITABLE_HARD_REGS (a));
+				       data->profitable_hard_regs);
       allocno_hard_regs_node = NULL;
       for (j = 0;
 	   VEC_iterate (allocno_hard_regs_node_t, hard_regs_node_vec,
@@ -614,7 +714,7 @@ form_allocno_hard_regs_nodes_forest (voi
 	     : first_common_ancestor_node (node, allocno_hard_regs_node));
       /* That is a temporary storage.  */
       allocno_hard_regs_node->used_p = true;
-      ALLOCNO_HARD_REGS_NODE (a) = allocno_hard_regs_node;
+      data->hard_regs_node = allocno_hard_regs_node;
     }
   ira_assert (hard_regs_roots->next == NULL);
   hard_regs_roots->used_p = true;
@@ -635,11 +735,12 @@ form_allocno_hard_regs_nodes_forest (voi
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
-      if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+      data = ALLOCNO_COLOR_DATA (a);
+      if (hard_reg_set_empty_p (data->profitable_hard_regs))
 	continue;
-      len = get_allocno_hard_regs_subnodes_num (ALLOCNO_HARD_REGS_NODE (a));
-      ALLOCNO_HARD_REGS_SUBNODES_START (a) = start;
-      ALLOCNO_HARD_REGS_SUBNODES_NUM (a) = len;
+      len = get_allocno_hard_regs_subnodes_num (data->hard_regs_node);
+      data->hard_regs_subnodes_start = start;
+      data->hard_regs_subnodes_num = len;
       start += len;
     }
   allocno_hard_regs_subnodes
@@ -693,20 +794,23 @@ setup_left_conflict_sizes_p (ira_allocno
   allocno_hard_regs_subnode_t subnodes;
   allocno_hard_regs_node_t node, conflict_node, temp_node, parent;
   HARD_REG_SET node_set, conflict_node_set;
+  color_data_t data, conflict_data;
 
   node_check_tick++;
-  subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
-  COPY_HARD_REG_SET (profitable_hard_regs, ALLOCNO_PROFITABLE_HARD_REGS (a));
-  node = ALLOCNO_HARD_REGS_NODE (a);
+  data = ALLOCNO_COLOR_DATA (a);
+  subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
+  COPY_HARD_REG_SET (profitable_hard_regs, data->profitable_hard_regs);
+  node = data->hard_regs_node;
   node_preorder_num = node->preorder_num;
   COPY_HARD_REG_SET (node_set, node->hard_regs->set);
   FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
     {
-      if (! ALLOCNO_IN_GRAPH_P (conflict_a)
+      conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
+      if (! conflict_data->in_graph_p
 	  || ! hard_reg_set_intersect_p (profitable_hard_regs,
-					 ALLOCNO_PROFITABLE_HARD_REGS (conflict_a)))
+					 conflict_data->profitable_hard_regs))
 	continue;
-      conflict_node = ALLOCNO_HARD_REGS_NODE (conflict_a);
+      conflict_node = conflict_data->hard_regs_node;
       COPY_HARD_REG_SET (conflict_node_set, conflict_node->hard_regs->set);
       if (hard_reg_set_subset_p (node_set, conflict_node_set))
 	temp_node = node;
@@ -724,7 +828,7 @@ setup_left_conflict_sizes_p (ira_allocno
 	+= (ira_reg_class_max_nregs
 	    [ALLOCNO_CLASS (conflict_a)][ALLOCNO_MODE (conflict_a)]);
     }
-  for (i = 0; i < ALLOCNO_HARD_REGS_SUBNODES_NUM (a); i++)
+  for (i = 0; i < data->hard_regs_subnodes_num; i++)
     {
       temp_node = allocno_hard_regs_nodes[i + node_preorder_num];
       ira_assert (temp_node->preorder_num == i + node_preorder_num);
@@ -750,7 +854,7 @@ setup_left_conflict_sizes_p (ira_allocno
       subnodes[i].left_conflict_subnodes_size = 0;
     }
   start = node_preorder_num * allocno_hard_regs_nodes_num;
-  for (i = ALLOCNO_HARD_REGS_SUBNODES_NUM (a) - 1; i >= 0; i--)
+  for (i = data->hard_regs_subnodes_num - 1; i >= 0; i--)
     {
       size = (subnodes[i].left_conflict_subnodes_size
 	      + MIN (subnodes[i].max_node_impact
@@ -772,8 +876,8 @@ setup_left_conflict_sizes_p (ira_allocno
 	      subnodes[0].left_conflict_size));
   conflict_size
     += ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
-  ALLOCNO_COLORABLE_P (a) = conflict_size <= ALLOCNO_AVAILABLE_REGS_NUM (a);
-  return ALLOCNO_COLORABLE_P (a);
+  data->colorable_p = conflict_size <= data->available_regs_num;
+  return data->colorable_p;
 }
 
 /* Update left conflict sizes of hard registers subnodes of allocno A
@@ -786,10 +890,12 @@ update_left_conflict_sizes_p (ira_allocn
   int node_preorder_num, parent_i;
   allocno_hard_regs_node_t node, removed_node, parent;
   allocno_hard_regs_subnode_t subnodes;
+  color_data_t data;
 
-  node = ALLOCNO_HARD_REGS_NODE (a);
+  data = ALLOCNO_COLOR_DATA (a);
+  node = data->hard_regs_node;
   node_preorder_num = node->preorder_num;
-  removed_node = ALLOCNO_HARD_REGS_NODE (removed_a);
+  removed_node = ALLOCNO_COLOR_DATA (removed_a)->hard_regs_node;
   ira_assert (hard_reg_set_subset_p (removed_node->hard_regs->set,
 				     node->hard_regs->set)
 	      || hard_reg_set_subset_p (node->hard_regs->set,
@@ -798,7 +904,7 @@ update_left_conflict_sizes_p (ira_allocn
   i = allocno_hard_regs_subnode_index[start + removed_node->preorder_num];
   if (i < 0)
     i = 0;
-  subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
+  subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
   before_conflict_size
     = (subnodes[i].left_conflict_subnodes_size
        + MIN (subnodes[i].max_node_impact
@@ -835,12 +941,12 @@ update_left_conflict_sizes_p (ira_allocn
   if (i == 0
       && (conflict_size
 	  + ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
-	  <= ALLOCNO_AVAILABLE_REGS_NUM (a)))
+	  <= data->available_regs_num))
     {
-      ALLOCNO_COLORABLE_P (a) = true;
+      data->colorable_p = true;
       return true;
     }
-  ira_assert (! ALLOCNO_COLORABLE_P (a));
+  ira_assert (! data->colorable_p);
   return false;
 }
 
@@ -856,26 +962,28 @@ setup_profitable_hard_regs (void)
   bitmap_iterator bi;
   enum reg_class aclass;
   enum machine_mode mode;
+  color_data_t data;
 
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
       if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS)
 	continue;
+      data = ALLOCNO_COLOR_DATA (a);
       if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
 	  && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
-	CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
       else
 	{
 	  mode = ALLOCNO_MODE (a);
-	  COPY_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	  COPY_HARD_REG_SET (data->profitable_hard_regs,
 			     reg_class_contents[aclass]);
 	  AND_COMPL_HARD_REG_SET
-	    (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	    (data->profitable_hard_regs,
 	     ira_prohibited_class_mode_regs[aclass][mode]);
-	  AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	  AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
 				  ira_no_alloc_regs);
-	  AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	  AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
 				  ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
 	}
     }
@@ -888,7 +996,7 @@ setup_profitable_hard_regs (void)
 	continue;
       FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
 	AND_COMPL_HARD_REG_SET
-	  (ALLOCNO_PROFITABLE_HARD_REGS (conflict_a),
+	  (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
 	   ira_reg_mode_hard_regset[hard_regno][ALLOCNO_MODE (a)]);
     }
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
@@ -897,8 +1005,9 @@ setup_profitable_hard_regs (void)
       int *costs;
 
       a = ira_allocnos[i];
+      data = ALLOCNO_COLOR_DATA (a);
       if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
-	  || hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+	  || hard_reg_set_empty_p (data->profitable_hard_regs))
 	continue;
       if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
 	  || (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
@@ -908,11 +1017,11 @@ setup_profitable_hard_regs (void)
 	  for (j = 0; j < class_size; j++)
 	    {
 	      hard_regno = ira_class_hard_regs[aclass][j];
-	      if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	      if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
 				       hard_regno))
 		continue;
 	      if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
-		CLEAR_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+		CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
 				    hard_regno);
 	      else if (min_cost > costs[j])
 		min_cost = costs[j];
@@ -920,7 +1029,7 @@ setup_profitable_hard_regs (void)
 	}
       else if (ALLOCNO_UPDATED_MEMORY_COST (a)
 	       < ALLOCNO_UPDATED_CLASS_COST (a))
-	CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+	CLEAR_HARD_REG_SET (data->profitable_hard_regs);
       if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
 	ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
     }
@@ -1000,8 +1109,8 @@ start_update_cost (void)
   update_cost_queue = NULL;
 }
 
-/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue,
-   unless ALLOCNO is already in the queue, or has NO_REGS class.  */
+/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless
+   ALLOCNO is already in the queue, or has NO_REGS class.  */
 static inline void
 queue_update_cost (ira_allocno_t allocno, int divisor)
 {
@@ -1066,6 +1175,7 @@ update_copy_costs (ira_allocno_t allocno
   do
     {
       mode = ALLOCNO_MODE (allocno);
+      ira_init_register_move_cost_if_necessary (mode);
       for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
 	{
 	  if (cp->first == allocno)
@@ -1087,8 +1197,8 @@ update_copy_costs (ira_allocno_t allocno
 	    continue;
 
 	  cost = (cp->second == allocno
-		  ? ira_get_register_move_cost (mode, rclass, aclass)
-		  : ira_get_register_move_cost (mode, aclass, rclass));
+		  ? ira_register_move_cost[mode][rclass][aclass]
+		  : ira_register_move_cost[mode][aclass][rclass]);
 	  if (decr_p)
 	    cost = -cost;
 
@@ -1150,8 +1260,7 @@ update_conflict_hard_regno_costs (int *c
  	another_aclass = ALLOCNO_CLASS (another_allocno);
  	if (! ira_reg_classes_intersect_p[aclass][another_aclass]
 	    || ALLOCNO_ASSIGNED_P (another_allocno)
-	    || ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
-					 (another_allocno)))
+	    || ALLOCNO_COLOR_DATA (another_allocno)->may_be_spilled_p)
 	  continue;
 	class_size = ira_class_hard_regs_num[another_aclass];
 	ira_allocate_and_copy_costs
@@ -1245,7 +1354,7 @@ assign_hard_reg (ira_allocno_t a, bool r
 		       reg_class_contents[aclass]);
   else
     COPY_HARD_REG_SET (profitable_hard_regs,
-		       ALLOCNO_PROFITABLE_HARD_REGS (a));
+		       ALLOCNO_COLOR_DATA (a)->profitable_hard_regs);
   class_size = ira_class_hard_regs_num[aclass];
   mode = ALLOCNO_MODE (a);
   CLEAR_HARD_REG_SET (conflicting_regs);
@@ -1291,7 +1400,7 @@ assign_hard_reg (ira_allocno_t a, bool r
 		 && ALLOCNO_HARD_REGNO (conflict_a) >= 0)
 		|| (hard_reg_set_intersect_p
 		    (profitable_hard_regs,
-		     ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))))
+		     ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs)))))
       {
 	conflict_aclass = ALLOCNO_CLASS (conflict_a);
 	ira_assert (ira_reg_classes_intersect_p[aclass][conflict_aclass]);
@@ -1310,7 +1419,7 @@ assign_hard_reg (ira_allocno_t a, bool r
 	      }
 	  }
 	else if (! retry_p
-		 && ! ALLOCNO_MAY_BE_SPILLED_P (conflict_a))
+		 && ! ALLOCNO_COLOR_DATA (conflict_a)->may_be_spilled_p)
 	  {
 	    ira_allocate_and_copy_costs
 	      (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a),
@@ -1331,13 +1440,14 @@ assign_hard_reg (ira_allocno_t a, bool r
 	  }
       }
   if (! retry_p)
+    /* Take into account preferences of allocnos connected by copies to
+       the conflict allocnos.  */
+    update_conflict_hard_regno_costs (full_costs, aclass, true);
+
+  /* Take preferences of allocnos connected by copies into
+     account.  */
+  if (! retry_p)
     {
-      /* Take into account preferences of allocnos connected by copies
-	 to the conflict allocnos.  */
-      update_conflict_hard_regno_costs (full_costs, aclass, true);
-      
-      /* Take preferences of allocnos connected by copies into
-	 account.  */
       start_update_cost ();
       queue_update_cost (a, COST_HOP_DIVISOR);
       update_conflict_hard_regno_costs (full_costs, aclass, false);
@@ -1420,21 +1530,24 @@ static int uncolorable_allocnos_num;
 
 /* Return the current spill priority of allocno A.  The less the
    number, the more preferable the allocno for spilling.  */
-static int
+static inline int
 allocno_spill_priority (ira_allocno_t a)
 {
-  return (ALLOCNO_TEMP (a)
+  color_data_t data = ALLOCNO_COLOR_DATA (a);
+
+  return (data->temp
 	  / (ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
 	     * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
 	     + 1));
 }
 
-/* Add A to bucket *BUCKET_PTR.  A should be not in a bucket
+/* Add allocno A to bucket *BUCKET_PTR.  A should be not in a bucket
    before the call.  */
 static void
 add_allocno_to_bucket (ira_allocno_t a, ira_allocno_t *bucket_ptr)
 {
   ira_allocno_t first_a;
+  color_data_t data;
 
   if (bucket_ptr == &uncolorable_allocno_bucket
       && ALLOCNO_CLASS (a) != NO_REGS)
@@ -1443,10 +1556,11 @@ add_allocno_to_bucket (ira_allocno_t a, 
       ira_assert (uncolorable_allocnos_num > 0);
     }
   first_a = *bucket_ptr;
-  ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = first_a;
-  ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
+  data = ALLOCNO_COLOR_DATA (a);
+  data->next_bucket_allocno = first_a;
+  data->prev_bucket_allocno = NULL;
   if (first_a != NULL)
-    ALLOCNO_PREV_BUCKET_ALLOCNO (first_a) = a;
+    ALLOCNO_COLOR_DATA (first_a)->prev_bucket_allocno = a;
   *bucket_ptr = a;
 }
 
@@ -1467,9 +1581,9 @@ bucket_allocno_compare_func (const void 
   if ((diff = (int) ALLOCNO_CLASS (a2) - ALLOCNO_CLASS (a1)) != 0)
     return diff;
   a1_freq = ALLOCNO_FREQ (a1);
-  a1_num = ALLOCNO_AVAILABLE_REGS_NUM (a1);
+  a1_num = ALLOCNO_COLOR_DATA (a1)->available_regs_num;
   a2_freq = ALLOCNO_FREQ (a2);
-  a2_num = ALLOCNO_AVAILABLE_REGS_NUM (a2);
+  a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
   if ((diff = a2_num - a1_num) != 0)
     return diff;
   else if ((diff = a1_freq - a2_freq) != 0)
@@ -1486,7 +1600,9 @@ sort_bucket (ira_allocno_t *bucket_ptr,
   ira_allocno_t a, head;
   int n;
 
-  for (n = 0, a = *bucket_ptr; a != NULL; a = ALLOCNO_NEXT_BUCKET_ALLOCNO (a))
+  for (n = 0, a = *bucket_ptr;
+       a != NULL;
+       a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
     sorted_allocnos[n++] = a;
   if (n <= 1)
     return;
@@ -1495,10 +1611,10 @@ sort_bucket (ira_allocno_t *bucket_ptr,
   for (n--; n >= 0; n--)
     {
       a = sorted_allocnos[n];
-      ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = head;
-      ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
+      ALLOCNO_COLOR_DATA (a)->next_bucket_allocno = head;
+      ALLOCNO_COLOR_DATA (a)->prev_bucket_allocno = NULL;
       if (head != NULL)
-	ALLOCNO_PREV_BUCKET_ALLOCNO (head) = a;
+	ALLOCNO_COLOR_DATA (head)->prev_bucket_allocno = a;
       head = a;
     }
   *bucket_ptr = head;
@@ -1521,17 +1637,18 @@ add_allocno_to_ordered_bucket (ira_alloc
     }
   for (before = *bucket_ptr, after = NULL;
        before != NULL;
-       after = before, before = ALLOCNO_NEXT_BUCKET_ALLOCNO (before))
+       after = before,
+	 before = ALLOCNO_COLOR_DATA (before)->next_bucket_allocno)
     if (bucket_allocno_compare_func (&allocno, &before) < 0)
       break;
-  ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno) = before;
-  ALLOCNO_PREV_BUCKET_ALLOCNO (allocno) = after;
+  ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno = before;
+  ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno = after;
   if (after == NULL)
     *bucket_ptr = allocno;
   else
-    ALLOCNO_NEXT_BUCKET_ALLOCNO (after) = allocno;
+    ALLOCNO_COLOR_DATA (after)->next_bucket_allocno = allocno;
   if (before != NULL)
-    ALLOCNO_PREV_BUCKET_ALLOCNO (before) = allocno;
+    ALLOCNO_COLOR_DATA (before)->prev_bucket_allocno = allocno;
 }
 
 /* Delete ALLOCNO from bucket *BUCKET_PTR.  It should be there before
@@ -1547,20 +1664,20 @@ delete_allocno_from_bucket (ira_allocno_
       uncolorable_allocnos_num--;
       ira_assert (uncolorable_allocnos_num >= 0);
     }
-  prev_allocno = ALLOCNO_PREV_BUCKET_ALLOCNO (allocno);
-  next_allocno = ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno);
+  prev_allocno = ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno;
+  next_allocno = ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno;
   if (prev_allocno != NULL)
-    ALLOCNO_NEXT_BUCKET_ALLOCNO (prev_allocno) = next_allocno;
+    ALLOCNO_COLOR_DATA (prev_allocno)->next_bucket_allocno = next_allocno;
   else
     {
       ira_assert (*bucket_ptr == allocno);
       *bucket_ptr = next_allocno;
     }
   if (next_allocno != NULL)
-    ALLOCNO_PREV_BUCKET_ALLOCNO (next_allocno) = prev_allocno;
+    ALLOCNO_COLOR_DATA (next_allocno)->prev_bucket_allocno = prev_allocno;
 }
 
-/* Put A onto the coloring stack without removing it from its
+/* Put allocno A onto the coloring stack without removing it from its
    bucket.  Pushing allocno to the coloring stack can result in moving
    conflicting allocnos from the uncolorable bucket to the colorable
    one.  */
@@ -1570,20 +1687,23 @@ push_allocno_to_stack (ira_allocno_t a)
   ira_allocno_t conflict_a;
   enum reg_class aclass;
   ira_allocno_conflict_iterator aci;
+  color_data_t data, conflict_data;
 
-  ALLOCNO_IN_GRAPH_P (a) = false;
+  data = ALLOCNO_COLOR_DATA (a);
+  data->in_graph_p = false;
   VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, a);
   aclass = ALLOCNO_CLASS (a);
   if (aclass == NO_REGS)
     return;
   FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
     {
-      if (! ALLOCNO_COLORABLE_P (conflict_a)
-	  && ALLOCNO_IN_GRAPH_P (conflict_a)
+      conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
+      if (! conflict_data->colorable_p
+	  && conflict_data->in_graph_p
 	  && ! ALLOCNO_ASSIGNED_P (conflict_a)
 	  && (hard_reg_set_intersect_p
-	      (ALLOCNO_PROFITABLE_HARD_REGS (a),
-	       ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))
+	      (data->profitable_hard_regs,
+	       conflict_data->profitable_hard_regs)))
 	{
 	  ira_assert (bitmap_bit_p (coloring_allocno_bitmap,
 				    ALLOCNO_NUM (conflict_a)));
@@ -1612,14 +1732,16 @@ remove_allocno_from_bucket_and_push (ira
       fprintf (ira_dump_file, "      Pushing");
       ira_print_expanded_allocno (allocno);
       if (colorable_p)
-	fprintf (ira_dump_file, "(cost %d)\n", ALLOCNO_TEMP (allocno));
+	fprintf (ira_dump_file, "(cost %d)\n",
+		 ALLOCNO_COLOR_DATA (allocno)->temp);
       else
 	fprintf (ira_dump_file, "(potential spill: %spri=%d, cost=%d)\n",
 		 ALLOCNO_BAD_SPILL_P (allocno) ? "bad spill, " : "",
-		 allocno_spill_priority (allocno), ALLOCNO_TEMP (allocno));
+		 allocno_spill_priority (allocno),
+		 ALLOCNO_COLOR_DATA (allocno)->temp);
     }
   if (! colorable_p)
-    ALLOCNO_MAY_BE_SPILLED_P (allocno) = true;
+    ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p = true;
   push_allocno_to_stack (allocno);
 }
 
@@ -1695,13 +1817,16 @@ calculate_allocno_spill_cost (ira_allocn
 	     + ira_memory_move_cost[mode][rclass][1]
 	     * ira_loop_edge_freq (loop_node, regno, false));
   else
-    cost += ((ira_memory_move_cost[mode][rclass][1]
-	      * ira_loop_edge_freq (loop_node, regno, true)
-	      + ira_memory_move_cost[mode][rclass][0]
-	      * ira_loop_edge_freq (loop_node, regno, false))
-	     - (ira_get_register_move_cost (mode, rclass, rclass)
-		* (ira_loop_edge_freq (loop_node, regno, false)
-		   + ira_loop_edge_freq (loop_node, regno, true))));
+    {
+      ira_init_register_move_cost_if_necessary (mode);
+      cost += ((ira_memory_move_cost[mode][rclass][1]
+		* ira_loop_edge_freq (loop_node, regno, true)
+		+ ira_memory_move_cost[mode][rclass][0]
+		* ira_loop_edge_freq (loop_node, regno, false))
+	       - (ira_register_move_cost[mode][rclass][rclass]
+		  * (ira_loop_edge_freq (loop_node, regno, false)
+		     + ira_loop_edge_freq (loop_node, regno, true))));
+    }
   return cost;
 }
 
@@ -1719,7 +1844,8 @@ allocno_spill_priority_compare (ira_allo
   pri2 = allocno_spill_priority (a2);
   if ((diff = pri1 - pri2) != 0)
     return diff;
-  if ((diff = ALLOCNO_TEMP (a1) - ALLOCNO_TEMP (a2)) != 0)
+  if ((diff
+       = ALLOCNO_COLOR_DATA (a1)->temp - ALLOCNO_COLOR_DATA (a2)->temp) != 0)
     return diff;
   return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
 }
@@ -1745,13 +1871,13 @@ push_allocnos_to_stack (void)
   /* Calculate uncolorable allocno spill costs.  */
   for (a = uncolorable_allocno_bucket;
        a != NULL;
-       a = ALLOCNO_NEXT_BUCKET_ALLOCNO (a))
+       a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
     if (ALLOCNO_CLASS (a) != NO_REGS)
       {
 	cost = calculate_allocno_spill_cost (a);
 	/* ??? Remove cost of copies between the coalesced
 	   allocnos.  */
-	ALLOCNO_TEMP (a) = cost;
+	ALLOCNO_COLOR_DATA (a)->temp = cost;
       }
   sort_bucket (&uncolorable_allocno_bucket, allocno_spill_sort_compare);
   for (;;)
@@ -1806,21 +1932,23 @@ pop_allocnos_from_stack (void)
 	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
 	    fprintf (ira_dump_file, "spill\n");
 	}
-      ALLOCNO_IN_GRAPH_P (allocno) = true;
+      ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
     }
 }
 
-/* Set up number of available hard registers for A.  */
+/* Set up number of available hard registers for allocno A.  */
 static void
 setup_allocno_available_regs_num (ira_allocno_t a)
 {
   int i, n, hard_regno, hard_regs_num;
-  enum machine_mode mode;
   enum reg_class aclass;
   HARD_REG_SET temp_set;
+  enum machine_mode mode;
+  color_data_t data;
 
   aclass = ALLOCNO_CLASS (a);
-  ALLOCNO_AVAILABLE_REGS_NUM (a) = 0;
+  data = ALLOCNO_COLOR_DATA (a);
+  data->available_regs_num = 0;
   if (aclass == NO_REGS)
     return;
   COPY_HARD_REG_SET (temp_set, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
@@ -1830,10 +1958,10 @@ setup_allocno_available_regs_num (ira_al
     {
       hard_regno = ira_class_hard_regs[aclass][i];
       if (! ira_hard_reg_set_intersection_p (hard_regno, mode, temp_set)
-	  && TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a), hard_regno))
+	  && TEST_HARD_REG_BIT (data->profitable_hard_regs, hard_regno))
 	n++;
     }
-  ALLOCNO_AVAILABLE_REGS_NUM (a) = n;
+  data->available_regs_num = n;
   if (internal_flag_ira_verbose <= 2 || ira_dump_file == NULL)
     return;
   fprintf
@@ -1841,15 +1969,15 @@ setup_allocno_available_regs_num (ira_al
      "      Allocno a%dr%d of %s(%d) has %d avail. regs (confl. regs): ",
      ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
      reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
-  print_hard_reg_set (ira_dump_file, ALLOCNO_PROFITABLE_HARD_REGS (a), false);
+  print_hard_reg_set (ira_dump_file, data->profitable_hard_regs, false);
   fprintf (ira_dump_file, " (");
   print_hard_reg_set (ira_dump_file, temp_set, false);
   fprintf (ira_dump_file, " ) %snode: ",
-	   hard_reg_set_equal_p (ALLOCNO_PROFITABLE_HARD_REGS (a),
-				 ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set)
+	   hard_reg_set_equal_p (data->profitable_hard_regs,
+				 data->hard_regs_node->hard_regs->set)
 	   ? "" : "^");
   print_hard_reg_set (ira_dump_file,
-		      ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set, false);
+		      data->hard_regs_node->hard_regs->set, false);
   fprintf (ira_dump_file, "\n");
 }
 
@@ -1858,7 +1986,7 @@ setup_allocno_available_regs_num (ira_al
 static void
 put_allocno_into_bucket (ira_allocno_t allocno)
 {
-  ALLOCNO_IN_GRAPH_P (allocno) = true;
+  ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
   setup_allocno_available_regs_num (allocno);
   if (setup_left_conflict_sizes_p (allocno))
     add_allocno_to_bucket (allocno, &colorable_allocno_bucket);
@@ -1930,7 +2058,7 @@ improve_allocation (void)
   EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
     {
       a = ira_allocnos[i];
-      if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+      if (hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs))
 	continue;
       aclass = ALLOCNO_CLASS (a);
       allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
@@ -1945,13 +2073,13 @@ improve_allocation (void)
 	  = allocno_costs[ira_class_hard_reg_index[aclass][hard_regno]];
       try_p = false;
       ira_assert (hard_reg_set_subset_p
-		  (ALLOCNO_PROFITABLE_HARD_REGS (a),
+		  (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
 		   reg_class_contents[aclass]));
       class_size = ira_class_hard_regs_num[aclass];
       for (j = 0; j < class_size; j++)
 	{
 	  hard_regno = ira_class_hard_regs[aclass][j];
-	  if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	  if (! TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
 				   hard_regno))
 	    continue;
 	  ira_assert (ira_class_hard_reg_index[aclass][hard_regno] == j);
@@ -1990,14 +2118,14 @@ improve_allocation (void)
 	       r >= 0 && r + hard_regno_nregs[r][mode] > conflict_hard_regno;
 	       r--)
 	    if (TEST_HARD_REG_BIT
-		(ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+		(ALLOCNO_COLOR_DATA (a)->profitable_hard_regs, r)
 		&& ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
 	      costs[r] += spill_cost;
 	  for (r = conflict_hard_regno + 1;
 	       r < conflict_hard_regno + conflict_nregs;
 	       r++)
 	    if (TEST_HARD_REG_BIT
-		(ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+		(ALLOCNO_COLOR_DATA (a)->profitable_hard_regs, r)
 		&& ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
 	      costs[r] += spill_cost;
 	}
@@ -2006,7 +2134,7 @@ improve_allocation (void)
       for (j = 0; j < class_size; j++)
 	{
 	  hard_regno = ira_class_hard_regs[aclass][j];
-	  if (TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+	  if (TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
 				 hard_regno)
 	      && (ira_hard_reg_not_in_set_p
 		  (hard_regno, ALLOCNO_MODE (a),
@@ -2158,8 +2286,9 @@ color_allocnos (void)
 	{
 	  a = ira_allocnos[i];
 	  if (ALLOCNO_CLASS (a) != NO_REGS
-	      && ! hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
-	    ALLOCNO_IN_GRAPH_P (a) = true;
+	      && ! hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)
+					 ->profitable_hard_regs))
+	    ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
 	  else
 	    {
 	      ALLOCNO_HARD_REGNO (a) = -1;
@@ -2180,7 +2309,7 @@ color_allocnos (void)
       EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
 	{
 	  a = ira_allocnos[i];
-	  if (ALLOCNO_IN_GRAPH_P (a))
+	  if (ALLOCNO_COLOR_DATA (a)->in_graph_p)
 	    put_allocno_into_bucket (a);
 	}
       push_allocnos_to_stack ();
@@ -2253,7 +2382,7 @@ print_loop_title (ira_loop_tree_node_t l
 static void
 color_pass (ira_loop_tree_node_t loop_tree_node)
 {
-  int regno, hard_regno, index = -1;
+  int regno, hard_regno, index = -1, n;
   int cost, exit_freq, enter_freq;
   unsigned int j;
   bitmap_iterator bi;
@@ -2268,13 +2397,25 @@ color_pass (ira_loop_tree_node_t loop_tr
 
   bitmap_copy (coloring_allocno_bitmap, loop_tree_node->all_allocnos);
   bitmap_copy (consideration_allocno_bitmap, coloring_allocno_bitmap);
+  n = 0;
   EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
     {
       a = ira_allocnos[j];
+      n++;
       if (! ALLOCNO_ASSIGNED_P (a))
 	continue;
       bitmap_clear_bit (coloring_allocno_bitmap, ALLOCNO_NUM (a));
     }
+  allocno_color_data
+    = (color_data_t) ira_allocate (sizeof (struct color_data) * n);
+  memset (allocno_color_data, 0, sizeof (struct color_data) * n);
+  n = 0;
+  EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
+    {
+      a = ira_allocnos[j];
+      ALLOCNO_ADD_DATA (a) = allocno_color_data + n;
+      n++;
+    }
   /* Color all mentioned allocnos including transparent ones.  */
   color_allocnos ();
   /* Process caps.  They are processed just once.  */
@@ -2382,7 +2523,8 @@ color_pass (ira_loop_tree_node_t loop_tr
 	  else
 	    {
 	      aclass = ALLOCNO_CLASS (subloop_allocno);
-	      cost = (ira_get_register_move_cost (mode, rclass, rclass)
+	      ira_init_register_move_cost_if_necessary (mode);
+	      cost = (ira_register_move_cost[mode][rclass][rclass]
 		      * (exit_freq + enter_freq));
 	      ira_allocate_and_set_or_copy_costs
 		(&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), aclass,
@@ -2404,6 +2546,12 @@ color_pass (ira_loop_tree_node_t loop_tr
 	    }
 	}
     }
+  ira_free (allocno_color_data);
+  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
+    {
+      a = ira_allocnos[j];
+      ALLOCNO_ADD_DATA (a) = NULL;
+    }
 }
 
 /* Initialize the common data for coloring and calls functions to do
@@ -2471,6 +2619,7 @@ move_spill_restore (void)
 		  - (ALLOCNO_HARD_REG_COSTS (a) == NULL
 		     ? ALLOCNO_CLASS_COST (a)
 		     : ALLOCNO_HARD_REG_COSTS (a)[index]));
+	  ira_init_register_move_cost_if_necessary (mode);
 	  for (subloop_node = loop_node->subloops;
 	       subloop_node != NULL;
 	       subloop_node = subloop_node->subloop_next)
@@ -2498,7 +2647,7 @@ move_spill_restore (void)
 		    += (ira_memory_move_cost[mode][rclass][0] * exit_freq
 			+ ira_memory_move_cost[mode][rclass][1] * enter_freq);
 		  if (hard_regno2 != hard_regno)
-		    cost -= (ira_get_register_move_cost (mode, rclass, rclass)
+		    cost -= (ira_register_move_cost[mode][rclass][rclass]
 			     * (exit_freq + enter_freq));
 		}
 	    }
@@ -2517,7 +2666,7 @@ move_spill_restore (void)
 		    += (ira_memory_move_cost[mode][rclass][1] * exit_freq
 			+ ira_memory_move_cost[mode][rclass][0] * enter_freq);
 		  if (hard_regno2 != hard_regno)
-		    cost -= (ira_get_register_move_cost (mode, rclass, rclass)
+		    cost -= (ira_register_move_cost[mode][rclass][rclass]
 			     * (exit_freq + enter_freq));
 		}
 	    }
@@ -2560,6 +2709,7 @@ update_curr_costs (ira_allocno_t a)
   if (aclass == NO_REGS)
     return;
   mode = ALLOCNO_MODE (a);
+  ira_init_register_move_cost_if_necessary (mode);
   for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
     {
       if (cp->first == a)
@@ -2583,8 +2733,8 @@ update_curr_costs (ira_allocno_t a)
       if (i < 0)
 	continue;
       cost = (cp->first == a
-	      ? ira_get_register_move_cost (mode, rclass, aclass)
-	      : ira_get_register_move_cost (mode, aclass, rclass));
+	      ? ira_register_move_cost[mode][rclass][aclass]
+	      : ira_register_move_cost[mode][aclass][rclass]);
       ira_allocate_and_set_or_copy_costs
 	(&ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a),
 	 ALLOCNO_HARD_REG_COSTS (a));
@@ -2734,6 +2884,27 @@ static bool allocno_coalesced_p;
    coalescing.  */
 static bitmap processed_coalesced_allocno_bitmap;
 
+/* See below.  */
+typedef struct coalesce_data *coalesce_data_t;
+
+/* To decrease footprint of ira_allocno structure we store all data
+   needed only for coalescing in the following structure.  */
+struct coalesce_data
+{
+  /* Coalesced allocnos form a cyclic list.  One allocno given by
+     FIRST represents all coalesced allocnos.  The
+     list is chained by NEXT.  */
+  ira_allocno_t first;
+  ira_allocno_t next;
+  int temp;
+};
+
+/* Container for storing allocno data concerning coalescing.  */
+static coalesce_data_t allocno_coalesce_data;
+
+/* Macro to access the data concerning coalescing.  */
+#define ALLOCNO_COALESCE_DATA(a) ((coalesce_data_t) ALLOCNO_ADD_DATA (a))
+
 /* The function is used to sort allocnos according to their execution
    frequencies.  */
 static int
@@ -2760,21 +2931,21 @@ merge_allocnos (ira_allocno_t a1, ira_al
 {
   ira_allocno_t a, first, last, next;
 
-  first = ALLOCNO_FIRST_COALESCED_ALLOCNO (a1);
-  a = ALLOCNO_FIRST_COALESCED_ALLOCNO (a2);
+  first = ALLOCNO_COALESCE_DATA (a1)->first;
+  a = ALLOCNO_COALESCE_DATA (a2)->first;
   if (first == a)
     return;
-  for (last = a2, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
-       a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+  for (last = a2, a = ALLOCNO_COALESCE_DATA (a2)->next;;
+       a = ALLOCNO_COALESCE_DATA (a)->next)
     {
-      ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = first;
+      ALLOCNO_COALESCE_DATA (a)->first = first;
       if (a == a2)
 	break;
       last = a;
     }
-  next = ALLOCNO_NEXT_COALESCED_ALLOCNO (first);
-  ALLOCNO_NEXT_COALESCED_ALLOCNO (first) = a2;
-  ALLOCNO_NEXT_COALESCED_ALLOCNO (last) = next;
+  next = allocno_coalesce_data[ALLOCNO_NUM (first)].next;
+  allocno_coalesce_data[ALLOCNO_NUM (first)].next = a2;
+  allocno_coalesce_data[ALLOCNO_NUM (last)].next = next;
 }
 
 /* Return TRUE if there are conflicting allocnos from two sets of
@@ -2790,19 +2961,19 @@ coalesced_allocno_conflict_p (ira_allocn
   if (allocno_coalesced_p)
     {
       bitmap_clear (processed_coalesced_allocno_bitmap);
-      for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
-	   a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+      for (a = ALLOCNO_COALESCE_DATA (a1)->next;;
+	   a = ALLOCNO_COALESCE_DATA (a)->next)
 	{
 	  bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
 	  if (a == a1)
 	    break;
 	}
     }
-  for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
-       a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+  for (a = ALLOCNO_COALESCE_DATA (a2)->next;;
+       a = ALLOCNO_COALESCE_DATA (a)->next)
     {
-      for (conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
-	   conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_a))
+      for (conflict_a = ALLOCNO_COALESCE_DATA (a1)->next;;
+	   conflict_a = ALLOCNO_COALESCE_DATA (conflict_a)->next)
 	{
 	  if (allocnos_have_intersected_live_ranges_p (a, conflict_a))
 	    return true;
@@ -2890,8 +3061,8 @@ coalesce_allocnos (void)
       for (n = 0; i < cp_num; i++)
 	{
 	  cp = sorted_copies[i];
-	  if (ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->first)
-	      != ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->second))
+	  if (allocno_coalesce_data[ALLOCNO_NUM (cp->first)].first
+	      != allocno_coalesce_data[ALLOCNO_NUM (cp->second)].first)
 	    sorted_copies[n++] = cp;
 	}
       cp_num = n;
@@ -2989,18 +3160,18 @@ setup_coalesced_allocno_costs_and_nums (
 	  regno_coalesced_allocno_num[regno] = ++num;
 	  continue;
 	}
-      if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno)
+      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
 	continue;
       num++;
-      for (cost = 0, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
-	   a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+      for (cost = 0, a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+	   a = ALLOCNO_COALESCE_DATA (a)->next)
 	{
 	  cost += ALLOCNO_FREQ (a);
 	  if (a == allocno)
 	    break;
 	}
-      for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
-	   a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+      for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+	   a = ALLOCNO_COALESCE_DATA (a)->next)
 	{
 	  regno_coalesced_allocno_num[ALLOCNO_REGNO (a)] = num;
 	  regno_coalesced_allocno_cost[ALLOCNO_REGNO (a)] = cost;
@@ -3027,7 +3198,7 @@ collect_spilled_coalesced_allocnos (int 
       regno = pseudo_regnos[i];
       allocno = ira_regno_allocno_map[regno];
       if (allocno == NULL || ALLOCNO_HARD_REGNO (allocno) >= 0
-	  || ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno)
+	  || ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
 	continue;
       spilled_coalesced_allocnos[num++] = allocno;
     }
@@ -3047,8 +3218,8 @@ slot_coalesced_allocno_live_ranges_inter
 {
   ira_allocno_t a;
 
-  for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
-       a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+  for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+       a = ALLOCNO_COALESCE_DATA (a)->next)
     {
       if (ira_allocno_live_ranges_intersect_p
 	  (slot_coalesced_allocnos_live_ranges[n], ALLOCNO_LIVE_RANGES (a)))
@@ -3068,9 +3239,9 @@ setup_slot_coalesced_allocno_live_ranges
   ira_allocno_t a;
   live_range_t r;
 
-  n = ALLOCNO_TEMP (allocno);
-  for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
-       a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+  n = ALLOCNO_COALESCE_DATA (allocno)->temp;
+  for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+       a = ALLOCNO_COALESCE_DATA (a)->next)
     {
       r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
       slot_coalesced_allocnos_live_ranges[n]
@@ -3104,7 +3275,7 @@ coalesce_spill_slots (ira_allocno_t *spi
   for (i = 0; i < num; i++)
     {
       allocno = spilled_coalesced_allocnos[i];
-      if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
+      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
 	  || bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (allocno))
 	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
 	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
@@ -3113,8 +3284,8 @@ coalesce_spill_slots (ira_allocno_t *spi
       for (j = 0; j < i; j++)
 	{
 	  a = spilled_coalesced_allocnos[j];
-	  n = ALLOCNO_TEMP (a);
-	  if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
+	  n = ALLOCNO_COALESCE_DATA (a)->temp;
+	  if (ALLOCNO_COALESCE_DATA (a)->first == a
 	      && ! bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (a))
 	      && (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
 		  || (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
@@ -3126,7 +3297,7 @@ coalesce_spill_slots (ira_allocno_t *spi
 	{
 	  /* No coalescing: set up number for coalesced allocnos
 	     represented by ALLOCNO.  */
-	  ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++;
+	  ALLOCNO_COALESCE_DATA (allocno)->temp = last_coalesced_allocno_num++;
 	  setup_slot_coalesced_allocno_live_ranges (allocno);
 	}
       else
@@ -3138,10 +3309,11 @@ coalesce_spill_slots (ira_allocno_t *spi
 		     "      Coalescing spilled allocnos a%dr%d->a%dr%d\n",
 		     ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
 		     ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
-	  ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a);
+	  ALLOCNO_COALESCE_DATA (allocno)->temp
+	    = ALLOCNO_COALESCE_DATA (a)->temp;
 	  setup_slot_coalesced_allocno_live_ranges (allocno);
 	  merge_allocnos (a, allocno);
-	  ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a);
+	  ira_assert (ALLOCNO_COALESCE_DATA (a)->first == a);
 	}
     }
   for (i = 0; i < ira_allocnos_num; i++)
@@ -3163,6 +3335,7 @@ ira_sort_regnos_for_alter_reg (int *pseu
   int max_regno = max_reg_num ();
   int i, regno, num, slot_num;
   ira_allocno_t allocno, a;
+  ira_allocno_iterator ai;
   ira_allocno_t *spilled_coalesced_allocnos;
 
   /* Set up allocnos can be coalesced.  */
@@ -3176,6 +3349,16 @@ ira_sort_regnos_for_alter_reg (int *pseu
     }
   allocno_coalesced_p = false;
   processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
+  allocno_coalesce_data
+    = (coalesce_data_t) ira_allocate (sizeof (struct coalesce_data)
+				      * ira_allocnos_num);
+  /* Initialize coalesce data for allocnos.  */
+  FOR_EACH_ALLOCNO (a, ai)
+    {
+      ALLOCNO_ADD_DATA (a) = allocno_coalesce_data + ALLOCNO_NUM (a);
+      ALLOCNO_COALESCE_DATA (a)->first = a;
+      ALLOCNO_COALESCE_DATA (a)->next = a;
+    }
   coalesce_allocnos ();
   ira_free_bitmap (coloring_allocno_bitmap);
   regno_coalesced_allocno_cost
@@ -3213,7 +3396,7 @@ ira_sort_regnos_for_alter_reg (int *pseu
   for (i = 0; i < num; i++)
     {
       allocno = spilled_coalesced_allocnos[i];
-      if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
+      if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
 	  || ALLOCNO_HARD_REGNO (allocno) >= 0
 	  || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
 	      && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
@@ -3222,8 +3405,8 @@ ira_sort_regnos_for_alter_reg (int *pseu
       if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
 	fprintf (ira_dump_file, "      Slot %d (freq,size):", slot_num);
       slot_num++;
-      for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
-	   a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+      for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+	   a = ALLOCNO_COALESCE_DATA (a)->next)
 	{
 	  ira_assert (ALLOCNO_HARD_REGNO (a) < 0);
 	  ALLOCNO_HARD_REGNO (a) = -slot_num;
@@ -3244,6 +3427,9 @@ ira_sort_regnos_for_alter_reg (int *pseu
   /* Sort regnos according the slot numbers.  */
   regno_max_ref_width = reg_max_ref_width;
   qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare);
+  FOR_EACH_ALLOCNO (a, ai)
+    ALLOCNO_ADD_DATA (a) = NULL;
+  ira_free (allocno_coalesce_data);
   ira_free (regno_coalesced_allocno_num);
   ira_free (regno_coalesced_allocno_cost);
 }
--- ./ira-conflicts.c	2010-07-06 11:37:23.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-conflicts.c	2010-06-30 17:55:10.000000000 -0400
@@ -68,6 +68,7 @@ static bool
 build_conflict_bit_table (void)
 {
   int i, num, id, allocated_words_num, conflict_bit_vec_words_num;
+  int a_min, a_max;
   unsigned int j;
   enum reg_class aclass;
   ira_allocno_t allocno, live_a;
@@ -75,6 +76,7 @@ build_conflict_bit_table (void)
   ira_allocno_iterator ai;
   sparseset allocnos_live;
   int allocno_set_words;
+  IRA_INT_TYPE *a_conflicts;
 
   allocno_set_words = (ira_allocnos_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
   allocated_words_num = 0;
@@ -132,6 +134,9 @@ build_conflict_bit_table (void)
 	  allocno = r->allocno;
 	  num = ALLOCNO_NUM (allocno);
 	  id = ALLOCNO_CONFLICT_ID (allocno);
+	  a_min = ALLOCNO_MIN (allocno);
+	  a_max = ALLOCNO_MAX (allocno);
+	  a_conflicts = conflicts[num];
 	  aclass = ALLOCNO_CLASS (allocno);
 	  sparseset_set_bit (allocnos_live, num);
 	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
@@ -142,10 +147,9 @@ build_conflict_bit_table (void)
 		  /* Don't set up conflict for the allocno with itself.  */
 		  && num != (int) j)
 		{
-		  SET_MINMAX_SET_BIT (conflicts[num],
+		  SET_MINMAX_SET_BIT (a_conflicts,
 				      ALLOCNO_CONFLICT_ID (live_a),
-				      ALLOCNO_MIN (allocno),
-				      ALLOCNO_MAX (allocno));
+				      a_min, a_max);
 		  SET_MINMAX_SET_BIT (conflicts[j], id,
 				      ALLOCNO_MIN (live_a),
 				      ALLOCNO_MAX (live_a));
@@ -378,7 +382,8 @@ process_regs_for_copy (rtx reg1, rtx reg
     }
   else
     return false;
-  if (! IN_RANGE (allocno_preferenced_hard_regno, 0, FIRST_PSEUDO_REGISTER - 1))
+  if (! IN_RANGE (allocno_preferenced_hard_regno,
+		  0, FIRST_PSEUDO_REGISTER - 1))
     /* Can not be tied.  */
     return false;
   rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
@@ -392,10 +397,11 @@ process_regs_for_copy (rtx reg1, rtx reg
   if (index < 0)
     /* Can not be tied.  It is not in the allocno class.  */
     return false;
+  ira_init_register_move_cost_if_necessary (mode);
   if (HARD_REGISTER_P (reg1))
-    cost = ira_get_register_move_cost (mode, aclass, rclass) * freq;
+    cost = ira_register_move_cost[mode][aclass][rclass] * freq;
   else
-    cost = ira_get_register_move_cost (mode, rclass, aclass) * freq;
+    cost = ira_register_move_cost[mode][rclass][aclass] * freq;
   do
     {
       ira_allocate_and_set_costs
@@ -459,7 +465,8 @@ add_insn_allocno_copies (rtx insn)
 			? SET_SRC (set)
 			: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
     {
-      process_regs_for_copy (SET_DEST (set), SET_SRC (set), false, insn, freq);
+      process_regs_for_copy (SET_DEST (set), SET_SRC (set),
+			     false, insn, freq);
       return;
     }
   /* Fast check of possibility of constraint or shuffle copies.  If
@@ -555,12 +562,13 @@ static ira_allocno_t *collected_conflict
 static void
 build_allocno_conflicts (ira_allocno_t a)
 {
-  int i, px, parent_num;
+  int i, px;
   int conflict_bit_vec_words_num;
   ira_allocno_t parent_a, another_a, another_parent_a;
   ira_allocno_t *vec;
-  IRA_INT_TYPE *allocno_conflicts;
+  IRA_INT_TYPE *allocno_conflicts, *parent_conflicts;
   minmax_set_iterator asi;
+  int parent_min, parent_max;
 
   allocno_conflicts = conflicts[ALLOCNO_NUM (a)];
   px = 0;
@@ -596,7 +604,9 @@ build_allocno_conflicts (ira_allocno_t a
   if (parent_a == NULL)
     return;
   ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a));
-  parent_num = ALLOCNO_NUM (parent_a);
+  parent_conflicts = conflicts[ALLOCNO_NUM (parent_a)];
+  parent_min = ALLOCNO_MIN (parent_a);
+  parent_max = ALLOCNO_MAX (parent_a);
   FOR_EACH_BIT_IN_MINMAX_SET (allocno_conflicts,
 			      ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi)
     {
@@ -609,10 +619,9 @@ build_allocno_conflicts (ira_allocno_t a
       ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
       ira_assert (ALLOCNO_CLASS (another_a)
 		  == ALLOCNO_CLASS (another_parent_a));
-      SET_MINMAX_SET_BIT (conflicts[parent_num],
+      SET_MINMAX_SET_BIT (parent_conflicts,
 			  ALLOCNO_CONFLICT_ID (another_parent_a),
-			  ALLOCNO_MIN (parent_a),
-			  ALLOCNO_MAX (parent_a));
+			  parent_min, parent_max);
     }
 }
 
--- ./ira-costs.c	2010-07-06 14:50:37.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-costs.c	2010-07-01 14:25:12.000000000 -0400
@@ -492,30 +492,56 @@ record_reg_classes (int n_alts, int n_op
 		     Moreover, if we cannot tie them, this alternative
 		     needs to do a copy, which is one insn.  */
 		  struct costs *pp = this_op_costs[i];
+		  int *pp_costs = pp->cost;
 		  cost_classes_t cost_classes_ptr = regno_cost_classes[REGNO (op)];
 		  enum reg_class *cost_classes = cost_classes_ptr->classes;
+		  bool in_p = recog_data.operand_type[i] != OP_OUT;
+		  bool out_p = recog_data.operand_type[i] != OP_IN;
+		  enum reg_class op_class = classes[i];
+		  move_table *move_in_cost, *move_out_cost;
 
-		  for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+		  ira_init_register_move_cost_if_necessary (mode);
+		  if (! in_p)
 		    {
-		      rclass = cost_classes[k];
-		      pp->cost[k]
-			= (((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, rclass,
-							classes[i], false) : 0))
-			   * frequency);
+		      ira_assert (out_p);
+		      move_out_cost = ira_may_move_out_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k]
+			    = move_out_cost[op_class][rclass] * frequency;
+			}
+		    }
+		  else if (! out_p)
+		    {
+		      ira_assert (in_p);
+		      move_in_cost = ira_may_move_in_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k]
+			    = move_in_cost[rclass][op_class] * frequency;
+			}
+		    }
+		  else
+		    {
+		      move_in_cost = ira_may_move_in_cost[mode];
+		      move_out_cost = ira_may_move_out_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k] = ((move_in_cost[rclass][op_class]
+					  + move_out_cost[op_class][rclass])
+					 * frequency);
+			}
 		    }
 
 		  /* If the alternative actually allows memory, make
 		     things a bit cheaper since we won't need an extra
 		     insn to load it.  */
 		  pp->mem_cost
-		    = ((recog_data.operand_type[i] != OP_IN
-			? ira_memory_move_cost[mode][classes[i]][0] : 0)
-		       + (recog_data.operand_type[i] != OP_OUT
-			  ? ira_memory_move_cost[mode][classes[i]][1] : 0)
+		    = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
+		       + (in_p ? ira_memory_move_cost[mode][op_class][1] : 0)
 		       - allows_mem[i]) * frequency;
 
 		  /* If we have assigned a class to this allocno in
@@ -528,17 +554,15 @@ record_reg_classes (int n_alts, int n_op
 
 		      if (pref_class == NO_REGS)
 			alt_cost
-			  += ((recog_data.operand_type[i] != OP_IN
-			       ? ira_memory_move_cost[mode][classes[i]][0]
-			       : 0)
-			      + (recog_data.operand_type[i] != OP_OUT
-				 ? ira_memory_move_cost[mode][classes[i]][1]
+			  += ((out_p
+			       ? ira_memory_move_cost[mode][op_class][0] : 0)
+			      + (in_p
+				 ? ira_memory_move_cost[mode][op_class][1]
 				 : 0));
 		      else if (ira_reg_class_intersect
-			       [pref_class][classes[i]] == NO_REGS)
-			alt_cost += ira_get_register_move_cost (mode,
-								pref_class,
-								classes[i]);
+			       [pref_class][op_class] == NO_REGS)
+			alt_cost
+			  += ira_register_move_cost[mode][pref_class][op_class];
 		    }
 		  if (REGNO (ops[i]) != REGNO (ops[j])
 		      && ! find_reg_note (insn, REG_DEAD, op))
@@ -734,30 +758,56 @@ record_reg_classes (int n_alts, int n_op
 	      else
 		{
 		  struct costs *pp = this_op_costs[i];
+		  int *pp_costs = pp->cost;
 		  cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
 		  enum reg_class *cost_classes = cost_classes_ptr->classes;
+		  bool in_p = recog_data.operand_type[i] != OP_OUT;
+		  bool out_p = recog_data.operand_type[i] != OP_IN;
+		  enum reg_class op_class = classes[i];
+		  move_table *move_in_cost, *move_out_cost;
 
-		  for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+		  ira_init_register_move_cost_if_necessary (mode);
+		  if (! in_p)
 		    {
-		      rclass = cost_classes[k];
-		      pp->cost[k]
-			= (((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);
+		      ira_assert (out_p);
+		      move_out_cost = ira_may_move_out_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k]
+			    = move_out_cost[op_class][rclass] * frequency;
+			}
+		    }
+		  else if (! out_p)
+		    {
+		      ira_assert (in_p);
+		      move_in_cost = ira_may_move_in_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k]
+			    = move_in_cost[rclass][op_class] * frequency;
+			}
+		    }
+		  else
+		    {
+		      move_in_cost = ira_may_move_in_cost[mode];
+		      move_out_cost = ira_may_move_out_cost[mode];
+		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+			{
+			  rclass = cost_classes[k];
+			  pp_costs[k] = ((move_in_cost[rclass][op_class]
+					  + move_out_cost[op_class][rclass])
+					 * frequency);
+			}
 		    }
 
 		  /* If the alternative actually allows memory, make
 		     things a bit cheaper since we won't need an extra
 		     insn to load it.  */
 		  pp->mem_cost
-		    = ((recog_data.operand_type[i] != OP_IN
-			? ira_memory_move_cost[mode][classes[i]][0] : 0)
-		       + (recog_data.operand_type[i] != OP_OUT
-			  ? ira_memory_move_cost[mode][classes[i]][1] : 0)
+		    = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
+		       + (in_p ? ira_memory_move_cost[mode][op_class][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
@@ -769,17 +819,14 @@ record_reg_classes (int n_alts, int n_op
 
 		      if (pref_class == NO_REGS)
 			alt_cost
-			  += ((recog_data.operand_type[i] != OP_IN
-			       ? ira_memory_move_cost[mode][classes[i]][0]
-			       : 0)
-			      + (recog_data.operand_type[i] != OP_OUT
-				 ? ira_memory_move_cost[mode][classes[i]][1]
+			  += ((out_p
+			       ? ira_memory_move_cost[mode][op_class][0] : 0)
+			      + (in_p
+				 ? ira_memory_move_cost[mode][op_class][1]
 				 : 0));
-		      else if (ira_reg_class_intersect[pref_class][classes[i]]
+		      else if (ira_reg_class_intersect[pref_class][op_class]
 			       == NO_REGS)
-			alt_cost += ira_get_register_move_cost (mode,
-								pref_class,
-								classes[i]);
+			alt_cost += ira_register_move_cost[mode][pref_class][op_class];
 		    }
 		}
 	    }
@@ -822,6 +869,7 @@ record_reg_classes (int n_alts, int n_op
 	if (REG_P (ops[i]) && (regno = REGNO (ops[i])) >= FIRST_PSEUDO_REGISTER)
 	  {
 	    struct costs *pp = op_costs[i], *qq = this_op_costs[i];
+	    int *pp_costs = pp->cost, *qq_costs = qq->cost;
 	    int scale = 1 + (recog_data.operand_type[i] == OP_INOUT);
 	    cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
 
@@ -829,8 +877,8 @@ record_reg_classes (int n_alts, int n_op
 				(qq->mem_cost + op_cost_add) * scale);
 
 	    for (k = cost_classes_ptr->num - 1; k >= 0; k--)
-	      pp->cost[k]
-		= MIN (pp->cost[k], (qq->cost[k] + op_cost_add) * scale);
+	      pp_costs[k]
+		= MIN (pp_costs[k], (qq_costs[k] + op_cost_add) * scale);
 	  }
     }
 
@@ -1084,10 +1132,12 @@ record_address_regs (enum machine_mode m
     case REG:
       {
 	struct costs *pp;
+	int *pp_costs;
 	enum reg_class i;
 	int k, regno, add_cost;
 	cost_classes_t cost_classes_ptr;
 	enum reg_class *cost_classes;
+	move_table *move_in_cost;
 
 	if ((regno = REGNO (x)) < FIRST_PSEUDO_REGISTER)
 	  break;
@@ -1102,14 +1152,17 @@ record_address_regs (enum machine_mode m
 	  pp->mem_cost += add_cost;
 	cost_classes_ptr = regno_cost_classes[regno];
 	cost_classes = cost_classes_ptr->classes;
+	pp_costs = pp->cost;
+	ira_init_register_move_cost_if_necessary (Pmode);
+	move_in_cost = ira_may_move_in_cost[Pmode];
 	for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 	  {
 	    i = cost_classes[k];
-	    add_cost = (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2;
-	    if (INT_MAX - add_cost < pp->cost[k])
-	      pp->cost[k] = INT_MAX;
+	    add_cost = (move_in_cost[i][rclass] * scale) / 2;
+	    if (INT_MAX - add_cost < pp_costs[k])
+	      pp_costs[k] = INT_MAX;
 	    else 
-	      pp->cost[k] += add_cost;
+	      pp_costs[k] += add_cost;
 	  }
       }
       break;
@@ -1240,6 +1293,7 @@ scan_one_insn (rtx insn)
       {
 	struct costs *p = COSTS (costs, COST_INDEX (regno));
 	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];
 	int add_cost;
 
@@ -1250,11 +1304,11 @@ scan_one_insn (rtx insn)
 	  p->mem_cost += add_cost;
 	for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 	  {
-	    add_cost = q->cost[k];
-	    if (add_cost > 0 && INT_MAX - add_cost < p->cost[k])
-	      p->cost[k] = INT_MAX;
+	    add_cost = q_costs[k];
+	    if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
+	      p_costs[k] = INT_MAX;
 	    else
-	      p->cost[k] += add_cost;
+	      p_costs[k] += add_cost;
 	  }
       }
 
@@ -1497,6 +1551,8 @@ find_costs_and_classes (FILE *dump_file)
 #endif
 	  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;
+	  int i_mem_cost;
 	  int equiv_savings = regno_equiv_gains[i];
 
 	  if (! allocno_p)
@@ -1507,17 +1563,21 @@ find_costs_and_classes (FILE *dump_file)
 	      inc_dec_p = in_inc_dec[i];
 #endif
 	      memcpy (temp_costs, COSTS (costs, i), struct_costs_size);
+	      i_mem_cost = temp_costs->mem_cost;
 	    }
 	  else
 	    {
 	      if (ira_regno_allocno_map[i] == NULL)
 		continue;
 	      memset (temp_costs, 0, struct_costs_size);
+	      i_mem_cost = 0;
 	      /* Find cost of all allocnos with the same regno.  */
 	      for (a = ira_regno_allocno_map[i];
 		   a != NULL;
 		   a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
 		{
+		  int *a_costs, *p_costs;
+		      
 		  a_num = ALLOCNO_NUM (a);
 		  if ((flag_ira_region == IRA_REGION_ALL
 		       || flag_ira_region == IRA_REGION_MIXED)
@@ -1531,14 +1591,15 @@ find_costs_and_classes (FILE *dump_file)
 		      /* Propagate costs to upper levels in the region
 			 tree.  */
 		      parent_a_num = ALLOCNO_NUM (parent_a);
+		      a_costs = COSTS (total_allocno_costs, a_num)->cost;
+		      p_costs = COSTS (total_allocno_costs, parent_a_num)->cost;
 		      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 			{
-			  add_cost = COSTS (total_allocno_costs, a_num)->cost[k];
-			  if (add_cost > 0 && INT_MAX - add_cost
-			      < COSTS (total_allocno_costs, parent_a_num)->cost[k])
-			    COSTS (total_allocno_costs, parent_a_num)->cost[k] = INT_MAX;
+			  add_cost = a_costs[k];
+			  if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
+			    p_costs[k] = INT_MAX;
 			  else
-			    COSTS (total_allocno_costs, parent_a_num)->cost[k] += add_cost;
+			    p_costs[k] += add_cost;
 			}
 		      add_cost = COSTS (total_allocno_costs, a_num)->mem_cost;
 		      if (add_cost > 0
@@ -1552,19 +1613,20 @@ find_costs_and_classes (FILE *dump_file)
 			  += add_cost;
 
 		    }
+		  a_costs = COSTS (costs, a_num)->cost;
 		  for (k = cost_classes_ptr->num - 1; k >= 0; k--)
 		    {
-		      add_cost = COSTS (total_allocno_costs, a_num)->cost[k];
-		      if (add_cost > 0 && INT_MAX - add_cost < temp_costs->cost[k])
-			temp_costs->cost[k] = INT_MAX;
+		      add_cost = a_costs[k];
+		      if (add_cost > 0 && INT_MAX - add_cost < i_costs[k])
+			i_costs[k] = INT_MAX;
 		      else
-			temp_costs->cost[k] += add_cost;
+			i_costs[k] += add_cost;
 		    }
 		  add_cost = COSTS (costs, a_num)->mem_cost;
-		  if (add_cost && INT_MAX - add_cost < temp_costs->mem_cost)
-		    temp_costs->mem_cost = INT_MAX;
+		  if (add_cost && INT_MAX - add_cost < i_mem_cost)
+		    i_mem_cost = INT_MAX;
 		  else
-		    temp_costs->mem_cost += add_cost;
+		    i_mem_cost += add_cost;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 		  if (in_inc_dec[a_num])
 		    inc_dec_p = true;
@@ -1577,7 +1639,7 @@ find_costs_and_classes (FILE *dump_file)
 	    {
 	      temp_costs->mem_cost = 0;
 	      for (k = cost_classes_ptr->num - 1; k >= 0; k--)
-		temp_costs->cost[k] += equiv_savings;
+		i_costs[k] += equiv_savings;
 	    }
 
 	  best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
@@ -1600,21 +1662,21 @@ find_costs_and_classes (FILE *dump_file)
 #endif
 		  )
 		continue;
-	      if (temp_costs->cost[k] < best_cost)
+	      if (i_costs[k] < best_cost)
 		{
-		  best_cost = temp_costs->cost[k];
+		  best_cost = i_costs[k];
 		  best = (enum reg_class) rclass;
 		}
-	      else if (temp_costs->cost[k] == best_cost)
+	      else if (i_costs[k] == best_cost)
 		best = ira_reg_class_subunion[best][rclass];
 	      if (pass == flag_expensive_optimizations
-		  && temp_costs->cost[k] < temp_costs->mem_cost
+		  && i_costs[k] < i_mem_cost
 		  && (reg_class_size[reg_class_subunion[alt_class][rclass]]
 		      > reg_class_size[alt_class]))
 		alt_class = reg_class_subunion[alt_class][rclass];
 	    }
 	  alt_class = ira_allocno_class_translate[alt_class];
-	  if (best_cost > temp_costs->mem_cost)
+	  if (best_cost > i_mem_cost)
 	    regno_aclass[i] = NO_REGS;
 	  else
 	    {
@@ -1627,7 +1689,7 @@ find_costs_and_classes (FILE *dump_file)
 	    }
 	  if (pass == flag_expensive_optimizations)
 	    {
-	      if (best_cost > temp_costs->mem_cost)
+	      if (best_cost > i_mem_cost)
 		best = alt_class = NO_REGS;
 	      else if (best == alt_class)
 		alt_class = NO_REGS;
@@ -1642,7 +1704,7 @@ find_costs_and_classes (FILE *dump_file)
 	  regno_best_class[i] = best;
 	  if (! allocno_p)
 	    {
-	      pref[i] = best_cost > temp_costs->mem_cost ? NO_REGS : best;
+	      pref[i] = best_cost > i_mem_cost ? NO_REGS : best;
 	      continue;
 	    }
 	  for (a = ira_regno_allocno_map[i];
@@ -1654,6 +1716,9 @@ find_costs_and_classes (FILE *dump_file)
 		best = NO_REGS;
 	      else
 		{
+		  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;
@@ -1677,16 +1742,16 @@ find_costs_and_classes (FILE *dump_file)
 #endif
 			  )
 			;
-		      else if (COSTS (total_allocno_costs, a_num)->cost[k] < best_cost)
+		      else if (total_a_costs[k] < best_cost)
 			{
-			  best_cost = COSTS (total_allocno_costs, a_num)->cost[k];
-			  allocno_cost = COSTS (costs, a_num)->cost[k];
+			  best_cost = total_a_costs[k];
+			  allocno_cost = a_costs[k];
 			  best = (enum reg_class) rclass;
 			}
-		      else if (COSTS (total_allocno_costs, a_num)->cost[k] == best_cost)
+		      else if (total_a_costs[k] == best_cost)
 			{
 			  best = ira_reg_class_subunion[best][rclass];
-			  allocno_cost = MAX (allocno_cost, COSTS (costs, a_num)->cost[k]);
+			  allocno_cost = MAX (allocno_cost, a_costs[k]);
 			}
 		    }
 		  ALLOCNO_CLASS_COST (a) = allocno_cost;
@@ -1784,9 +1849,10 @@ process_bb_node_for_hard_reg_moves (ira_
 	continue;
       mode = ALLOCNO_MODE (a);
       hard_reg_class = REGNO_REG_CLASS (hard_regno);
+      ira_init_register_move_cost_if_necessary (mode);
       cost
-	= (to_p ? ira_get_register_move_cost (mode, hard_reg_class, rclass)
-	   : ira_get_register_move_cost (mode, rclass, hard_reg_class)) * freq;
+	= (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
+	   : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
       ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
 				  ALLOCNO_CLASS_COST (a));
       ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
--- ./ira-emit.c	2010-07-06 11:37:23.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-emit.c	2010-06-30 12:39:31.000000000 -0400
@@ -44,6 +44,73 @@ along with GCC; see the file COPYING3.  
 #include "ira-int.h"
 
 
+/* Data used to emit live range split insns and to flattening IR.  */
+ira_emit_data_t ira_allocno_emit_data;
+
+/* Definitions for vectors of pointers.  */
+typedef void *void_p;
+DEF_VEC_P (void_p);
+DEF_VEC_ALLOC_P (void_p,heap);
+
+/* Pointers to data allocated for allocnos being created during
+   emitting.  Usually there are quite few such allocnos because they
+   are created only for resolving loop in register shuffling.  */
+static VEC(void_p, heap) *new_allocno_emit_data_vec;
+
+/* Allocate and initiate the emit data.  */
+void
+ira_initiate_emit_data (void)
+{
+  ira_allocno_t a;
+  ira_allocno_iterator ai;
+
+  ira_allocno_emit_data
+    = (ira_emit_data_t) ira_allocate (ira_allocnos_num
+				      * sizeof (struct ira_emit_data));
+  memset (ira_allocno_emit_data, 0,
+	  ira_allocnos_num * sizeof (struct ira_emit_data));
+  FOR_EACH_ALLOCNO (a, ai)
+    ALLOCNO_ADD_DATA (a) = ira_allocno_emit_data + ALLOCNO_NUM (a);
+  new_allocno_emit_data_vec = VEC_alloc (void_p, heap, 50);
+
+}
+
+/* Free the emit data.  */
+void
+ira_finish_emit_data (void)
+{
+  void_p p;
+  ira_allocno_t a;
+  ira_allocno_iterator ai;
+
+  ira_free (ira_allocno_emit_data);
+  FOR_EACH_ALLOCNO (a, ai)
+    ALLOCNO_ADD_DATA (a) = NULL;
+  for (;VEC_length (void_p, new_allocno_emit_data_vec) != 0;)
+    {
+      p = VEC_pop (void_p, new_allocno_emit_data_vec);
+      ira_free (p);
+    }
+  VEC_free (void_p, heap, new_allocno_emit_data_vec);
+}
+
+/* Create and return a new allocno with given REGNO and
+   LOOP_TREE_NODE.  Allocate emit data for it.  */
+static ira_allocno_t
+create_new_allocno (int regno, ira_loop_tree_node_t loop_tree_node)
+{
+  ira_allocno_t a;
+
+  a = ira_create_allocno (regno, false, loop_tree_node);
+  ALLOCNO_ADD_DATA (a) = ira_allocate (sizeof (struct ira_emit_data));
+  memset (ALLOCNO_ADD_DATA (a), 0, sizeof (struct ira_emit_data));
+  VEC_safe_push (void_p, heap, new_allocno_emit_data_vec, ALLOCNO_ADD_DATA (a));
+  return a;
+}
+
+
+
+/* See comments below.  */
 typedef struct move *move_t;
 
 /* The structure represents an allocno move.  Both allocnos have the
@@ -171,7 +238,7 @@ change_regs (rtx *loc)
 	return false;
       if (ira_curr_regno_allocno_map[regno] == NULL)
 	return false;
-      reg = ALLOCNO_REG (ira_curr_regno_allocno_map[regno]);
+      reg = ALLOCNO_EMIT_DATA (ira_curr_regno_allocno_map[regno])->reg;
       if (reg == *loc)
 	return false;
       *loc = reg;
@@ -258,9 +325,9 @@ set_allocno_reg (ira_allocno_t allocno, 
        a != NULL;
        a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
     if (subloop_tree_node_p (ALLOCNO_LOOP_TREE_NODE (a), node))
-      ALLOCNO_REG (a) = reg;
+      ALLOCNO_EMIT_DATA (a)->reg = reg;
   for (a = ALLOCNO_CAP (allocno); a != NULL; a = ALLOCNO_CAP (a))
-    ALLOCNO_REG (a) = reg;
+    ALLOCNO_EMIT_DATA (a)->reg = reg;
   regno = ALLOCNO_REGNO (allocno);
   for (a = allocno;;)
     {
@@ -273,9 +340,9 @@ set_allocno_reg (ira_allocno_t allocno, 
 	}
       if (a == NULL)
 	continue;
-      if (ALLOCNO_CHILD_RENAMED_P (a))
+      if (ALLOCNO_EMIT_DATA (a)->child_renamed_p)
 	break;
-      ALLOCNO_CHILD_RENAMED_P (a) = true;
+      ALLOCNO_EMIT_DATA (a)->child_renamed_p = true;
     }
 }
 
@@ -346,14 +413,14 @@ store_can_be_removed_p (ira_allocno_t sr
   ira_assert (ALLOCNO_CAP_MEMBER (src_allocno) == NULL
 	      && ALLOCNO_CAP_MEMBER (dest_allocno) == NULL);
   orig_regno = ALLOCNO_REGNO (src_allocno);
-  regno = REGNO (ALLOCNO_REG (dest_allocno));
+  regno = REGNO (ALLOCNO_EMIT_DATA (dest_allocno)->reg);
   for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
        node != NULL;
        node = node->parent)
     {
       a = node->regno_allocno_map[orig_regno];
       ira_assert (a != NULL);
-      if (REGNO (ALLOCNO_REG (a)) == (unsigned) regno)
+      if (REGNO (ALLOCNO_EMIT_DATA (a)->reg) == (unsigned) regno)
 	/* We achieved the destination and everything is ok.  */
 	return true;
       else if (bitmap_bit_p (node->modified_regnos, orig_regno))
@@ -397,8 +464,8 @@ generate_edge_moves (edge e)
       {
 	src_allocno = src_map[regno];
 	dest_allocno = dest_map[regno];
-	if (REGNO (ALLOCNO_REG (src_allocno))
-	    == REGNO (ALLOCNO_REG (dest_allocno)))
+	if (REGNO (ALLOCNO_EMIT_DATA (src_allocno)->reg)
+	    == REGNO (ALLOCNO_EMIT_DATA (dest_allocno)->reg))
 	  continue;
 	/* Remove unnecessary stores at the region exit.  We should do
 	   this for readonly memory for sure and this is guaranteed by
@@ -409,8 +476,8 @@ generate_edge_moves (edge e)
 	    && ALLOCNO_HARD_REGNO (src_allocno) >= 0
 	    && store_can_be_removed_p (src_allocno, dest_allocno))
 	  {
-	    ALLOCNO_MEM_OPTIMIZED_DEST (src_allocno) = dest_allocno;
-	    ALLOCNO_MEM_OPTIMIZED_DEST_P (dest_allocno) = true;
+	    ALLOCNO_EMIT_DATA (src_allocno)->mem_optimized_dest = dest_allocno;
+	    ALLOCNO_EMIT_DATA (dest_allocno)->mem_optimized_dest_p = true;
 	    if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
 	      fprintf (ira_dump_file, "      Remove r%d:a%d->a%d(mem)\n",
 		       regno, ALLOCNO_NUM (src_allocno),
@@ -500,9 +567,10 @@ change_loop (ira_loop_tree_node_t node)
 		  || ira_reg_equiv_invariant_p[regno]
 		  || ira_reg_equiv_const[regno] != NULL_RTX))
 	    continue;
-	  original_reg = ALLOCNO_REG (allocno);
+	  original_reg = ALLOCNO_EMIT_DATA (allocno)->reg;
 	  if (parent_allocno == NULL
-	      || REGNO (ALLOCNO_REG (parent_allocno)) == REGNO (original_reg))
+	      || (REGNO (ALLOCNO_EMIT_DATA (parent_allocno)->reg)
+		  == REGNO (original_reg)))
 	    {
 	      if (internal_flag_ira_verbose > 3 && ira_dump_file)
 		fprintf (ira_dump_file, "  %i vs parent %i:",
@@ -526,11 +594,12 @@ change_loop (ira_loop_tree_node_t node)
 	continue;
       used_p = bitmap_bit_p (used_regno_bitmap, regno);
       bitmap_set_bit (used_regno_bitmap, regno);
-      ALLOCNO_SOMEWHERE_RENAMED_P (allocno) = true;
+      ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
       if (! used_p)
 	continue;
       bitmap_set_bit (renamed_regno_bitmap, regno);
-      set_allocno_reg (allocno, create_new_reg (ALLOCNO_REG (allocno)));
+      set_allocno_reg (allocno,
+		       create_new_reg (ALLOCNO_EMIT_DATA (allocno)->reg));
     }
 }
 
@@ -546,8 +615,8 @@ set_allocno_somewhere_renamed_p (void)
     {
       regno = ALLOCNO_REGNO (allocno);
       if (bitmap_bit_p (renamed_regno_bitmap, regno)
-	  && REGNO (ALLOCNO_REG (allocno)) == regno)
-	ALLOCNO_SOMEWHERE_RENAMED_P (allocno) = true;
+	  && REGNO (ALLOCNO_EMIT_DATA (allocno)->reg) == regno)
+	ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
     }
 }
 
@@ -724,15 +793,15 @@ modify_move_list (move_t list)
 		   subsequent IRA internal representation
 		   flattening.  */
 		new_allocno
-		  = ira_create_allocno (ALLOCNO_REGNO (set_move->to), false,
+		  = create_new_allocno (ALLOCNO_REGNO (set_move->to),
 					ALLOCNO_LOOP_TREE_NODE (set_move->to));
 		ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
-		ira_set_allocno_class
-		  (new_allocno, ALLOCNO_CLASS (set_move->to));
+		ira_set_allocno_class (new_allocno,
+				       ALLOCNO_CLASS (set_move->to));
 		ALLOCNO_ASSIGNED_P (new_allocno) = true;
 		ALLOCNO_HARD_REGNO (new_allocno) = -1;
-		ALLOCNO_REG (new_allocno)
-		  = create_new_reg (ALLOCNO_REG (set_move->to));
+		ALLOCNO_EMIT_DATA (new_allocno)->reg
+		  = create_new_reg (ALLOCNO_EMIT_DATA (set_move->to)->reg);
 		ALLOCNO_CONFLICT_ID (new_allocno) = ALLOCNO_NUM (new_allocno);
 		/* Make it possibly conflicting with all earlier
 		   created allocnos.  Cases where temporary allocnos
@@ -747,7 +816,7 @@ modify_move_list (move_t list)
 		  fprintf (ira_dump_file,
 			   "    Creating temporary allocno a%dr%d\n",
 			   ALLOCNO_NUM (new_allocno),
-			   REGNO (ALLOCNO_REG (new_allocno)));
+			   REGNO (ALLOCNO_EMIT_DATA (new_allocno)->reg));
 	      }
 	}
       if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
@@ -783,7 +852,8 @@ emit_move_list (move_t list, int freq)
   for (; list != NULL; list = list->next)
     {
       start_sequence ();
-      emit_move_insn (ALLOCNO_REG (list->to), ALLOCNO_REG (list->from));
+      emit_move_insn (ALLOCNO_EMIT_DATA (list->to)->reg,
+		      ALLOCNO_EMIT_DATA (list->from)->reg);
       list->insn = get_insns ();
       end_sequence ();
       /* The reload needs to have set up insn codes.  If the reload
@@ -814,8 +884,8 @@ emit_move_list (move_t list, int freq)
 	}
       else
 	{
-	  cost = (ira_get_register_move_cost (mode, aclass, aclass)
-		  * freq);
+	  ira_init_register_move_cost_if_necessary (mode);
+	  cost = ira_register_move_cost[mode][aclass][aclass] * freq;
 	  ira_shuffle_cost += cost;
 	}
       ira_overall_cost += cost;
@@ -938,7 +1008,7 @@ add_range_and_copies_from_move_list (mov
 	{
 	  if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
 	    fprintf (ira_dump_file, "    Allocate conflicts for a%dr%d\n",
-		     ALLOCNO_NUM (to), REGNO (ALLOCNO_REG (to)));
+		     ALLOCNO_NUM (to), REGNO (ALLOCNO_EMIT_DATA (to)->reg));
 	  ira_allocate_allocno_conflicts (to, n);
 	}
       bitmap_clear_bit (live_through, ALLOCNO_REGNO (from));
@@ -955,8 +1025,9 @@ add_range_and_copies_from_move_list (mov
       if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
 	fprintf (ira_dump_file, "    Adding cp%d:a%dr%d-a%dr%d\n",
 		 cp->num, ALLOCNO_NUM (cp->first),
-		 REGNO (ALLOCNO_REG (cp->first)), ALLOCNO_NUM (cp->second),
-		 REGNO (ALLOCNO_REG (cp->second)));
+		 REGNO (ALLOCNO_EMIT_DATA (cp->first)->reg),
+		 ALLOCNO_NUM (cp->second),
+		 REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
       r = ALLOCNO_LIVE_RANGES (from);
       if (r == NULL || r->finish >= 0)
 	{
@@ -966,7 +1037,7 @@ add_range_and_copies_from_move_list (mov
 	    fprintf (ira_dump_file,
 		     "    Adding range [%d..%d] to allocno a%dr%d\n",
 		     start, ira_max_point, ALLOCNO_NUM (from),
-		     REGNO (ALLOCNO_REG (from)));
+		     REGNO (ALLOCNO_EMIT_DATA (from)->reg));
 	}
       else
 	{
@@ -975,7 +1046,7 @@ add_range_and_copies_from_move_list (mov
 	    fprintf (ira_dump_file,
 		     "    Adding range [%d..%d] to allocno a%dr%d\n",
 		     r->start, ira_max_point, ALLOCNO_NUM (from),
-		     REGNO (ALLOCNO_REG (from)));
+		     REGNO (ALLOCNO_EMIT_DATA (from)->reg));
 	}
       ira_max_point++;
       ALLOCNO_LIVE_RANGES (to)
@@ -993,13 +1064,13 @@ add_range_and_copies_from_move_list (mov
 	    fprintf (ira_dump_file,
 		     "    Adding range [%d..%d] to allocno a%dr%d\n",
 		     r->start, r->finish, ALLOCNO_NUM (move->to),
-		     REGNO (ALLOCNO_REG (move->to)));
+		     REGNO (ALLOCNO_EMIT_DATA (move->to)->reg));
 	}
     }
   EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
     {
       a = node->regno_allocno_map[regno];
-      if ((to = ALLOCNO_MEM_OPTIMIZED_DEST (a)) != NULL)
+      if ((to = ALLOCNO_EMIT_DATA (a)->mem_optimized_dest) != NULL)
 	a = to;
       ALLOCNO_LIVE_RANGES (a)
 	= ira_create_allocno_live_range (a, start, ira_max_point - 1,
@@ -1010,7 +1081,7 @@ add_range_and_copies_from_move_list (mov
 	   "    Adding range [%d..%d] to live through %s allocno a%dr%d\n",
 	   start, ira_max_point - 1,
 	   to != NULL ? "upper level" : "",
-	   ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)));
+	   ALLOCNO_NUM (a), REGNO (ALLOCNO_EMIT_DATA (a)->reg));
     }
 }
 
@@ -1063,7 +1134,7 @@ ira_emit (bool loops_p)
   ira_allocno_iterator ai;
 
   FOR_EACH_ALLOCNO (a, ai)
-    ALLOCNO_REG (a) = regno_reg_rtx[ALLOCNO_REGNO (a)];
+    ALLOCNO_EMIT_DATA (a)->reg = regno_reg_rtx[ALLOCNO_REGNO (a)];
   if (! loops_p)
     return;
   at_bb_start = (move_t *) ira_allocate (sizeof (move_t) * last_basic_block);
--- t/ira-int.h	2010-07-06 20:43:32.000000000 -0400
+++ ira-int.h	2010-07-06 20:47:26.000000000 -0400
@@ -43,9 +43,9 @@ along with GCC; see the file COPYING3.  
    profile driven feedback is available and the function is never
    executed, frequency is always equivalent.  Otherwise rescale the
    edge frequency.  */
-#define REG_FREQ_FROM_EDGE_FREQ(freq)					      \
-  (optimize_size || (flag_branch_probabilities && !ENTRY_BLOCK_PTR->count)    \
-   ? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX)			      \
+#define REG_FREQ_FROM_EDGE_FREQ(freq)					   \
+  (optimize_size || (flag_branch_probabilities && !ENTRY_BLOCK_PTR->count) \
+   ? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX)			   \
    ? (freq * REG_FREQ_MAX / BB_FREQ_MAX) : 1)
 
 /* All natural loops.  */
@@ -219,57 +219,6 @@ extern int ira_max_point;
    live ranges with given start/finish point.  */
 extern live_range_t *ira_start_point_ranges, *ira_finish_point_ranges;
 
-/* See below.  */
-typedef struct allocno_hard_regs *allocno_hard_regs_t;
-
-/* The structure contains information about hard registers can be
-   assigned to allocnos.  Usually it is allocno profitable hard
-   registers but in some cases this set can be a bit different.  Major
-   reason of the difference is a requirement to use hard register sets
-   that form a tree or a forest (set of trees), i.e. hard register set
-   of a node should contain hard register sets of its subnodes.  */
-struct allocno_hard_regs
-{
-  /* Hard registers can be assigned to an allocno.  */
-  HARD_REG_SET set;
-  /* Overall (spilling) cost of all allocnos with given register
-     set.  */
-  long long int cost;
-};
-
-/* See below.  */
-typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
-
-/* A node representing allocno hard registers.  Such nodes form a
-   forest (set of trees).  Each subnode of given node in the forest
-   refers for hard register set (usually allocno profitable hard
-   register set) which is a subset of one referred from given
-   node.  */
-struct allocno_hard_regs_node
-{
-  /* Set up number of the node in preorder traversing of the forest.  */
-  int preorder_num;
-  /* Used for different calculation like finding conflict size of an
-     allocno.  */
-  int check;
-  /* Used for calculation of conflict size of an allocno.  The
-     conflict size of the allocno is maximal number of given allocno
-     hard registers needed for allocation of the conflicting allocnos.
-     Given allocno is trivially colored if this number plus the number
-     of hard registers needed for given allocno is not greater than
-     the number of given allocno hard register set.  */
-  int conflict_size;
-  /* The number of hard registers given by member hard_regs.  */
-  int hard_regs_num;
-  /* The following member is used to form the final forest.  */
-  bool used_p;
-  /* Pointer to the corresponding profitable hard registers.  */
-  allocno_hard_regs_t hard_regs;
-  /* Parent, first subnode, previous and next node with the same
-     parent in the forest.  */
-  allocno_hard_regs_node_t parent, first, prev, next;
-};
-
 /* A structure representing an allocno (allocation entity).  Allocno
    represents a pseudo-register in an allocation region.  If
    pseudo-register does not live in a region but it lives in the
@@ -287,16 +236,40 @@ struct ira_allocno
   int regno;
   /* Mode of the allocno which is the mode of the corresponding
      pseudo-register.  */
-  enum machine_mode mode;
+  ENUM_BITFIELD (machine_mode) mode : 8;
+  /* Register class which should be used for allocation for given
+     allocno.  NO_REGS means that we should use memory.  */
+  ENUM_BITFIELD (reg_class) aclass : 16;
+  /* During the reload, value TRUE means that we should not reassign a
+     hard register to the allocno got memory earlier.  It is set up
+     when we removed memory-memory move insn before each iteration of
+     the reload.  */
+  unsigned int dont_reassign_p : 1;
+#ifdef STACK_REGS
+  /* Set to TRUE if allocno can't be assigned to the stack hard
+     register correspondingly in this region and area including the
+     region and all its subregions recursively.  */
+  unsigned int no_stack_reg_p : 1, total_no_stack_reg_p : 1;
+#endif
+  /* TRUE value means that there is no sense to spill the allocno
+     during coloring because the spill will result in additional
+     reloads in reload pass.  */
+  unsigned int bad_spill_p : 1;
+  /* TRUE if a hard register or memory has been assigned to the
+     allocno.  */
+  unsigned int assigned_p : 1;
+  /* TRUE if conflicts for given allocno are represented by vector of
+     pointers to the conflicting allocnos.  Otherwise, we use a bit
+     vector where a bit with given index represents allocno with the
+     same number.  */
+  unsigned int conflict_vec_p : 1;
   /* Hard register assigned to given allocno.  Negative value means
      that memory was allocated to the allocno.  During the reload,
      spilled allocno has value equal to the corresponding stack slot
      number (0, ...) - 2.  Value -1 is used for allocnos spilled by the
      reload (at this point pseudo-register has only one allocno) which
      did not get stack slot yet.  */
-  int hard_regno;
-  /* Final rtx representation of the allocno.  */
-  rtx reg;
+  short int hard_regno;
   /* Allocnos with the same regno are linked by the following member.
      Allocnos corresponding to inner loops are first in the list (it
      corresponds to depth-first traverse of the loops).  */
@@ -314,9 +287,6 @@ struct ira_allocno
   int nrefs;
   /* Accumulated frequency of usage of the allocno.  */
   int freq;
-  /* Register class which should be used for allocation for given
-     allocno.  NO_REGS means that we should use memory.  */
-  enum reg_class aclass;
   /* Minimal accumulated and updated costs of usage register of the
      allocno class.  */
   int class_cost, updated_class_cost;
@@ -344,11 +314,6 @@ struct ira_allocno
   /* It is a link to allocno (cap) on lower loop level represented by
      given cap.  Null if given allocno is not a cap.  */
   ira_allocno_t cap_member;
-  /* Coalesced allocnos form a cyclic list.  One allocno given by
-     FIRST_COALESCED_ALLOCNO represents all coalesced allocnos.  The
-     list is chained by NEXT_COALESCED_ALLOCNO.  */
-  ira_allocno_t first_coalesced_allocno;
-  ira_allocno_t next_coalesced_allocno;
   /* Pointer to structures describing at what program point the
      allocno lives.  We always maintain the list in such way that *the
      ranges in the list are not intersected and ordered by decreasing
@@ -381,53 +346,6 @@ struct ira_allocno
   int call_freq;
   /* Accumulated number of the intersected calls.  */
   int calls_crossed_num;
-  /* TRUE if the allocno assigned to memory was a destination of
-     removed move (see ira-emit.c) at loop exit because the value of
-     the corresponding pseudo-register is not changed inside the
-     loop.  */
-  unsigned int mem_optimized_dest_p : 1;
-  /* TRUE if the corresponding pseudo-register has disjoint live
-     ranges and the other allocnos of the pseudo-register except this
-     one changed REG.  */
-  unsigned int somewhere_renamed_p : 1;
-  /* TRUE if allocno with the same REGNO in a subregion has been
-     renamed, in other words, got a new pseudo-register.  */
-  unsigned int child_renamed_p : 1;
-  /* During the reload, value TRUE means that we should not reassign a
-     hard register to the allocno got memory earlier.  It is set up
-     when we removed memory-memory move insn before each iteration of
-     the reload.  */
-  unsigned int dont_reassign_p : 1;
-#ifdef STACK_REGS
-  /* Set to TRUE if allocno can't be assigned to the stack hard
-     register correspondingly in this region and area including the
-     region and all its subregions recursively.  */
-  unsigned int no_stack_reg_p : 1, total_no_stack_reg_p : 1;
-#endif
-  /* TRUE value means that there is no sense to spill the allocno
-     during coloring because the spill will result in additional
-     reloads in reload pass.  */
-  unsigned int bad_spill_p : 1;
-  /* TRUE value means that the allocno was not removed yet from the
-     conflicting graph during colouring.  */
-  unsigned int in_graph_p : 1;
-  /* TRUE if a hard register or memory has been assigned to the
-     allocno.  */
-  unsigned int assigned_p : 1;
-  /* TRUE if it is put on the stack to make other allocnos
-     colorable.  */
-  unsigned int may_be_spilled_p : 1;
-  /* TRUE if conflicts for given allocno are represented by vector of
-     pointers to the conflicting allocnos.  Otherwise, we use a bit
-     vector where a bit with given index represents allocno with the
-     same number.  */
-  unsigned int conflict_vec_p : 1;
-  /* TRUE if the allocno is trivially colorable.  */
-  unsigned int colorable_p : 1;
-  /* Non NULL if we remove restoring value from given allocno to
-     MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
-     allocno value is not changed inside the loop.  */
-  ira_allocno_t mem_optimized_dest;
   /* Array of usage costs (accumulated and the one updated during
      coloring) for each hard register of the allocno class.  The
      member value can be NULL if all costs are the same and equal to
@@ -450,32 +368,12 @@ struct ira_allocno
      of other allocnos not assigned yet during assigning to given
      allocno.  */
   int *conflict_hard_reg_costs, *updated_conflict_hard_reg_costs;
-  /* Number of hard registers of the allocno class really
-     available for the allocno allocation.  It is number of the
-     profitable hard regs.  */
-  int available_regs_num;
-  /* Allocnos in a bucket (used in coloring) chained by the following
-     two members.  */
-  ira_allocno_t next_bucket_allocno;
-  ira_allocno_t prev_bucket_allocno;
-  /* Used for temporary purposes.  */
-  int temp;
-  /* Profitable hard regs available for this pseudo allocation.  It
-     means that the set excludes unavailable hard regs and hard regs
-     conflicting with given pseudo.  They should be of the allocno
-     class.  */
-  HARD_REG_SET profitable_hard_regs;
-  /* The allocno hard registers node.  */
-  allocno_hard_regs_node_t hard_regs_node;
-  /* Array of structures allocno_hard_regs_subnode representing
-     given allocno hard registers node (the 1st element in the array)
-     and all its subnodes in the tree (forest) of allocno hard
-     register nodes (see comments above).  */
-  int hard_regs_subnodes_start;
-  /* The length of the previous array. */
-  int hard_regs_subnodes_num;
+  /* Different additional data.  It is used to decrease size of
+     allocno data footprint.  */
+  void *add_data;
 };
 
+
 /* All members of the allocno structures should be accessed only
    through the following macros.  */
 #define ALLOCNO_NUM(A) ((A)->num)
@@ -507,11 +405,8 @@ struct ira_allocno
 #define ALLOCNO_TOTAL_NO_STACK_REG_P(A) ((A)->total_no_stack_reg_p)
 #endif
 #define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
-#define ALLOCNO_IN_GRAPH_P(A) ((A)->in_graph_p)
 #define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
-#define ALLOCNO_MAY_BE_SPILLED_P(A) ((A)->may_be_spilled_p)
 #define ALLOCNO_CONFLICT_VEC_P(A) ((A)->conflict_vec_p)
-#define ALLOCNO_COLORABLE_P(A) ((A)->colorable_p)
 #define ALLOCNO_MODE(A) ((A)->mode)
 #define ALLOCNO_COPIES(A) ((A)->allocno_copies)
 #define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
@@ -525,21 +420,45 @@ struct ira_allocno
 #define ALLOCNO_UPDATED_CLASS_COST(A) ((A)->updated_class_cost)
 #define ALLOCNO_MEMORY_COST(A) ((A)->memory_cost)
 #define ALLOCNO_UPDATED_MEMORY_COST(A) ((A)->updated_memory_cost)
-#define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) ((A)->excess_pressure_points_num)
-#define ALLOCNO_AVAILABLE_REGS_NUM(A) ((A)->available_regs_num)
-#define ALLOCNO_NEXT_BUCKET_ALLOCNO(A) ((A)->next_bucket_allocno)
-#define ALLOCNO_PREV_BUCKET_ALLOCNO(A) ((A)->prev_bucket_allocno)
-#define ALLOCNO_TEMP(A) ((A)->temp)
-#define ALLOCNO_FIRST_COALESCED_ALLOCNO(A) ((A)->first_coalesced_allocno)
-#define ALLOCNO_NEXT_COALESCED_ALLOCNO(A) ((A)->next_coalesced_allocno)
+#define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) \
+  ((A)->excess_pressure_points_num)
 #define ALLOCNO_LIVE_RANGES(A) ((A)->live_ranges)
 #define ALLOCNO_MIN(A) ((A)->min)
 #define ALLOCNO_MAX(A) ((A)->max)
 #define ALLOCNO_CONFLICT_ID(A) ((A)->conflict_id)
-#define ALLOCNO_PROFITABLE_HARD_REGS(A) ((A)->profitable_hard_regs)
-#define ALLOCNO_HARD_REGS_NODE(A) ((A)->hard_regs_node)
-#define ALLOCNO_HARD_REGS_SUBNODES_START(A) ((A)->hard_regs_subnodes_start)
-#define ALLOCNO_HARD_REGS_SUBNODES_NUM(A) ((A)->hard_regs_subnodes_num)
+#define ALLOCNO_ADD_DATA(A) ((A)->add_data)
+
+/* Typedef for pointer to the subsequent structure.  */
+typedef struct ira_emit_data *ira_emit_data_t;
+
+/* Allocno bound data used for emit pseudo live range split insns and
+   to flattening IR.  */
+struct ira_emit_data
+{
+  /* TRUE if the allocno assigned to memory was a destination of
+     removed move (see ira-emit.c) at loop exit because the value of
+     the corresponding pseudo-register is not changed inside the
+     loop.  */
+  unsigned int mem_optimized_dest_p : 1;
+  /* TRUE if the corresponding pseudo-register has disjoint live
+     ranges and the other allocnos of the pseudo-register except this
+     one changed REG.  */
+  unsigned int somewhere_renamed_p : 1;
+  /* TRUE if allocno with the same REGNO in a subregion has been
+     renamed, in other words, got a new pseudo-register.  */
+  unsigned int child_renamed_p : 1;
+  /* Final rtx representation of the allocno.  */
+  rtx reg;
+  /* Non NULL if we remove restoring value from given allocno to
+     MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
+     allocno value is not changed inside the loop.  */
+  ira_allocno_t mem_optimized_dest;
+};
+
+#define ALLOCNO_EMIT_DATA(a) ((ira_emit_data_t) ALLOCNO_ADD_DATA (a))
+
+/* Data used to emit live range split insns and to flattening IR.  */
+extern ira_emit_data_t ira_allocno_emit_data;
 
 /* Map regno -> allocnos with given regno (see comments for
    allocno member `next_regno_allocno').  */
@@ -781,23 +700,22 @@ minmax_set_iter_next (minmax_set_iterato
 extern HARD_REG_SET ira_reg_mode_hard_regset
                     [FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
 
-/* Array based on TARGET_REGISTER_MOVE_COST.  Don't use
-   ira_register_move_cost directly.  Use function of
-   ira_get_may_move_cost instead.  */
+/* Array based on TARGET_REGISTER_MOVE_COST.  The element is
+   initialized by ira_init_register_move_cost_if_necessary.  */
 extern move_table *ira_register_move_cost[MAX_MACHINE_MODE];
 
 /* Similar to may_move_in_cost but it is calculated in IRA instead of
    regclass.  Another difference we take only available hard registers
    into account to figure out that one register class is a subset of
-   the another one.  Don't use it directly.  Use function of
-   ira_get_may_move_cost instead.  */
+   the another one.  The element is initialized by
+   ira_init_register_move_cost_if_necessary.  */
 extern move_table *ira_may_move_in_cost[MAX_MACHINE_MODE];
 
 /* Similar to may_move_out_cost but it is calculated in IRA instead of
    regclass.  Another difference we take only available hard registers
    into account to figure out that one register class is a subset of
-   the another one.  Don't use it directly.  Use function of
-   ira_get_may_move_cost instead.  */
+   the another one.  The element is initialized by
+   ira_init_register_move_cost_if_necessary.  */
 extern move_table *ira_may_move_out_cost[MAX_MACHINE_MODE];
 
 /* Register class subset relation: TRUE if the first class is a subset
@@ -876,7 +794,6 @@ extern enum reg_class ira_reg_class_subu
 extern enum reg_class ira_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
 
 extern void *ira_allocate (size_t);
-extern void *ira_reallocate (void *, size_t);
 extern void ira_free (void *addr);
 extern bitmap ira_allocate_bitmap (void);
 extern void ira_free_bitmap (bitmap);
@@ -930,7 +847,6 @@ extern ira_copy_t ira_create_copy (ira_a
 				   int, bool, rtx, ira_loop_tree_node_t);
 extern void ira_add_allocno_copy_to_list (ira_copy_t);
 extern void ira_swap_allocno_copy_ends_if_necessary (ira_copy_t);
-extern void ira_remove_allocno_copy_from_list (ira_copy_t);
 extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int,
 					bool, rtx, ira_loop_tree_node_t);
 
@@ -972,34 +888,18 @@ extern void ira_finish_assign (void);
 extern void ira_color (void);
 
 /* ira-emit.c */
+extern void ira_initiate_emit_data (void);
+extern void ira_finish_emit_data (void);
 extern void ira_emit (bool);
 
 
 
-/* Return cost of moving value of MODE from register of class FROM to
-   register of class TO.  */
-static inline int
-ira_get_register_move_cost (enum machine_mode mode,
-			    enum reg_class from, enum reg_class to)
-{
-  if (ira_register_move_cost[mode] == NULL)
-    ira_init_register_move_cost (mode);
-  return ira_register_move_cost[mode][from][to];
-}
-
-/* Return cost of moving value of MODE from register of class FROM to
-   register of class TO.  Return zero if IN_P is true and FROM is
-   subset of TO or if IN_P is false and FROM is superset of TO.  */
-static inline int
-ira_get_may_move_cost (enum machine_mode mode,
-		       enum reg_class from, enum reg_class to,
-		       bool in_p)
+/* Initialize register costs for MODE if necessary.  */
+static inline void
+ira_init_register_move_cost_if_necessary (enum machine_mode mode)
 {
   if (ira_register_move_cost[mode] == NULL)
     ira_init_register_move_cost (mode);
-  return (in_p
-	  ? ira_may_move_in_cost[mode][from][to]
-	  : ira_may_move_out_cost[mode][from][to]);
 }
 
 
@@ -1150,7 +1050,7 @@ ira_allocno_conflict_iter_cond (ira_allo
 
   if (i->allocno_conflict_vec_p)
     {
-      conflict_allocno = ((ira_allocno_t *) i->vec)[i->word_num];
+      conflict_allocno = ((ira_allocno_t *) i->vec)[i->word_num++];
       if (conflict_allocno == NULL)
 	return false;
       *a = conflict_allocno;
@@ -1158,8 +1058,11 @@ ira_allocno_conflict_iter_cond (ira_allo
     }
   else
     {
+      unsigned IRA_INT_TYPE word = i->word;
+      unsigned int bit_num = i->bit_num;
+
       /* Skip words that are zeros.  */
-      for (; i->word == 0; i->word = ((IRA_INT_TYPE *) i->vec)[i->word_num])
+      for (; word == 0; word = ((IRA_INT_TYPE *) i->vec)[i->word_num])
 	{
 	  i->word_num++;
 
@@ -1167,40 +1070,28 @@ ira_allocno_conflict_iter_cond (ira_allo
 	  if (i->word_num * sizeof (IRA_INT_TYPE) >= i->size)
 	    return false;
 
-	  i->bit_num = i->word_num * IRA_INT_BITS;
+	  bit_num = i->word_num * IRA_INT_BITS;
 	}
 
       /* Skip bits that are zero.  */
-      for (; (i->word & 1) == 0; i->word >>= 1)
-	i->bit_num++;
+      for (; (word & 1) == 0; word >>= 1)
+	bit_num++;
 
-      *a = ira_conflict_id_allocno_map[i->bit_num + i->base_conflict_id];
+      *a = ira_conflict_id_allocno_map[bit_num + i->base_conflict_id];
+      i->bit_num = bit_num + 1;
+      i->word = word >> 1;
 
       return true;
     }
 }
 
-/* Advance to the next conflicting allocno.  */
-static inline void
-ira_allocno_conflict_iter_next (ira_allocno_conflict_iterator *i)
-{
-  if (i->allocno_conflict_vec_p)
-    i->word_num++;
-  else
-    {
-      i->word >>= 1;
-      i->bit_num++;
-    }
-}
-
 /* Loop over all allocnos conflicting with ALLOCNO.  In each
    iteration, A is set to the next conflicting allocno.  ITER is an
    instance of ira_allocno_conflict_iterator used to iterate the
    conflicts.  */
 #define FOR_EACH_ALLOCNO_CONFLICT(ALLOCNO, A, ITER)			\
   for (ira_allocno_conflict_iter_init (&(ITER), (ALLOCNO));		\
-       ira_allocno_conflict_iter_cond (&(ITER), &(A));			\
-       ira_allocno_conflict_iter_next (&(ITER)))
+       ira_allocno_conflict_iter_cond (&(ITER), &(A));)
 
 
 
@@ -1270,8 +1161,8 @@ ira_allocate_and_set_costs (int **vec, e
     reg_costs[i] = val;
 }
 
-/* Allocate cost vector *VEC for hard registers of ACLASS and
-   copy values of vector SRC into the vector if it is necessary */
+/* Allocate cost vector *VEC for hard registers of ACLASS and copy
+   values of vector SRC into the vector if it is necessary */
 static inline void
 ira_allocate_and_copy_costs (int **vec, enum reg_class aclass, int *src)
 {
@@ -1284,11 +1175,10 @@ ira_allocate_and_copy_costs (int **vec, 
   memcpy (*vec, src, sizeof (int) * len);
 }
 
-/* Allocate cost vector *VEC for hard registers of ACLASS and
-   add values of vector SRC into the vector if it is necessary */
+/* Allocate cost vector *VEC for hard registers of ACLASS and add
+   values of vector SRC into the vector if it is necessary */
 static inline void
-ira_allocate_and_accumulate_costs (int **vec, enum reg_class aclass,
-				   int *src)
+ira_allocate_and_accumulate_costs (int **vec, enum reg_class aclass, int *src)
 {
   int i, len;
 
@@ -1304,9 +1194,9 @@ ira_allocate_and_accumulate_costs (int *
     (*vec)[i] += src[i];
 }
 
-/* Allocate cost vector *VEC for hard registers of ACLASS and
-   copy values of vector SRC into the vector or initialize it by VAL
-   (if SRC is null).  */
+/* Allocate cost vector *VEC for hard registers of ACLASS and copy
+   values of vector SRC into the vector or initialize it by VAL (if
+   SRC is null).  */
 static inline void
 ira_allocate_and_set_or_copy_costs (int **vec, enum reg_class aclass,
 				    int val, int *src)
--- ./ira-lives.c	2010-07-06 12:32:04.000000000 -0400
+++ /home/cygnus/vmakarov/build1/ira-improv/gcc/gcc/ira-lives.c	2010-07-01 13:45:14.000000000 -0400
@@ -833,11 +833,11 @@ process_single_reg_class_operands (bool 
 	      && reg_class_size[cl] <= (unsigned) CLASS_MAX_NREGS (cl, mode))
 	    {
 	      int i, size;
-	      cost
-		= (freq
-		   * (in_p
-		      ? ira_get_register_move_cost (mode, aclass, cl)
-		      : ira_get_register_move_cost (mode, cl, aclass)));
+
+	      ira_init_register_move_cost_if_necessary (mode);
+	      cost = freq * (in_p
+			     ? ira_register_move_cost[mode][aclass][cl]
+			     : ira_register_move_cost[mode][cl][aclass]);
 	      ira_allocate_and_set_costs
 		(&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), aclass, 0);
 	      size = ira_reg_class_max_nregs[aclass][mode];

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]