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]

RFA: patch adding priority coloring for m32c and other ports


 Trying to port IRA to m32c, I realized that for some very specific
architectures a division of register classes on set of non-intersected
clases is a severe requirement (of Chaitin-Briggs graph coloring
algorithm).  Although it is possible to achieve generation of correct
code with many small non-intersected register classes as in m32c case,
it is not worth of it because a lot of pseudos get memory and some
hard registers are not used.  In other words, the RA quality is bad.

 So I've decided to add Chow's priority coloring to IRA because it
can work on any pseudo register classes (intersected or not).  The
following patch implements it.  It modifies code assuming
non-intersected register classes.  It is mainly in conflict building,
register pressure calculation, and cost calculations.  The Chow's
priority coloring itself is implemented on the base of IRA
infrastructure and takes only 50 lines of C code (see function
ira-color.c::color_allocnos).

 The patch also modifies semantics of -fira-algorithm and defines a
new option -fira-region.  The first flag has a two values: CB meaning
Chaitin-Briggs coloring and priority meaning Chow's priority coloring.
The second flag defines RA regions:

o one meaning one RA region, in order words, a whole function as a region;
o all meaning that all loops form RA regions;
o mixed meaning that only loops with high register pressure from RA regions.


I think such options are more logical.  If a port has a defined
IRA_COVER_CLASSES macro, the default algorithm is CB, otherwise the
default (and single possible algorithm is Chow's priority coloring).
By default RA regions are only loops with high register pressure
independently from the algorithm.

And finally, the patch has two parts specific for m32c.  One is a fix
of a typo in REG_ALLOC_ORDER.  And another one is to prohibit usage of
callee-saved likely spilled base registers for allocnos crossing
calls.  M32c has 2 registers of class A_REGS which are used for
addressing.  If a code for save/restore of such register is generated,
reload pass dies because we need one A_REG for addressing in
save/restore code for saving A_REG register, and one A_REG register
can be used explicitly in a call.

 Theoretically, the patch should make working targets which were not
ported to IRA (which did not have defined macro IRA_COVER_CLASS).  But
I checked only m32c.  M32c has no additional regressions on gcc
testsuite with comparison of the old RA.  The patch was also
successfully bootstrapped on x86, x86_64, itanium, and ppc64 with and
without BOOT_CFLAGS='-O2 -g -fira-algorithm=priority'.  The patch
should not change the code generated earlier by IRA by default.  I've
checked that on variety of tests on x86 and x86_64.

Is it ok to commit?

2008-11-28 Vladimir Makarov <vmakarov@redhat.com>

* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.

   * doc/invoke.texi (-fira-region): Describe new option.
   (-fira-algorithm): Change the values.

   * ira-conflicts.c (build_conflict_bit_table,
   build_allocno_conflicts): Use ira_reg_classes_intersect_p.
   (ira_build_conflicts): Use flag flag_ira_region instead of
   flag_ira_algorithm.  Prohibit usage of callee-saved likely spilled
   base registers for allocnos crossing calls.

   * flags.h (enum ira_algorithm): Redefine.
   (enum ira_region): New.
   (flag_ira_region): New.

   * cfgloopanal.c (estimate_reg_pressure_cost): Use flag_ira_region
   instead of flag_ira_algorithm.

   * toplev.c (flag_ira_algorithm): Change the initial value.
   (flag_ira_region): New.

   * ira-int.h (ira_reg_classes_intersect_p,
   ira_reg_class_super_classes): New.

   * ira-color.c (update_copy_costs): Use
   ira_reg_classes_intersect_p.  Use right class to find hard reg
   index.
   (update_conflict_hard_regno_costs): Ditto.  Add a new parameter.
   (assign_hard_reg): Ditto.  Pass additional argument to
   update_conflict_hard_regno_costs.  Do not uncoalesce for priority
   coloring.
   (allocno_priorities, setup_allocno_priorities,
   allocno_priority_compare_func): Move before color_allocnos.
   (color_allocnos): Add priority coloring.  Use flag flag_ira_region
   instead of flag_ira_algorithm.
   (move_spill_restore): Check classes of the same reg allocno from
   different regions.
   (update_curr_costs): Use ira_reg_classes_intersect_p.
   (ira_reassign_conflict_allocnos): Ditto.

   * opts.c (decode_options): Always set up flag_ira.  Set up
   flag_ira_algorithm.  Warn CB can not be used for architecture.
   (common_handle_option): Modify code for -fira-algorithm.  Add code
   to process -fira-region.

   * ira-lives.c (update_allocno_pressure_excess_length): Process
   superclasses too.
   (set_allocno_live, clear_allocno_live, mark_reg_live,
   mark_reg_dead, process_bb_node_lives): Ditto.

   * ira-build.c (propagate_allocno_info): Use flag flag_ira_region
   instead of flag_ira_algorithm.
   (allocno_range_compare_func): Ignore classes for priority
   coloring.
   (setup_min_max_conflict_allocno_ids): Ditto.
   (ira_flattening): Use ira_reg_classes_intersect_p.

* genpreds.c (write_enum_constraint_num): Output
CONSTRAINT__LIMIT.
* common.opt (fira-algorithm): Modify.
(fira-region): New.


   * ira.c (setup_class_hard_regs): Initialize.
   (setup_cover_and_important_classes): Modify code setting class
   related info for priority coloring.
   (setup_class_translate): Ditto.
   (ira_reg_classes_intersect_p, ira_reg_class_super_classes): New.
   (setup_reg_class_intersect_union): Rename to
   setup_reg_class_relations.  Add code for setting up new variables.
   (find_reg_class_closure): Do not check targetm.ira_cover_classes.
   (ira): Use flag flag_ira_region instead of flag_ira_algorithm.

* ira-costs.c (common_classes): New.
(print_costs): Use flag flag_ira_region instead of
flag_ira_algorithm.
(find_allocno_class_costs): Ditto. Use common_classes. Translate
alt_class.
(ira_costs): Allocate/deallocate common_classes.
* config/m32c/m32.h (REG_ALLOC_ORDER): Add reg 19.


Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 142255)
+++ doc/tm.texi	(working copy)
@@ -2841,7 +2841,8 @@ options have been processed. It is then 
 The default implementation returns @code{IRA_COVER_CLASSES}, if defined,
 otherwise there is no default implementation.  You must define either this
 macro or @code{IRA_COVER_CLASSES} in order to use the integrated register
-allocator for the target.
+allocator with Chaitin-Briggs coloring. If the macro is not defined,
+the only available coloring algorithm is Chow's priority coloring.
 @end deftypefn
 
 @defmac IRA_COVER_CLASSES
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 142255)
+++ doc/invoke.texi	(working copy)
@@ -338,7 +338,7 @@ Objective-C and Objective-C++ Dialects}.
 -finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol 
 -fipa-pure-const -fipa-reference -fipa-struct-reorg @gol
 -fipa-type-escape -fira -fira-algorithm=@var{algorithm} @gol
--fira-coalesce -fno-ira-share-save-slots @gol
+-fira-region=@var{region} -fira-coalesce -fno-ira-share-save-slots @gol
 -fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
 -fivopts -fkeep-inline-functions -fkeep-static-consts @gol
 -floop-block -floop-interchange -floop-strip-mine @gol
@@ -5728,17 +5728,25 @@ allocation.  It is a default if @acronym
 target.
 
 @item -fira-algorithm=@var{algorithm}
-Use specified algorithm for the integrated register allocator.  The
-@var{algorithm} argument should be one of @code{regional}, @code{CB},
-or @code{mixed}.  The second algorithm specifies Chaitin-Briggs
-coloring, the first one specifies regional coloring based on
-Chaitin-Briggs coloring, and the third one which is the default
-specifies a mix of Chaitin-Briggs and regional algorithms where loops
-with small register pressure are ignored.  The first algorithm can
-give best result for machines with small size and irregular register
-set, the second one is faster and generates decent code and the
-smallest size code, and the mixed algorithm usually give the best
-results in most cases and for most architectures.
+Use specified coloring algorithm for the integrated register
+allocator.  The @var{algorithm} argument should be @code{priority} or
+@code{CB}.  The first algorithm specifies Chow's priority coloring,
+the second one specifies Chaitin-Briggs coloring.  The second
+algorithm can be unimplemented for some architectures.  If it is
+implemented, it is the default because Chaitin-Briggs coloring as a
+rule generates a better code.
+
+@item -fira-region=@var{region}
+Use specified regions for the integrated register allocator.  The
+@var{region} argument should be one of @code{all}, @code{mixed}, or
+@code{one}.  The first value means using all loops as register
+allocation regions, the second value which is the default means using
+all loops except for loops with small register pressure as the
+regions, and third one means using all function as a single region.
+The first value can give best result for machines with small size and
+irregular register set, the third one results in faster and generates
+decent code and the smallest size code, and the default value usually
+give the best results in most cases and for most architectures.
 
 @item -fira-coalesce
 @opindex fira-coalesce
Index: ira-conflicts.c
===================================================================
--- ira-conflicts.c	(revision 142255)
+++ ira-conflicts.c	(working copy)
@@ -114,7 +114,8 @@ build_conflict_bit_table (void)
 	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
 	    {
 	      live_a = ira_allocnos[j];
-	      if (cover_class == ALLOCNO_COVER_CLASS (live_a)
+	      if (ira_reg_classes_intersect_p
+		  [cover_class][ALLOCNO_COVER_CLASS (live_a)]
 		  /* Don't set up conflict for the allocno with itself.  */
 		  && num != (int) j)
 		{
@@ -555,8 +556,8 @@ build_allocno_conflicts (ira_allocno_t a
 			   ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi)
     {
       another_a = ira_conflict_id_allocno_map[i];
-      ira_assert (ALLOCNO_COVER_CLASS (a)
-		  == ALLOCNO_COVER_CLASS (another_a));
+      ira_assert (ira_reg_classes_intersect_p
+		  [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
       collected_conflict_allocnos[px++] = another_a;
     }
   if (ira_conflict_vector_profitable_p (a, px))
@@ -592,8 +593,8 @@ build_allocno_conflicts (ira_allocno_t a
 			   ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi)
     {
       another_a = ira_conflict_id_allocno_map[i];
-      ira_assert (ALLOCNO_COVER_CLASS (a)
-		  == ALLOCNO_COVER_CLASS (another_a));
+      ira_assert (ira_reg_classes_intersect_p
+		  [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
       if ((another_parent_a = ALLOCNO_CAP (another_a)) == NULL
 	  && (another_parent_a = (parent->regno_allocno_map
 				  [ALLOCNO_REGNO (another_a)])) == NULL)
@@ -740,6 +741,7 @@ ira_build_conflicts (void)
 {
   ira_allocno_t a;
   ira_allocno_iterator ai;
+  HARD_REG_SET temp_hard_reg_set;
 
   if (optimize)
     {
@@ -747,8 +749,8 @@ ira_build_conflicts (void)
       build_conflicts ();
       ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
       /* We need finished conflict table for the subsequent call.  */
-      if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-	  || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
+      if (flag_ira_region == IRA_REGION_ALL
+	  || flag_ira_region == IRA_REGION_MIXED)
 	propagate_copies ();
       /* Now we can free memory for the conflict table (see function
 	 build_allocno_conflicts for details).  */
@@ -759,6 +761,14 @@ ira_build_conflicts (void)
 	}
       ira_free (conflicts);
     }
+  if (! CLASS_LIKELY_SPILLED_P (BASE_REG_CLASS))
+    CLEAR_HARD_REG_SET (temp_hard_reg_set);
+  else
+    {
+      COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[BASE_REG_CLASS]);
+      AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
+      AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
+    }
   FOR_EACH_ALLOCNO (a, ai)
     {
       if (ALLOCNO_CALLS_CROSSED_NUM (a) == 0)
@@ -775,6 +785,8 @@ ira_build_conflicts (void)
 	{
 	  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
 			    no_caller_save_reg_set);
+	  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+			    temp_hard_reg_set);
 	  if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
 	    IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
 			      no_caller_save_reg_set);
Index: flags.h
===================================================================
--- flags.h	(revision 142255)
+++ flags.h	(working copy)
@@ -209,13 +209,22 @@ extern int flag_dump_rtl_in_asm;
 /* The algorithm used for the integrated register allocator (IRA).  */
 enum ira_algorithm
 {
-  IRA_ALGORITHM_REGIONAL,
   IRA_ALGORITHM_CB,
-  IRA_ALGORITHM_MIXED
+  IRA_ALGORITHM_PRIORITY
 };
 
 extern enum ira_algorithm flag_ira_algorithm;
 
+/* The regions used for the integrated register allocator (IRA).  */
+enum ira_region
+{
+  IRA_REGION_ONE,
+  IRA_REGION_ALL,
+  IRA_REGION_MIXED
+};
+
+extern enum ira_region flag_ira_region;
+
 extern unsigned int flag_ira_verbose;
 
 
Index: cfgloopanal.c
===================================================================
--- cfgloopanal.c	(revision 142255)
+++ cfgloopanal.c	(working copy)
@@ -396,8 +396,8 @@ estimate_reg_pressure_cost (unsigned n_n
        one.  */
     cost = target_spill_cost [speed] * n_new;
 
-  if (optimize && flag_ira && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-			       || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
+  if (optimize && flag_ira && (flag_ira_region == IRA_REGION_ALL
+			       || flag_ira_region == IRA_REGION_MIXED)
       && number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM)
     /* IRA regional allocation deals with high register pressure
        better.  So decrease the cost (to do more accurate the cost
Index: toplev.c
===================================================================
--- toplev.c	(revision 142255)
+++ toplev.c	(working copy)
@@ -271,9 +271,11 @@ int flag_next_runtime = 0;
 
 enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
 
-/* Set the default algorithm for the integrated register allocator.  */
+/* Set the default region and algorithm for the integrated register
+   allocator.  */
 
-enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_MIXED;
+enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_CB;
+enum ira_region flag_ira_region = IRA_REGION_MIXED;
 
 /* Set the default value for -fira-verbose.  */
 
Index: ira-int.h
===================================================================
--- ira-int.h	(revision 142255)
+++ ira-int.h	(working copy)
@@ -819,6 +819,16 @@ extern enum reg_class ira_class_translat
    taking all hard-registers including fixed ones into account.  */
 extern enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES];
 
+/* True if the two classes (that is calculated taking only hard
+   registers available for allocation into account) are
+   intersected.  */
+extern bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES];
+
+/* Classes with end marker LIM_REG_CLASSES which are intersected with
+   given class (the first index).  That includes given class itself.
+   This is calculated taking only hard registers available for
+   allocation into account.  */
+extern enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES];
 /* The biggest important class inside of union of the two classes
    (that is calculated taking only hard registers available for
    allocation into account).  If the both classes contain no hard
Index: ira-color.c
===================================================================
--- ira-color.c	(revision 142255)
+++ ira-color.c	(working copy)
@@ -279,7 +279,8 @@ update_copy_costs (ira_allocno_t allocno
 	  else
 	    gcc_unreachable ();
 
-	  if (cover_class != ALLOCNO_COVER_CLASS (another_allocno)
+	  cover_class = ALLOCNO_COVER_CLASS (another_allocno);
+	  if (! ira_reg_classes_intersect_p[rclass][cover_class]
 	      || ALLOCNO_ASSIGNED_P (another_allocno))
 	    continue;
 
@@ -301,6 +302,8 @@ update_copy_costs (ira_allocno_t allocno
 	    (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
 	     cover_class, 0,
 	     ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
+	  i = ira_class_hard_reg_index[cover_class][hard_regno];
+	  ira_assert (i >= 0);
 	  ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
 	  ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
 	    += update_cost;
@@ -311,17 +314,19 @@ update_copy_costs (ira_allocno_t allocno
   while (get_next_update_cost (&allocno, &divisor));
 }
 
-/* This function updates COSTS (decrease if DECR_P) by conflict costs
-   of the unassigned allocnos connected by copies with allocnos in
-   update_cost_queue.  This update increases chances to remove some
-   copies.  */
+/* This function updates COSTS (decrease if DECR_P) for hard_registers
+   of COVER_CLASS by conflict costs of the unassigned allocnos
+   connected by copies with allocnos in update_cost_queue.  This
+   update increases chances to remove some copies.  */
 static void
-update_conflict_hard_regno_costs (int *costs, bool decr_p)
+update_conflict_hard_regno_costs (int *costs, enum reg_class cover_class,
+				  bool decr_p)
 {
   int i, cost, class_size, freq, mult, div, divisor;
+  int index, hard_regno;
   int *conflict_costs;
   bool cont_p;
-  enum reg_class cover_class;
+  enum reg_class another_cover_class;
   ira_allocno_t allocno, another_allocno;
   ira_copy_t cp, next_cp;
 
@@ -340,16 +345,17 @@ update_conflict_hard_regno_costs (int *c
 	  }
 	else
 	  gcc_unreachable ();
-	cover_class = ALLOCNO_COVER_CLASS (allocno);
-	if (cover_class != ALLOCNO_COVER_CLASS (another_allocno)
+ 	another_cover_class = ALLOCNO_COVER_CLASS (another_allocno);
+ 	if (! ira_reg_classes_intersect_p[cover_class][another_cover_class]
 	    || ALLOCNO_ASSIGNED_P (another_allocno)
 	    || ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
 					 (another_allocno)))
 	  continue;
-	class_size = ira_class_hard_regs_num[cover_class];
+	class_size = ira_class_hard_regs_num[another_cover_class];
 	ira_allocate_and_copy_costs
 	  (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
-	   cover_class, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
+	   another_cover_class,
+	   ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
 	conflict_costs
 	  = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno);
 	if (conflict_costs == NULL)
@@ -364,13 +370,18 @@ update_conflict_hard_regno_costs (int *c
 	    cont_p = false;
 	    for (i = class_size - 1; i >= 0; i--)
 	      {
+		hard_regno = ira_class_hard_regs[another_cover_class][i];
+		ira_assert (hard_regno >= 0);
+		index = ira_class_hard_reg_index[cover_class][hard_regno];
+		if (index < 0)
+		  continue;
 		cost = conflict_costs [i] * mult / div;
 		if (cost == 0)
 		  continue;
 		cont_p = true;
 		if (decr_p)
 		  cost = -cost;
-		costs[i] += cost;
+		costs[index] += cost;
 	      }
 	  }
 	/* Probably 5 hops will be enough.  */
@@ -429,11 +440,11 @@ static bool
 assign_hard_reg (ira_allocno_t allocno, bool retry_p)
 {
   HARD_REG_SET conflicting_regs;
-  int i, j, hard_regno, best_hard_regno, class_size;
+  int i, j, k, hard_regno, best_hard_regno, class_size;
   int cost, mem_cost, min_cost, full_cost, min_full_cost, add_cost;
   int *a_costs;
   int *conflict_costs;
-  enum reg_class cover_class, rclass;
+  enum reg_class cover_class, rclass, conflict_cover_class;
   enum machine_mode mode;
   ira_allocno_t a, conflict_allocno;
   ira_allocno_conflict_iterator aci;
@@ -490,7 +501,9 @@ assign_hard_reg (ira_allocno_t allocno, 
 	if (retry_p || bitmap_bit_p (consideration_allocno_bitmap,
 				     ALLOCNO_NUM (conflict_allocno)))
 	  {
-	    ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_allocno));
+	    conflict_cover_class = ALLOCNO_COVER_CLASS (conflict_allocno);
+	    ira_assert (ira_reg_classes_intersect_p
+			[cover_class][conflict_cover_class]);
 	    if (allocno_coalesced_p)
 	      {
 		if (bitmap_bit_p (processed_coalesced_allocno_bitmap,
@@ -501,7 +514,8 @@ assign_hard_reg (ira_allocno_t allocno, 
 	      }
 	    if (ALLOCNO_ASSIGNED_P (conflict_allocno))
 	      {
-		if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0)
+		if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0
+		    && ira_class_hard_reg_index[cover_class][hard_regno] >= 0)
 		  {
 		    IOR_HARD_REG_SET
 		      (conflicting_regs,
@@ -511,20 +525,27 @@ assign_hard_reg (ira_allocno_t allocno, 
 					       conflicting_regs))
 		      goto fail;
 		  }
-		continue;
 	      }
 	    else if (! ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
 						 (conflict_allocno)))
 	      {
 		ira_allocate_and_copy_costs
 		  (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno),
-		   cover_class,
+		   conflict_cover_class,
 		   ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_allocno));
 		conflict_costs
 		  = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno);
 		if (conflict_costs != NULL)
 		  for (j = class_size - 1; j >= 0; j--)
-		    full_costs[j] -= conflict_costs[j];
+ 		    {
+ 		      hard_regno = ira_class_hard_regs[cover_class][j];
+ 		      ira_assert (hard_regno >= 0);
+ 		      k = (ira_class_hard_reg_index
+ 			   [conflict_cover_class][hard_regno]);
+ 		      if (k < 0)
+ 			continue;
+ 		      full_costs[j] -= conflict_costs[k];
+ 		    }
 		queue_update_cost (conflict_allocno, COST_HOP_DIVISOR);
 	      }
 	  }
@@ -533,7 +554,7 @@ assign_hard_reg (ira_allocno_t allocno, 
     }
   /* Take into account preferences of allocnos connected by copies to
      the conflict allocnos.  */
-  update_conflict_hard_regno_costs (full_costs, true);
+  update_conflict_hard_regno_costs (full_costs, cover_class, true);
 
   /* Take preferences of allocnos connected by copies into
      account.  */
@@ -545,7 +566,7 @@ assign_hard_reg (ira_allocno_t allocno, 
       if (a == allocno)
 	break;
     }
-  update_conflict_hard_regno_costs (full_costs, false);
+  update_conflict_hard_regno_costs (full_costs, cover_class, false);
   min_cost = min_full_cost = INT_MAX;
   /* We don't care about giving callee saved registers to allocnos no
      living through calls because call clobbered registers are
@@ -594,7 +615,8 @@ assign_hard_reg (ira_allocno_t allocno, 
       best_hard_regno = -1;
     }
  fail:
-  if (best_hard_regno < 0
+  if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
+      && best_hard_regno < 0
       && ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno) != allocno)
     {
       for (j = 0, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
@@ -1605,6 +1627,10 @@ coalesce_allocnos (bool reload_p)
 	    {
 	      next_cp = cp->next_first_allocno_copy;
 	      regno = ALLOCNO_REGNO (cp->second);
+	      /* For priority coloring we coalesce allocnos only with
+		 the same cover class not with intersected cover
+		 classes as it were possible.  It is done for
+		 simplicity.  */
 	      if ((reload_p
 		   || (ALLOCNO_COVER_CLASS (cp->second) == cover_class
 		       && ALLOCNO_MODE (cp->second) == mode))
@@ -1659,12 +1685,72 @@ coalesce_allocnos (bool reload_p)
   ira_free (sorted_copies);
 }
 
+/* Map: allocno number -> allocno priority.  */
+static int *allocno_priorities;
+
+/* Set up priorities for N allocnos in array
+   CONSIDERATION_ALLOCNOS.  */
+static void
+setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
+{
+  int i, length, nrefs, priority, max_priority, mult;
+  ira_allocno_t a;
+
+  max_priority = 0;
+  for (i = 0; i < n; i++)
+    {
+      a = consideration_allocnos[i];
+      nrefs = ALLOCNO_NREFS (a);
+      ira_assert (nrefs >= 0);
+      mult = floor_log2 (ALLOCNO_NREFS (a)) + 1;
+      ira_assert (mult >= 0);
+      allocno_priorities[ALLOCNO_NUM (a)]
+	= priority
+	= (mult
+	   * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a))
+	   * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]);
+      if (priority < 0)
+	priority = -priority;
+      if (max_priority < priority)
+	max_priority = priority;
+    }
+  mult = max_priority == 0 ? 1 : INT_MAX / max_priority;
+  for (i = 0; i < n; i++)
+    {
+      a = consideration_allocnos[i];
+      length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
+      if (length <= 0)
+	length = 1;
+      allocno_priorities[ALLOCNO_NUM (a)]
+	= allocno_priorities[ALLOCNO_NUM (a)] * mult / length;
+    }
+}
+
+/* Sort allocnos according to their priorities which are calculated
+   analogous to ones in file `global.c'.  */
+static int
+allocno_priority_compare_func (const void *v1p, const void *v2p)
+{
+  ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
+  ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
+  int pri1, pri2;
+
+  pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
+  pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
+  if (pri2 - pri1)
+    return pri2 - pri1;
+
+  /* If regs are equally good, sort by allocnos, so that the results of
+     qsort leave nothing to chance.  */
+  return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
+}
+
 /* Chaitin-Briggs coloring for allocnos in COLORING_ALLOCNO_BITMAP
    taking into account allocnos in CONSIDERATION_ALLOCNO_BITMAP.  */
 static void
 color_allocnos (void)
 {
-  unsigned int i;
+  unsigned int i, n;
   bitmap_iterator bi;
   ira_allocno_t a;
 
@@ -1672,30 +1758,83 @@ color_allocnos (void)
   processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
   if (flag_ira_coalesce)
     coalesce_allocnos (false);
-  /* Put the allocnos into the corresponding buckets.  */
-  colorable_allocno_bucket = NULL;
-  uncolorable_allocno_bucket = NULL;
-  EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
-    {
-      a = ira_allocnos[i];
-      if (ALLOCNO_COVER_CLASS (a) == NO_REGS)
-	{
-	  ALLOCNO_HARD_REGNO (a) = -1;
-	  ALLOCNO_ASSIGNED_P (a) = true;
-	  ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
-	  ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
-	  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+  if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+    {
+      n = 0;
+      EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+	{
+	  a = ira_allocnos[i];
+	  if (ALLOCNO_COVER_CLASS (a) == NO_REGS)
 	    {
-	      fprintf (ira_dump_file, "      Spill");
-	      print_coalesced_allocno (a);
-	      fprintf (ira_dump_file, "\n");
+	      ALLOCNO_HARD_REGNO (a) = -1;
+	      ALLOCNO_ASSIGNED_P (a) = true;
+	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
+	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
+	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+		{
+		  fprintf (ira_dump_file, "      Spill");
+		  print_coalesced_allocno (a);
+		  fprintf (ira_dump_file, "\n");
+		}
+	      continue;
 	    }
-	  continue;
+	  sorted_allocnos[n++] = a;
 	}
-      put_allocno_into_bucket (a);
+      if (n != 0)
+	{
+	  setup_allocno_priorities (sorted_allocnos, n);
+	  qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
+		 allocno_priority_compare_func);
+	  for (i = 0; i < n; i++)
+	    {
+	      a = sorted_allocnos[i];
+	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+		{
+		  fprintf (ira_dump_file, "      ");
+		  print_coalesced_allocno (a);
+		  fprintf (ira_dump_file, "  -- ");
+		}
+	      if (assign_hard_reg (a, false))
+		{
+		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+		    fprintf (ira_dump_file, "assign hard reg %d\n",
+			     ALLOCNO_HARD_REGNO (a));
+		}
+	      else
+		{
+		  if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+		    fprintf (ira_dump_file, "assign memory\n");
+		}
+	    }
+	}
+    }
+  else
+    {
+      /* Put the allocnos into the corresponding buckets.  */
+      colorable_allocno_bucket = NULL;
+      uncolorable_allocno_bucket = NULL;
+      EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+	{
+	  a = ira_allocnos[i];
+	  if (ALLOCNO_COVER_CLASS (a) == NO_REGS)
+	    {
+	      ALLOCNO_HARD_REGNO (a) = -1;
+	      ALLOCNO_ASSIGNED_P (a) = true;
+	      ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
+	      ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL);
+	      if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+		{
+		  fprintf (ira_dump_file, "      Spill");
+		  print_coalesced_allocno (a);
+		  fprintf (ira_dump_file, "\n");
+		}
+	      continue;
+	    }
+	  put_allocno_into_bucket (a);
+	}
+      push_allocnos_to_stack ();
+      pop_allocnos_from_stack ();
     }
-  push_allocnos_to_stack ();
-  pop_allocnos_from_stack ();
   if (flag_ira_coalesce)
     /* We don't need coalesced allocnos for ira_reassign_pseudos.  */
     EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
@@ -1796,8 +1935,8 @@ color_pass (ira_loop_tree_node_t loop_tr
   /* Color all mentioned allocnos including transparent ones.  */
   color_allocnos ();
   /* Process caps.  They are processed just once.  */
-  if (flag_ira_algorithm == IRA_ALGORITHM_MIXED
-      || flag_ira_algorithm == IRA_ALGORITHM_REGIONAL)
+  if (flag_ira_region == IRA_REGION_MIXED
+      || flag_ira_region == IRA_REGION_ALL)
     EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi)
       {
 	a = ira_allocnos[j];
@@ -1806,9 +1945,9 @@ color_pass (ira_loop_tree_node_t loop_tr
 	/* Remove from processing in the next loop.  */
 	bitmap_clear_bit (consideration_allocno_bitmap, j);
 	rclass = ALLOCNO_COVER_CLASS (a);
-	if ((flag_ira_algorithm == IRA_ALGORITHM_MIXED
-	     && loop_tree_node->reg_pressure[rclass]
-	     <= ira_available_class_regs[rclass]))
+	if (flag_ira_region == IRA_REGION_MIXED
+	    && (loop_tree_node->reg_pressure[rclass]
+		<= ira_available_class_regs[rclass]))
 	  {
 	    mode = ALLOCNO_MODE (a);
 	    hard_regno = ALLOCNO_HARD_REGNO (a);
@@ -1843,6 +1982,7 @@ color_pass (ira_loop_tree_node_t loop_tr
 	  mode = ALLOCNO_MODE (a);
 	  rclass = ALLOCNO_COVER_CLASS (a);
 	  hard_regno = ALLOCNO_HARD_REGNO (a);
+	  /* Use hard register class here.  ??? */
 	  if (hard_regno >= 0)
 	    {
 	      index = ira_class_hard_reg_index[rclass][hard_regno];
@@ -1854,9 +1994,10 @@ color_pass (ira_loop_tree_node_t loop_tr
 	  if (subloop_allocno == NULL
 	      || ALLOCNO_CAP (subloop_allocno) != NULL)
 	    continue;
+	  ira_assert (ALLOCNO_COVER_CLASS (subloop_allocno) == rclass);
 	  ira_assert (bitmap_bit_p (subloop_node->all_allocnos,
 				    ALLOCNO_NUM (subloop_allocno)));
-	  if (flag_ira_algorithm == IRA_ALGORITHM_MIXED
+	  if ((flag_ira_region == IRA_REGION_MIXED)
 	      && (loop_tree_node->reg_pressure[rclass]
 		  <= ira_available_class_regs[rclass]))
 	    {
@@ -2002,6 +2143,7 @@ move_spill_restore (void)
 	      subloop_allocno = subloop_node->regno_allocno_map[regno];
 	      if (subloop_allocno == NULL)
 		continue;
+	      ira_assert (rclass == ALLOCNO_COVER_CLASS (subloop_allocno));
 	      /* We have accumulated cost.  To get the real cost of
 		 allocno usage in the loop we should subtract costs of
 		 the subloop allocnos.  */
@@ -2027,6 +2169,7 @@ move_spill_restore (void)
 	  if ((parent = loop_node->parent) != NULL
 	      && (parent_allocno = parent->regno_allocno_map[regno]) != NULL)
 	    {
+	      ira_assert (rclass == ALLOCNO_COVER_CLASS (parent_allocno));
 	      exit_freq	= ira_loop_edge_freq (loop_node, regno, true);
 	      enter_freq = ira_loop_edge_freq (loop_node, regno, false);
 	      if ((hard_regno2 = ALLOCNO_HARD_REGNO (parent_allocno)) < 0)
@@ -2094,13 +2237,15 @@ update_curr_costs (ira_allocno_t a)
 	}
       else
 	gcc_unreachable ();
-      if (cover_class != ALLOCNO_COVER_CLASS (another_a)
+      if (! ira_reg_classes_intersect_p[cover_class][ALLOCNO_COVER_CLASS
+						     (another_a)]
 	  || ! ALLOCNO_ASSIGNED_P (another_a)
 	  || (hard_regno = ALLOCNO_HARD_REGNO (another_a)) < 0)
 	continue;
       rclass = REGNO_REG_CLASS (hard_regno);
       i = ira_class_hard_reg_index[cover_class][hard_regno];
-      ira_assert (i >= 0);
+      if (i < 0)
+	continue;
       cost = (cp->first == a
 	      ? ira_register_move_cost[mode][rclass][cover_class]
 	      : ira_register_move_cost[mode][cover_class][rclass]);
@@ -2116,66 +2261,6 @@ update_curr_costs (ira_allocno_t a)
     }
 }
 
-/* Map: allocno number -> allocno priority.  */
-static int *allocno_priorities;
-
-/* Set up priorities for N allocnos in array
-   CONSIDERATION_ALLOCNOS.  */
-static void
-setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n)
-{
-  int i, length, nrefs, priority, max_priority, mult;
-  ira_allocno_t a;
-
-  max_priority = 0;
-  for (i = 0; i < n; i++)
-    {
-      a = consideration_allocnos[i];
-      nrefs = ALLOCNO_NREFS (a);
-      ira_assert (nrefs >= 0);
-      mult = floor_log2 (ALLOCNO_NREFS (a)) + 1;
-      ira_assert (mult >= 0);
-      allocno_priorities[ALLOCNO_NUM (a)]
-	= priority
-	= (mult
-	   * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a))
-	   * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]);
-      if (priority < 0)
-	priority = -priority;
-      if (max_priority < priority)
-	max_priority = priority;
-    }
-  mult = max_priority == 0 ? 1 : INT_MAX / max_priority;
-  for (i = 0; i < n; i++)
-    {
-      a = consideration_allocnos[i];
-      length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
-      if (length <= 0)
-	length = 1;
-      allocno_priorities[ALLOCNO_NUM (a)]
-	= allocno_priorities[ALLOCNO_NUM (a)] * mult / length;
-    }
-}
-
-/* Sort allocnos according to their priorities which are calculated
-   analogous to ones in file `global.c'.  */
-static int
-allocno_priority_compare_func (const void *v1p, const void *v2p)
-{
-  ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
-  ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
-  int pri1, pri2;
-
-  pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
-  pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
-  if (pri2 - pri1)
-    return pri2 - pri1;
-
-  /* If regs are equally good, sort by allocnos, so that the results of
-     qsort leave nothing to chance.  */
-  return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
-}
-
 /* Try to assign hard registers to the unassigned allocnos and
    allocnos conflicting with them or conflicting with allocnos whose
    regno >= START_REGNO.  The function is called after ira_flattening,
@@ -2215,7 +2300,8 @@ ira_reassign_conflict_allocnos (int star
 	continue;
       FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
 	{
-	  ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_a));
+	  ira_assert (ira_reg_classes_intersect_p
+		      [cover_class][ALLOCNO_COVER_CLASS (conflict_a)]);
 	  if (bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (conflict_a)))
 	    continue;
 	  bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (conflict_a));
Index: opts.c
===================================================================
--- opts.c	(revision 142255)
+++ opts.c	(working copy)
@@ -870,9 +870,11 @@ decode_options (unsigned int argc, const
 	}
     }
   
-  /* Use IRA if it is implemented for the target.  */
-  if (targetm.ira_cover_classes)
-    flag_ira = 1;
+  flag_ira = 1;
+  /* Use priority coloring if cover classes is not defined for the
+     target.  */
+  if (targetm.ira_cover_classes == NULL)
+    flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
 
   /* -O1 optimizations.  */
   opt1 = (optimize >= 1);
@@ -1096,10 +1098,12 @@ decode_options (unsigned int argc, const
   if (!flag_sel_sched_pipelining)
     flag_sel_sched_pipelining_outer_loops = 0;
 
-  if (flag_ira && !targetm.ira_cover_classes)
+  if (flag_ira && !targetm.ira_cover_classes
+      && flag_ira_algorithm == IRA_ALGORITHM_CB)
     {
-      inform (input_location, "-fira does not work on this architecture");
-      flag_ira = 0;
+      inform (input_location,
+	      "-fira-algorithm=CB does not work on this architecture");
+      flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
     }
 
   /* Save the current optimization options if this is the first call.  */
@@ -1976,16 +1980,25 @@ common_handle_option (size_t scode, cons
       break;
 
     case OPT_fira_algorithm_:
-      if (!strcmp (arg, "regional"))
-	flag_ira_algorithm = IRA_ALGORITHM_REGIONAL;
-      else if (!strcmp (arg, "CB"))
+      if (!strcmp (arg, "CB"))
 	flag_ira_algorithm = IRA_ALGORITHM_CB;
-      else if (!strcmp (arg, "mixed"))
-	flag_ira_algorithm = IRA_ALGORITHM_MIXED;
+      else if (!strcmp (arg, "priority"))
+	flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
       else
 	warning (0, "unknown ira algorithm \"%s\"", arg);
       break;
 
+    case OPT_fira_region_:
+      if (!strcmp (arg, "one"))
+	flag_ira_region = IRA_REGION_ONE;
+      else if (!strcmp (arg, "all"))
+	flag_ira_region = IRA_REGION_ALL;
+      else if (!strcmp (arg, "mixed"))
+	flag_ira_region = IRA_REGION_MIXED;
+      else
+	warning (0, "unknown ira region \"%s\"", arg);
+      break;
+
     case OPT_fira_verbose_:
       flag_ira_verbose = value;
       break;
Index: ira-lives.c
===================================================================
--- ira-lives.c	(revision 142255)
+++ ira-lives.c	(working copy)
@@ -117,18 +117,23 @@ make_regno_born (int regno)
 static void
 update_allocno_pressure_excess_length (ira_allocno_t a)
 {
-  int start;
-  enum reg_class cover_class;
+  int start, i;
+  enum reg_class cover_class, cl;
   allocno_live_range_t p;
 
   cover_class = ALLOCNO_COVER_CLASS (a);
-  if (high_pressure_start_point[cover_class] < 0)
-    return;
-  p = ALLOCNO_LIVE_RANGES (a);
-  ira_assert (p != NULL);
-  start = (high_pressure_start_point[cover_class] > p->start
-	   ? high_pressure_start_point[cover_class] : p->start);
-  ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1;
+  for (i = 0;
+       (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+       i++)
+    {
+      if (high_pressure_start_point[cl] < 0)
+	continue;
+      p = ALLOCNO_LIVE_RANGES (a);
+      ira_assert (p != NULL);
+      start = (high_pressure_start_point[cl] > p->start
+	       ? high_pressure_start_point[cl] : p->start);
+      ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1;
+    }
 }
 
 /* Process the death of register REGNO.  This updates hard_regs_live
@@ -165,8 +170,8 @@ static int curr_reg_pressure[N_REG_CLASS
 static void
 set_allocno_live (ira_allocno_t a)
 {
-  int nregs;
-  enum reg_class cover_class;
+  int i;
+  enum reg_class cover_class, cl;
 
   /* Invalidate because it is referenced.  */
   allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
@@ -176,15 +181,17 @@ set_allocno_live (ira_allocno_t a)
   IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), hard_regs_live);
   IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), hard_regs_live);
   cover_class = ALLOCNO_COVER_CLASS (a);
-  nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)];
-  curr_reg_pressure[cover_class] += nregs;
-  if (high_pressure_start_point[cover_class] < 0
-      && (curr_reg_pressure[cover_class]
-	  > ira_available_class_regs[cover_class]))
-    high_pressure_start_point[cover_class] = curr_point;
-  if (curr_bb_node->reg_pressure[cover_class]
-      < curr_reg_pressure[cover_class])
-    curr_bb_node->reg_pressure[cover_class] = curr_reg_pressure[cover_class];
+  for (i = 0;
+       (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+       i++)
+    {
+      curr_reg_pressure[cl] += ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
+      if (high_pressure_start_point[cl] < 0
+	  && (curr_reg_pressure[cl] > ira_available_class_regs[cl]))
+	high_pressure_start_point[cl] = curr_point;
+      if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl])
+	curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl];
+    }
 }
 
 /* Mark allocno A as currently not living and update current register
@@ -193,26 +200,40 @@ set_allocno_live (ira_allocno_t a)
 static void
 clear_allocno_live (ira_allocno_t a)
 {
-  unsigned int i;
-  enum reg_class cover_class;
+  int i;
+  unsigned int j;
+  enum reg_class cover_class, cl;
+  bool set_p;
 
   /* Invalidate because it is referenced.  */
   allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
   if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
     {
       cover_class = ALLOCNO_COVER_CLASS (a);
-      curr_reg_pressure[cover_class]
-	-= ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)];
-      ira_assert (curr_reg_pressure[cover_class] >= 0);
-      if (high_pressure_start_point[cover_class] >= 0
-	  && (curr_reg_pressure[cover_class]
-	      <= ira_available_class_regs[cover_class]))
+      set_p = false;
+      for (i = 0;
+	   (cl = ira_reg_class_super_classes[cover_class][i])
+	     != LIM_REG_CLASSES;
+	   i++)
 	{
-	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
-	    {
-	      update_allocno_pressure_excess_length (ira_allocnos[i]);
-	    }
-	  high_pressure_start_point[cover_class] = -1;
+	  curr_reg_pressure[cl] -= ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
+	  ira_assert (curr_reg_pressure[cl] >= 0);
+	  if (high_pressure_start_point[cl] >= 0
+	      && curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+	    set_p = true;
+	}
+      if (set_p)
+	{
+	  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
+	    update_allocno_pressure_excess_length (ira_allocnos[j]);
+	  for (i = 0;
+	       (cl = ira_reg_class_super_classes[cover_class][i])
+		 != LIM_REG_CLASSES;
+	       i++)
+	    if (high_pressure_start_point[cl] >= 0
+		&& curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+	      high_pressure_start_point[cl] = -1;
+	  
 	}
     }
   sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
@@ -225,7 +246,7 @@ clear_allocno_live (ira_allocno_t a)
 static void
 mark_reg_live (rtx reg)
 {
-  int regno;
+  int i, regno;
 
   gcc_assert (REG_P (reg));
   regno = REGNO (reg);
@@ -249,7 +270,7 @@ mark_reg_live (rtx reg)
   else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
     {
       int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-      enum reg_class cover_class;
+      enum reg_class cover_class, cl;
 
       while (regno < last)
 	{
@@ -257,20 +278,26 @@ mark_reg_live (rtx reg)
 	      && ! TEST_HARD_REG_BIT (eliminable_regset, regno))
 	    {
 	      cover_class = ira_hard_regno_cover_class[regno];
-	      if (cover_class != NO_REGS)
+	      for (i = 0;
+		   (cl = ira_reg_class_super_classes[cover_class][i])
+		     != LIM_REG_CLASSES;
+		   i++)
 		{
-		  curr_reg_pressure[cover_class]++;
-		  if (high_pressure_start_point[cover_class] < 0
-		      && (curr_reg_pressure[cover_class]
-			  > ira_available_class_regs[cover_class]))
-		    high_pressure_start_point[cover_class] = curr_point;
+		  curr_reg_pressure[cl]++;
+		  if (high_pressure_start_point[cl] < 0
+		      && (curr_reg_pressure[cl]
+			  > ira_available_class_regs[cl]))
+		    high_pressure_start_point[cl] = curr_point;
 		}
 	      make_regno_born (regno);
-	      if (cover_class != NO_REGS
-		  && (curr_bb_node->reg_pressure[cover_class]
-		      < curr_reg_pressure[cover_class]))
-		curr_bb_node->reg_pressure[cover_class]
-		  = curr_reg_pressure[cover_class];
+	      for (i = 0;
+		   (cl = ira_reg_class_super_classes[cover_class][i])
+		     != LIM_REG_CLASSES;
+		   i++)
+		{
+		  if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl])
+		    curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl];
+		}
 	    }
 	  regno++;
 	}
@@ -317,30 +344,41 @@ mark_reg_dead (rtx reg)
     }
   else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
     {
-      unsigned int i;
+      int i;
+      unsigned int j;
       int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-      enum reg_class cover_class;
+      enum reg_class cover_class, cl;
+      bool set_p;
 
       while (regno < last)
 	{
 	  if (TEST_HARD_REG_BIT (hard_regs_live, regno))
 	    {
+	      set_p = false;
 	      cover_class = ira_hard_regno_cover_class[regno];
-	      if (cover_class != NO_REGS)
+	      for (i = 0;
+		   (cl = ira_reg_class_super_classes[cover_class][i])
+		     != LIM_REG_CLASSES;
+		   i++)
+  		{
+		  curr_reg_pressure[cl]--;
+		  if (high_pressure_start_point[cl] >= 0
+		      && curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+		    set_p = true;
+		  ira_assert (curr_reg_pressure[cl] >= 0);
+		}
+	      if (set_p)
 		{
-		  curr_reg_pressure[cover_class]--;
-		  if (high_pressure_start_point[cover_class] >= 0
-		      && (curr_reg_pressure[cover_class]
-			  <= ira_available_class_regs[cover_class]))
-		    {
-		      EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
-			{
-			  update_allocno_pressure_excess_length
-			    (ira_allocnos[i]);
-			}
-		      high_pressure_start_point[cover_class] = -1;
-		    }
-		  ira_assert (curr_reg_pressure[cover_class] >= 0);
+		  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
+		    update_allocno_pressure_excess_length (ira_allocnos[j]);
+		  for (i = 0;
+		       (cl = ira_reg_class_super_classes[cover_class][i])
+			 != LIM_REG_CLASSES;
+		       i++)
+		    if (high_pressure_start_point[cl] >= 0
+			&& (curr_reg_pressure[cl]
+			    <= ira_available_class_regs[cl]))
+		      high_pressure_start_point[cl] = -1;
 		}
 	      make_regno_dead (regno);
 	    }
@@ -807,18 +845,20 @@ process_bb_node_lives (ira_loop_tree_nod
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	if (TEST_HARD_REG_BIT (hard_regs_live, i))
 	  {
-	    enum reg_class cover_class;
+	    enum reg_class cover_class, cl;
 	    
-	    cover_class = ira_hard_regno_cover_class[i];
-	    if (cover_class == NO_REGS)
-	      continue;
-	    curr_reg_pressure[cover_class]++;
-	    if (curr_bb_node->reg_pressure[cover_class]
-		< curr_reg_pressure[cover_class])
-	      curr_bb_node->reg_pressure[cover_class]
-		= curr_reg_pressure[cover_class];
-	    ira_assert (curr_reg_pressure[cover_class]
-			<= ira_available_class_regs[cover_class]);
+	    cover_class = ira_class_translate[REGNO_REG_CLASS (i)];
+	    for (j = 0;
+		 (cl = ira_reg_class_super_classes[cover_class][j])
+		   != LIM_REG_CLASSES;
+		 j++)
+	      {
+		curr_reg_pressure[cl]++;
+		if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl])
+		  curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl];
+		ira_assert (curr_reg_pressure[cl]
+			    <= ira_available_class_regs[cl]);
+	      }
 	  }
       EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
 	{
Index: ira-build.c
===================================================================
--- ira-build.c	(revision 142255)
+++ ira-build.c	(working copy)
@@ -1583,8 +1583,8 @@ propagate_allocno_info (void)
   ira_loop_tree_node_t parent;
   enum reg_class cover_class;
 
-  if (flag_ira_algorithm != IRA_ALGORITHM_REGIONAL
-      && flag_ira_algorithm != IRA_ALGORITHM_MIXED)
+  if (flag_ira_region != IRA_REGION_ALL
+      && flag_ira_region != IRA_REGION_MIXED)
     return;
   for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
     for (a = ira_regno_allocno_map[i];
@@ -2044,9 +2044,10 @@ setup_min_max_allocno_live_range_point (
 }
 
 /* Sort allocnos according to their live ranges.  Allocnos with
-   smaller cover class are put first.  Allocnos with the same cove
-   class are ordered according their start (min).  Allocnos with the
-   same start are ordered according their finish (max).  */
+   smaller cover class are put first unless we use priority coloring.
+   Allocnos with the same cove class are ordered according their start
+   (min).  Allocnos with the same start are ordered according their
+   finish (max).  */
 static int
 allocno_range_compare_func (const void *v1p, const void *v2p)
 {
@@ -2054,7 +2055,8 @@ allocno_range_compare_func (const void *
   ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
   ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
 
-  if ((diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0)
+  if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
+      && (diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0)
     return diff;
   if ((diff = ALLOCNO_MIN (a1) - ALLOCNO_MIN (a2)) != 0)
     return diff;
@@ -2089,7 +2091,7 @@ sort_conflict_id_allocno_map (void)
 static void
 setup_min_max_conflict_allocno_ids (void)
 {
-  enum reg_class cover_class;
+  int cover_class;
   int i, j, min, max, start, finish, first_not_finished, filled_area_start;
   int *live_range_min, *last_lived;
   ira_allocno_t a;
@@ -2102,7 +2104,9 @@ setup_min_max_conflict_allocno_ids (void
       a = ira_conflict_id_allocno_map[i];
       if (a == NULL)
 	continue;
-      if (cover_class != ALLOCNO_COVER_CLASS (a))
+      if (cover_class < 0
+	  || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
+	      && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
 	{
 	  cover_class = ALLOCNO_COVER_CLASS (a);
 	  min = i;
@@ -2136,7 +2140,9 @@ setup_min_max_conflict_allocno_ids (void
       a = ira_conflict_id_allocno_map[i];
       if (a == NULL)
 	continue;
-      if (cover_class != ALLOCNO_COVER_CLASS (a))
+      if (cover_class < 0
+	  || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
+	      && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
 	{
 	  cover_class = ALLOCNO_COVER_CLASS (a);
 	  for (j = 0; j < ira_max_point; j++)
@@ -2431,7 +2437,8 @@ ira_flattening (int max_regno_before_emi
 		{
 		  ira_allocno_t live_a = ira_allocnos[n];
 
-		  if (cover_class == ALLOCNO_COVER_CLASS (live_a)
+		  if (ira_reg_classes_intersect_p
+		      [cover_class][ALLOCNO_COVER_CLASS (live_a)]
 		      /* Don't set up conflict for the allocno with itself.  */
 		      && num != (int) n)
 		    ira_add_allocno_conflict (a, live_a);
Index: genpreds.c
===================================================================
--- genpreds.c	(revision 142255)
+++ genpreds.c	(working copy)
@@ -959,7 +959,7 @@ write_enum_constraint_num (void)
 	 "  CONSTRAINT__UNKNOWN = 0", stdout);
   FOR_ALL_CONSTRAINTS (c)
     printf (",\n  CONSTRAINT_%s", c->c_name);
-  puts ("\n};\n");
+  puts (",\n  CONSTRAINT__LIMIT\n};\n");
 }
 
 /* Write out a function which looks at a string and determines what
Index: common.opt
===================================================================
--- common.opt	(revision 142255)
+++ common.opt	(working copy)
@@ -683,7 +683,11 @@ Use integrated register allocator.
 
 fira-algorithm=
 Common Joined RejectNegative
--fira-algorithm=[regional|CB|mixed] Set the used IRA algorithm
+-fira-algorithm=[CB|priority] Set the used IRA algorithm
+
+fira-region=
+Common Joined RejectNegative
+-fira-region=[one|all|mixed] Set regions for IRA
 
 fira-coalesce
 Common Report Var(flag_ira_coalesce) Init(0)
Index: ira.c
===================================================================
--- ira.c	(revision 142255)
+++ ira.c	(working copy)
@@ -434,6 +434,8 @@ setup_class_hard_regs (void)
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
       CLEAR_HARD_REG_SET (processed_hard_reg_set);
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+	ira_class_hard_reg_index[cl][0] = -1;
       for (n = 0, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	{
 #ifdef REG_ALLOC_ORDER
@@ -714,22 +716,72 @@ enum reg_class ira_important_classes[N_R
    classes.  */
 int ira_important_class_nums[N_REG_CLASSES];
 
-/* Check IRA_COVER_CLASSES and sets the four global variables defined
-   above.  */
+/* Set the four global variables defined above.  */
 static void
 setup_cover_and_important_classes (void)
 {
-  int i, j;
+  int i, j, n;
+  bool set_p, eq_p;
   enum reg_class cl;
-  const enum reg_class *classes;
+  const enum reg_class *cover_classes;
   HARD_REG_SET temp_hard_regset2;
+  static enum reg_class classes[LIM_REG_CLASSES + 1];
+
+  if (targetm.ira_cover_classes == NULL)
+    cover_classes = NULL;
+  else
+    cover_classes = targetm.ira_cover_classes ();
+  if (cover_classes == NULL)
+    ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY);
+  else
+    {
+      for (i = 0; (cl = cover_classes[i]) != LIM_REG_CLASSES; i++)
+	classes[i] = cl;
+      classes[i] = LIM_REG_CLASSES;
+    }
+
+  if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+    {
+      n = 0;
+      for (i = 0; i <= LIM_REG_CLASSES; i++)
+	{
+	  if (i == NO_REGS)
+	    continue;
+#ifdef CONSTRAINT__LIMIT
+	  for (j = 0; j < CONSTRAINT__LIMIT; j++)
+	    if ((int) regclass_for_constraint (j) == i)
+	      break;
+	  if (j < CONSTRAINT__LIMIT)
+	    {
+	      classes[n++] = i;
+	      continue;
+	    }
+#endif
+	  COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
+	  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+	  for (j = 0; j < LIM_REG_CLASSES; j++)
+	    {
+	      if (i == j)
+		continue;
+	      COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[j]);
+	      AND_COMPL_HARD_REG_SET (temp_hard_regset2,
+				      no_unit_alloc_regs);
+	      if (hard_reg_set_equal_p (temp_hard_regset,
+					temp_hard_regset2))
+		    break;
+	    }
+	  if (j >= i)
+	    classes[n++] = i;
+	}
+      classes[n] = LIM_REG_CLASSES;
+    }
 
-  classes = targetm.ira_cover_classes ();
   ira_reg_class_cover_size = 0;
   for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++)
     {
       for (j = 0; j < i; j++)
-	if (reg_classes_intersect_p (cl, classes[j]))
+	if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
+	    && reg_classes_intersect_p (cl, classes[j]))
 	  gcc_unreachable ();
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
@@ -742,22 +794,34 @@ setup_cover_and_important_classes (void)
       COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
       AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
       if (! hard_reg_set_empty_p (temp_hard_regset))
-	for (j = 0; j < ira_reg_class_cover_size; j++)
-	  {
-	    COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-	    AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-	    COPY_HARD_REG_SET (temp_hard_regset2,
-			       reg_class_contents[ira_reg_class_cover[j]]);
-	    AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
-	    if (cl == ira_reg_class_cover[j]
-		|| (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
-		    && ! hard_reg_set_equal_p (temp_hard_regset,
-					       temp_hard_regset2)))
-	      {
-		ira_important_class_nums[cl] = ira_important_classes_num;
-		ira_important_classes[ira_important_classes_num++] = cl;
-	      }
-	  }
+	{
+	  set_p = eq_p = false;
+	  for (j = 0; j < ira_reg_class_cover_size; j++)
+	    {
+	      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+	      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+	      COPY_HARD_REG_SET (temp_hard_regset2,
+				 reg_class_contents[ira_reg_class_cover[j]]);
+	      AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+	      if (cl == ira_reg_class_cover[j])
+		{
+		  eq_p = false;
+		  set_p = true;
+		  break;
+		}
+	      else if (hard_reg_set_equal_p (temp_hard_regset,
+					     temp_hard_regset2))
+		eq_p = true;
+	      else if (hard_reg_set_subset_p (temp_hard_regset,
+					      temp_hard_regset2))
+		set_p = true;
+	    }
+	  if (set_p && ! eq_p)
+	    {
+	      ira_important_class_nums[cl] = ira_important_classes_num;
+	      ira_important_classes[ira_important_classes_num++] = cl;
+	    }
+	}
     }
 }
 
@@ -776,25 +840,44 @@ setup_class_translate (void)
 
   for (cl = 0; cl < N_REG_CLASSES; cl++)
     ira_class_translate[cl] = NO_REGS;
+  
+  if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+    for (cl = 0; cl < LIM_REG_CLASSES; cl++)
+      {
+	COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+	AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+	for (i = 0; i < ira_reg_class_cover_size; i++)
+	  {
+	    HARD_REG_SET temp_hard_regset2;
+	    
+	    cover_class = ira_reg_class_cover[i];
+	    COPY_HARD_REG_SET (temp_hard_regset2,
+			       reg_class_contents[cover_class]);
+	    AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+	    if (hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2))
+	      ira_class_translate[cl] = cover_class;
+	  }
+      }
   for (i = 0; i < ira_reg_class_cover_size; i++)
     {
       cover_class = ira_reg_class_cover[i];
-      for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0];
-	   (cl = *cl_ptr) != LIM_REG_CLASSES;
-	   cl_ptr++)
-	{
-	  if (ira_class_translate[cl] == NO_REGS)
-	    ira_class_translate[cl] = cover_class;
+      if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY)
+	for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0];
+	     (cl = *cl_ptr) != LIM_REG_CLASSES;
+	     cl_ptr++)
+	  {
+	    if (ira_class_translate[cl] == NO_REGS)
+	      ira_class_translate[cl] = cover_class;
 #ifdef ENABLE_IRA_CHECKING
-	  else
-	    {
-	      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-	      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
-	      if (! hard_reg_set_empty_p (temp_hard_regset))
-		gcc_unreachable ();
-	    }
+	    else
+	      {
+		COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+		AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+		if (! hard_reg_set_empty_p (temp_hard_regset))
+		  gcc_unreachable ();
+	      }
 #endif
-	}
+	  }
       ira_class_translate[cover_class] = cover_class;
     }
   /* For classes which are not fully covered by a cover class (in
@@ -842,6 +925,17 @@ setup_class_translate (void)
    account.  */
 enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES];
 
+/* True if the two classes (that is calculated taking only hard
+   registers available for allocation into account) are
+   intersected.  */
+bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES];
+
+/* Important classes with end marker LIM_REG_CLASSES which are
+   supersets with given important class (the first index).  That
+   includes given class itself.  This is calculated taking only hard
+   registers available for allocation into account.  */
+enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES];
+
 /* The biggest important reg_class inside of union of the two
    reg_classes (that is calculated taking only hard registers
    available for allocation into account).  If the both reg_classes
@@ -851,17 +945,23 @@ enum reg_class ira_reg_class_intersect[N
    reg_class_subunion value.  */
 enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES];
 
-/* Set up IRA_REG_CLASS_INTERSECT and IRA_REG_CLASS_UNION.  */
+/* Set up the above reg class relations.  */
 static void
-setup_reg_class_intersect_union (void)
+setup_reg_class_relations (void)
 {
   int i, cl1, cl2, cl3;
   HARD_REG_SET intersection_set, union_set, temp_set2;
+  bool important_class_p[N_REG_CLASSES];
 
+  memset (important_class_p, 0, sizeof (important_class_p));
+  for (i = 0; i < ira_important_classes_num; i++)
+    important_class_p[ira_important_classes[i]] = true;
   for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
     {
+      ira_reg_class_super_classes[cl1][0] = LIM_REG_CLASSES;
       for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++)
 	{
+	  ira_reg_classes_intersect_p[cl1][cl2] = false;
 	  ira_reg_class_intersect[cl1][cl2] = NO_REGS;
 	  COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
 	  AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
@@ -882,6 +982,19 @@ setup_reg_class_intersect_union (void)
 	      ira_reg_class_union[cl1][cl2] = reg_class_subunion[cl1][cl2];
 	      continue;
 	    }
+	  ira_reg_classes_intersect_p[cl1][cl2]
+	    = hard_reg_set_intersect_p (temp_hard_regset, temp_set2);
+	  if (important_class_p[cl1] && important_class_p[cl2]
+	      && hard_reg_set_subset_p (temp_hard_regset, temp_set2))
+	    {
+	      enum reg_class *p;
+
+	      p = &ira_reg_class_super_classes[cl1][0];
+	      while (*p != LIM_REG_CLASSES)
+		p++;
+	      *p++ = (enum reg_class) cl2;
+	      *p = LIM_REG_CLASSES;
+	    }
 	  ira_reg_class_union[cl1][cl2] = NO_REGS;
 	  COPY_HARD_REG_SET (intersection_set, reg_class_contents[cl1]);
 	  AND_HARD_REG_SET (intersection_set, reg_class_contents[cl2]);
@@ -966,12 +1079,9 @@ static void
 find_reg_class_closure (void)
 {
   setup_reg_subclasses ();
-  if (targetm.ira_cover_classes)
-    {
-      setup_cover_and_important_classes ();
-      setup_class_translate ();
-      setup_reg_class_intersect_union ();
-    }
+  setup_cover_and_important_classes ();
+  setup_class_translate ();
+  setup_reg_class_relations ();
 }
 
 
@@ -1804,8 +1914,8 @@ ira (FILE *f)
   if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
     fprintf (ira_dump_file, "Building IRA IR\n");
   loops_p = ira_build (optimize
-		       && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-			   || flag_ira_algorithm == IRA_ALGORITHM_MIXED));
+		       && (flag_ira_region == IRA_REGION_ALL
+			   || flag_ira_region == IRA_REGION_MIXED));
 
   saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
   if (too_high_register_pressure_p ())
Index: ira-costs.c
===================================================================
--- ira-costs.c	(revision 142255)
+++ ira-costs.c	(working copy)
@@ -105,6 +105,9 @@ static enum reg_class *allocno_pref;
 /* Allocated buffers for allocno_pref.  */
 static enum reg_class *allocno_pref_buffer;
 
+/* Record register class of each allocno with the same regno.  */
+static enum reg_class *common_classes;
+
 /* Execution frequency of the current insn.  */
 static int frequency;
 
@@ -1082,8 +1085,8 @@ print_costs (FILE *f)
 	    {
 	      fprintf (f, " %s:%d", reg_class_names[rclass],
 		       COSTS_OF_ALLOCNO (allocno_costs, i)->cost[k]);
-	      if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-		  || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
+	      if (flag_ira_region == IRA_REGION_ALL
+		  || flag_ira_region == IRA_REGION_MIXED)
 		fprintf (f, ",%d", COSTS_OF_ALLOCNO (total_costs, i)->cost[k]);
 	    }
 	}
@@ -1173,7 +1176,7 @@ find_allocno_class_costs (void)
 	  int rclass, a_num, parent_a_num;
 	  ira_loop_tree_node_t parent;
 	  int best_cost, allocno_cost;
-	  enum reg_class best, alt_class, common_class;
+	  enum reg_class best, alt_class;
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 	  int inc_dec_p = false;
 #endif
@@ -1187,8 +1190,8 @@ find_allocno_class_costs (void)
 	       a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
 	    {
 	      a_num = ALLOCNO_NUM (a);
-	      if ((flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
-		   || flag_ira_algorithm == IRA_ALGORITHM_MIXED)
+	      if ((flag_ira_region == IRA_REGION_ALL
+		   || flag_ira_region == IRA_REGION_MIXED)
 		  && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL
 		  && (parent_a = parent->regno_allocno_map[i]) != NULL
 		  /* There are no caps yet.  */
@@ -1247,6 +1250,7 @@ find_allocno_class_costs (void)
 		      > reg_class_size[alt_class]))
 		alt_class = reg_class_subunion[alt_class][rclass];
 	    }
+	  alt_class = ira_class_translate[alt_class];
 	  if (pass == flag_expensive_optimizations)
 	    {
 	      if (best_cost > temp_costs->mem_cost)
@@ -1260,18 +1264,22 @@ find_allocno_class_costs (void)
 			 i, reg_class_names[best], reg_class_names[alt_class]);
 	    }
 	  if (best_cost > temp_costs->mem_cost)
-	    common_class = NO_REGS;
+	    common_classes[i] = NO_REGS;
+	  else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+	    /* Make the common class the biggest class of best and
+	       alt_class.  */
+	    common_classes[i] = alt_class == NO_REGS ? best : alt_class;
 	  else
 	    /* Make the common class a cover class.  Remember all
 	       allocnos with the same regno should have the same cover
 	       class.  */
-	    common_class = ira_class_translate[best];
+	    common_classes[i] = ira_class_translate[best];
 	  for (a = ira_regno_allocno_map[i];
 	       a != NULL;
 	       a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
 	    {
 	      a_num = ALLOCNO_NUM (a);
-	      if (common_class == NO_REGS)
+	      if (common_classes[i] == NO_REGS)
 		best = NO_REGS;
 	      else
 		{	      
@@ -1283,7 +1291,7 @@ find_allocno_class_costs (void)
 		  for (k = 0; k < cost_classes_num; k++)
 		    {
 		      rclass = cost_classes[k];
-		      if (! ira_class_subset_p[rclass][common_class])
+		      if (! ira_class_subset_p[rclass][common_classes[i]])
 			continue;
 		      /* Ignore classes that are too small for this
 			 operand or invalid for an operand that was
@@ -1319,6 +1327,8 @@ find_allocno_class_costs (void)
 		    }
 		  ALLOCNO_COVER_CLASS_COST (a) = allocno_cost;
 		}
+	      ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY
+			  || ira_class_translate[best] == common_classes[i]);
 	      if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL
 		  && (pass == 0 || allocno_pref[a_num] != best))
 		{
@@ -1330,7 +1340,7 @@ find_allocno_class_costs (void)
 			     ALLOCNO_LOOP_TREE_NODE (a)->loop->num);
 		  fprintf (ira_dump_file, ") best %s, cover %s\n",
 			   reg_class_names[best],
-			   reg_class_names[ira_class_translate[best]]);
+			   reg_class_names[common_classes[i]]);
 		}
 	      allocno_pref[a_num] = best;
 	    }
@@ -1439,7 +1449,7 @@ setup_allocno_cover_class_and_costs (voi
     {
       i = ALLOCNO_NUM (a);
       mode = ALLOCNO_MODE (a);
-      cover_class = ira_class_translate[allocno_pref[i]];
+      cover_class = common_classes[ALLOCNO_REGNO (a)];
       ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS);
       ALLOCNO_MEMORY_COST (a) = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost;
       ira_set_allocno_cover_class (a, cover_class);
@@ -1572,6 +1582,9 @@ ira_costs (void)
   allocno_pref_buffer
     = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
 				       * ira_allocnos_num);
+  common_classes
+    = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
+				       * max_reg_num ());
   find_allocno_class_costs ();
   setup_allocno_cover_class_and_costs ();
   /* Because we could process operands only as subregs, check mode of
@@ -1580,6 +1593,7 @@ ira_costs (void)
     if (ira_register_move_cost[ALLOCNO_MODE (a)] == NULL
 	&& have_regs_of_mode[ALLOCNO_MODE (a)])
       ira_init_register_move_cost (ALLOCNO_MODE (a));
+  ira_free (common_classes);
   ira_free (allocno_pref_buffer);
   ira_free (total_costs);
   ira_free (allocno_costs);
Index: config/m32c/m32c.h
===================================================================
--- config/m32c/m32c.h	(revision 142255)
+++ config/m32c/m32c.h	(working copy)
@@ -224,7 +224,7 @@ machine_function;
 
 #define REG_ALLOC_ORDER { \
 	0, 1, 2, 3, 4, 5, /* r0..r3, a0, a1 */ \
-	12, 13, 14, 15, 16, 17, 18, /* mem0..mem7 */  \
+        12, 13, 14, 15, 16, 17, 18, 19, /* mem0..mem7 */	\
 	6, 7, 8, 9, 10, 11 /* sb, fb, sp, pc, flg, ap */ }
 
 /* How Values Fit in Registers */

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