diff mbox

Patch 2/9: Split up and reorganize some functions

Message ID 4C1B7D21.6020607@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt June 18, 2010, 2:05 p.m. UTC
This creates a few helper functions by breaking them out of larger ones.
In part, this is to make the code easier to read and should be a stand-alone
improvement, but mostly it is motivated by subsequent patches which will
modify the behaviour of the new functions.

In ira-lives.c, there is a slightly more involved restructuring of the:
Functions to mark registers live or dead are split up into versions for
pseudos and hard registers.  set_allocno_live and clear_allocno_live get
the more descriptive names inc_register_pressure and dec_register_pressure;
all code that isn't related to tracking pressure is moved into other
functions.  This allows us to further reduce code duplication by reusing
these functions in mark_hard_reg_live and mark_hard_reg_dead.  I've also
fixed up some confusion about when to clear allocno_saved_at_call.

Note that there is a small change in behaviour: in inc/dec_register_pressure,
we no longer recompute nregs as we iterate through the classes.  I think it's
more correct this way, and I haven't seen any difference in code generation.

	* ira-build.c (merge_hard_reg_conflicts): New function.
	(create_cap_allocno, copy_info_to_removed_store_destinations,
	propagate_some_info_from_allocno, propagate_allocno_info): Use it.
	(move_allocno_live_ranges, copy_allocno_live_ranges): New functions.
	(remove_unnecessary_allocnos, remove_low_level_allocnos)
	copy_nifo_to_removed_store_destination): Use them.
	* ira-lives.c (make_hard_regno_born): New function, split out of
	make_regno_born.
	(make_allocno_born): Likewise.
	(make_hard_regno_dead): New function, split out of make_regno_dead.
	(make_allocno_dead): Likewise.
	(inc_register_pressure): New function, split out of set_allocno_live.
	(dec_register_pressure): New function, split out of clear_allocno_live.
	(mark_pseudo_regno_live): New function, split out of mark_reg_live.
	(mark_hard_reg_live): Likewise.  Use inc_register_pressure.
	(mark_pseudo_regno_dead): New function, split out of mark_reg_dead.
	(mark_hard_reg_dead): Likewise.  Use dec_register_pressure.
	(make_pseudo_conflict): Use mark_pseudo_regno_dead and
	mark_pseudo_regno_live.
	(process_bb_node_lives): Use mark_pseudo_regno_live,
	make_hard_regno_born and make_allocno_dead.
	(make_regno_born, make_regno_dead, mark_reg_live, mark_reg_dead,
	set_allocno_live, clear_allocno_live): Delete functions.

(Index: gcc/ira-build.c

Comments

Jeff Law June 18, 2010, 5:09 p.m. UTC | #1
On 06/18/10 08:05, Bernd Schmidt wrote:
>   I've also
> fixed up some confusion about when to clear allocno_saved_at_call.
Yea, I had to look at that a few times to convince myself that 
everything was OK.

>
> Note that there is a small change in behaviour: in 
> inc/dec_register_pressure,
> we no longer recompute nregs as we iterate through the classes.  I 
> think it's
> more correct this way, and I haven't seen any difference in code 
> generation.
There may be oddball architectures where this matters, but I can't think 
of one offhand.  One could argue that for such an architecture that the 
regs should be in different classes.  If we wanted to be absolutely sure 
we could test for this situation once per compilation unit and ICE -- 
that might save a developer on one of these targets considerable 
debugging time.

I think I'd give port maintainers a quick chance to chime in as to 
whether or not their port has registers in a class where the number of 
hard regs to represent a given mode varies within the class.   Otherwise 
it looks fine.

If you wanted to get the bulk of these changes in and old off on the 
behaviour change, then that'd be fine by me.

jeff
Bernd Schmidt June 18, 2010, 5:25 p.m. UTC | #2
On 06/18/10 17:09, Jeff Law wrote:

> I think I'd give port maintainers a quick chance to chime in as to
> whether or not their port has registers in a class where the number of
> hard regs to represent a given mode varies within the class.   Otherwise
> it looks fine.

The reason why I think it's more correct this way is that we're going to
allocate the allocno from within its cover_class.  In these functions
we're trying to estimate how many registers are going to be used by an
allocno, and we should use the nregs we compute for that cover class,
even when adjusting the pressure for its superclasses (since none of the
extra registers in the superclasses can be used anyway).

Example: we have a class A of 64 bit registers and a 64 bit allocno with
cover class A; nregs would be 1.  The register pressure in A would be
increased by 1, and the pressure in ALL_REGS should also be increased
only by 1, even if ALL_REGS also contains 32 bit registers, since the
existence of those is irrelevant to the allocno we're looking at.  The
current code would recompute nregs when cl == ALL_REGS and set it to 2,
which I think is wrong.

> If you wanted to get the bulk of these changes in and old off on the
> behaviour change, then that'd be fine by me.

I'll just wait until we have consensus on that; if we decide it's not
correct I can then figure out how to adjust it (it would make it harder
to share code between the allocno/hard reg cases).

Thanks for the quick reviews.


Bernd
Jeff Law June 21, 2010, 3:54 p.m. UTC | #3
On 06/18/10 11:25, Bernd Schmidt wrote:
> On 06/18/10 17:09, Jeff Law wrote:
>
>    
>> I think I'd give port maintainers a quick chance to chime in as to
>> whether or not their port has registers in a class where the number of
>> hard regs to represent a given mode varies within the class.   Otherwise
>> it looks fine.
>>      
> The reason why I think it's more correct this way is that we're going to
> allocate the allocno from within its cover_class.  In these functions
> we're trying to estimate how many registers are going to be used by an
> allocno, and we should use the nregs we compute for that cover class,
> even when adjusting the pressure for its superclasses (since none of the
> extra registers in the superclasses can be used anyway).
>
> Example: we have a class A of 64 bit registers and a 64 bit allocno with
> cover class A; nregs would be 1.  The register pressure in A would be
> increased by 1, and the pressure in ALL_REGS should also be increased
> only by 1, even if ALL_REGS also contains 32 bit registers, since the
> existence of those is irrelevant to the allocno we're looking at.  The
> current code would recompute nregs when cl == ALL_REGS and set it to 2,
> which I think is wrong.
>    
I wasn't disagreeing with whether or not this change is more correct -- 
in fact, I'm in total agreement that it's more correct.  I merely had a 
concern that if we had a port where the number of hard regs needed to 
represent a particular mode varied within the class was going to cause a 
problem.   I consider the possibility unlikely, particularly since an 
under-estimation of the number of available regs merely results in 
inefficient code, not incorrect code.  I just wanted to give port 
maintainers a chance to chime in.

I'd say, give them another 48hrs or so to object, and if none occur, go 
forward with the patch.

Jeff
Bernd Schmidt June 21, 2010, 4 p.m. UTC | #4
On 06/21/2010 05:54 PM, Jeff Law wrote:
> I wasn't disagreeing with whether or not this change is more correct --
> in fact, I'm in total agreement that it's more correct.  I merely had a
> concern that if we had a port where the number of hard regs needed to
> represent a particular mode varied within the class was going to cause a
> problem.

Yeah, but I don't think that this part of the code is affected at all by
that particular issue.  It's an estimate of register pressure, and it
always uses the maximum nregs that could be needed by a class/mode
combination.  What am I missing?
The issue of variable nregs inside one class is something I have to deal
with in the final patch (which I expect to post sometime later this
evening, test results look good so far).

> I'd say, give them another 48hrs or so to object, and if none occur, go
> forward with the patch.

Will do.  Thanks.


Bernd
diff mbox

Patch

===================================================================
--- gcc.orig/ira-build.c
+++ gcc/ira-build.c
@@ -504,6 +504,25 @@  ira_set_allocno_cover_class (ira_allocno
 			  reg_class_contents[cover_class]);
 }
 
+/* Merge hard register conflicts from allocno FROM into allocno TO.  If
+   TOTAL_ONLY is true, we ignore ALLOCNO_CONFLICT_HARD_REGS.  */
+static void
+merge_hard_reg_conflicts (ira_allocno_t from, ira_allocno_t to,
+			  bool total_only)
+{
+  if (!total_only)
+    IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (to),
+		      ALLOCNO_CONFLICT_HARD_REGS (from));
+  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (to),
+		    ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from));
+#ifdef STACK_REGS
+  if (!total_only && ALLOCNO_NO_STACK_REG_P (from))
+    ALLOCNO_NO_STACK_REG_P (to) = true;
+  if (ALLOCNO_TOTAL_NO_STACK_REG_P (from))
+    ALLOCNO_TOTAL_NO_STACK_REG_P (to) = true;
+#endif
+}
+
 /* Return TRUE if the conflict vector with NUM elements is more
    profitable than conflict bit vector for A.  */
 bool
@@ -781,15 +800,8 @@  create_cap_allocno (ira_allocno_t a)
   ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a);
   ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a);
   ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a);
-  IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (cap),
-		    ALLOCNO_CONFLICT_HARD_REGS (a));
-  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (cap),
-		    ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+  merge_hard_reg_conflicts (a, cap, false);
   ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a);
-#ifdef STACK_REGS
-  ALLOCNO_NO_STACK_REG_P (cap) = ALLOCNO_NO_STACK_REG_P (a);
-  ALLOCNO_TOTAL_NO_STACK_REG_P (cap) = ALLOCNO_TOTAL_NO_STACK_REG_P (a);
-#endif
   if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
     {
       fprintf (ira_dump_file, "    Creating cap ");
@@ -1603,12 +1615,7 @@  propagate_allocno_info (void)
 	  ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a);
 	  ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a);
 	  ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
-#ifdef STACK_REGS
-	  if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
-	    ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
-	  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
-			    ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+	  merge_hard_reg_conflicts (a, parent_a, true);
 	  ALLOCNO_CALLS_CROSSED_NUM (parent_a)
 	    += ALLOCNO_CALLS_CROSSED_NUM (a);
 	  ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
@@ -1657,6 +1664,46 @@  change_allocno_in_range_list (allocno_li
     r->allocno = a;
 }
 
+/* Move all live ranges associated with allocno A to allocno OTHER_A.  */
+static void
+move_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to)
+{
+  allocno_live_range_t lr = ALLOCNO_LIVE_RANGES (from);
+
+  if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+    {
+      fprintf (ira_dump_file,
+	       "      Moving ranges of a%dr%d to a%dr%d: ",
+	       ALLOCNO_NUM (from), ALLOCNO_REGNO (from),
+	       ALLOCNO_NUM (to), ALLOCNO_REGNO (to));
+      ira_print_live_range_list (ira_dump_file, lr);
+    }
+  change_allocno_in_range_list (lr, to);
+  ALLOCNO_LIVE_RANGES (to)
+    = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to));
+  ALLOCNO_LIVE_RANGES (from) = NULL;
+}
+
+/* Copy all live ranges associated with allocno A to allocno OTHER_A.  */
+static void
+copy_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to)
+{
+  allocno_live_range_t lr = ALLOCNO_LIVE_RANGES (from);
+
+  if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+    {
+      fprintf (ira_dump_file,
+	       "      Copying ranges of a%dr%d to a%dr%d: ",
+	       ALLOCNO_NUM (from), ALLOCNO_REGNO (from),
+	       ALLOCNO_NUM (to), ALLOCNO_REGNO (to));
+      ira_print_live_range_list (ira_dump_file, lr);
+    }
+  lr = ira_copy_allocno_live_range_list (lr);
+  change_allocno_in_range_list (lr, to);
+  ALLOCNO_LIVE_RANGES (to)
+    = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to));
+}
+
 /* Return TRUE if NODE represents a loop with low register
    pressure.  */
 static bool
@@ -1890,26 +1937,15 @@  propagate_some_info_from_allocno (ira_al
 {
   enum reg_class cover_class;
 
-  IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
-		    ALLOCNO_CONFLICT_HARD_REGS (from_a));
-#ifdef STACK_REGS
-  if (ALLOCNO_NO_STACK_REG_P (from_a))
-    ALLOCNO_NO_STACK_REG_P (a) = true;
-#endif
+  merge_hard_reg_conflicts (from_a, a, false);
   ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
   ALLOCNO_FREQ (a) += ALLOCNO_FREQ (from_a);
   ALLOCNO_CALL_FREQ (a) += ALLOCNO_CALL_FREQ (from_a);
-  IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
-		    ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from_a));
   ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
   ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
     += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
   if (! ALLOCNO_BAD_SPILL_P (from_a))
     ALLOCNO_BAD_SPILL_P (a) = false;
-#ifdef STACK_REGS
-  if (ALLOCNO_TOTAL_NO_STACK_REG_P (from_a))
-    ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true;
-#endif
   cover_class = ALLOCNO_COVER_CLASS (from_a);
   ira_assert (cover_class == ALLOCNO_COVER_CLASS (a));
   ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
@@ -1930,7 +1966,6 @@  remove_unnecessary_allocnos (void)
   bool merged_p, rebuild_p;
   ira_allocno_t a, prev_a, next_a, parent_a;
   ira_loop_tree_node_t a_node, parent;
-  allocno_live_range_t r;
 
   merged_p = false;
   regno_allocnos = NULL;
@@ -1971,13 +2006,8 @@  remove_unnecessary_allocnos (void)
 		    ira_regno_allocno_map[regno] = next_a;
 		  else
 		    ALLOCNO_NEXT_REGNO_ALLOCNO (prev_a) = next_a;
-		  r = ALLOCNO_LIVE_RANGES (a);
-		  change_allocno_in_range_list (r, parent_a);
-		  ALLOCNO_LIVE_RANGES (parent_a)
-		    = ira_merge_allocno_live_ranges
-		      (r, ALLOCNO_LIVE_RANGES (parent_a));
+		  move_allocno_live_ranges (a, parent_a);
 		  merged_p = true;
-		  ALLOCNO_LIVE_RANGES (a) = NULL;
 		  propagate_some_info_from_allocno (parent_a, a);
 		  /* Remove it from the corresponding regno allocno
 		     map to avoid info propagation of subsequent
@@ -2011,7 +2041,6 @@  remove_low_level_allocnos (void)
   bool merged_p, propagate_p;
   ira_allocno_t a, top_a;
   ira_loop_tree_node_t a_node, parent;
-  allocno_live_range_t r;
   ira_allocno_iterator ai;
 
   merged_p = false;
@@ -2030,12 +2059,8 @@  remove_low_level_allocnos (void)
       propagate_p = a_node->parent->regno_allocno_map[regno] == NULL;
       /* Remove the allocno and update info of allocno in the upper
 	 region.  */
-      r = ALLOCNO_LIVE_RANGES (a);
-      change_allocno_in_range_list (r, top_a);
-      ALLOCNO_LIVE_RANGES (top_a)
-	= ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (top_a));
+      move_allocno_live_ranges (a, top_a);
       merged_p = true;
-      ALLOCNO_LIVE_RANGES (a) = NULL;
       if (propagate_p)
 	propagate_some_info_from_allocno (top_a, a);
     }
@@ -2402,7 +2427,6 @@  copy_info_to_removed_store_destinations 
   ira_allocno_t a;
   ira_allocno_t parent_a = NULL;
   ira_loop_tree_node_t parent;
-  allocno_live_range_t r;
   bool merged_p;
 
   merged_p = false;
@@ -2425,26 +2449,8 @@  copy_info_to_removed_store_destinations 
 	  break;
       if (parent == NULL || parent_a == NULL)
 	continue;
-      if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
-	{
-	  fprintf
-	    (ira_dump_file,
-	     "      Coping ranges of a%dr%d to a%dr%d: ",
-	     ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)),
-	     ALLOCNO_NUM (parent_a), REGNO (ALLOCNO_REG (parent_a)));
-	  ira_print_live_range_list (ira_dump_file,
-				     ALLOCNO_LIVE_RANGES (a));
-	}
-      r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
-      change_allocno_in_range_list (r, parent_a);
-      ALLOCNO_LIVE_RANGES (parent_a)
-	= ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (parent_a));
-      IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
-			ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
-#ifdef STACK_REGS
-      if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
-	ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
+      copy_allocno_live_ranges (a, parent_a);
+      merge_hard_reg_conflicts (a, parent_a, true);
       ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
       ALLOCNO_CALLS_CROSSED_NUM (parent_a)
 	+= ALLOCNO_CALLS_CROSSED_NUM (a);
@@ -2522,28 +2528,9 @@  ira_flattening (int max_regno_before_emi
 	    mem_dest_p = true;
 	  if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a)))
 	    {
-	      IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
-				ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
-#ifdef STACK_REGS
-	      if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
-		ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
-	      if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
-		{
-		  fprintf (ira_dump_file,
-			   "      Moving ranges of a%dr%d to a%dr%d: ",
-			   ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)),
-			   ALLOCNO_NUM (parent_a),
-			   REGNO (ALLOCNO_REG (parent_a)));
-		  ira_print_live_range_list (ira_dump_file,
-					     ALLOCNO_LIVE_RANGES (a));
-		}
-	      change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a);
-	      ALLOCNO_LIVE_RANGES (parent_a)
-		= ira_merge_allocno_live_ranges
-		  (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a));
+	      merge_hard_reg_conflicts (a, parent_a, true);
+	      move_allocno_live_ranges (a, parent_a);
 	      merged_p = true;
-	      ALLOCNO_LIVE_RANGES (a) = NULL;
 	      ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
 		= (ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
 		   || ALLOCNO_MEM_OPTIMIZED_DEST_P (a));
Index: gcc/ira-lives.c
===================================================================
--- gcc.orig/ira-lives.c
+++ gcc/ira-lives.c
@@ -81,33 +81,44 @@  static int last_call_num;
 /* The number of last call at which given allocno was saved.  */
 static int *allocno_saved_at_call;
 
-/* The function processing birth of register REGNO.  It updates living
-   hard regs and conflict hard regs for living allocnos or starts a
-   new live range for the allocno corresponding to REGNO if it is
-   necessary.  */
+/* Record the birth of hard register REGNO, updating hard_regs_live
+   and hard reg conflict information for living allocno.  */
 static void
-make_regno_born (int regno)
+make_hard_regno_born (int regno)
 {
   unsigned int i;
-  ira_allocno_t a;
-  allocno_live_range_t p;
 
-  if (regno < FIRST_PSEUDO_REGISTER)
+  SET_HARD_REG_BIT (hard_regs_live, regno);
+  EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
     {
-      SET_HARD_REG_BIT (hard_regs_live, regno);
-      EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
-        {
-	  SET_HARD_REG_BIT (ALLOCNO_CONFLICT_HARD_REGS (ira_allocnos[i]),
-			    regno);
-	  SET_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (ira_allocnos[i]),
-			    regno);
-	}
-      return;
+      SET_HARD_REG_BIT (ALLOCNO_CONFLICT_HARD_REGS (ira_allocnos[i]),
+			regno);
+      SET_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (ira_allocnos[i]),
+			regno);
     }
-  a = ira_curr_regno_allocno_map[regno];
-  if (a == NULL)
-    return;
-  if ((p = ALLOCNO_LIVE_RANGES (a)) == NULL
+}
+
+/* Process the death of hard register REGNO.  This updates
+   hard_regs_live.  */
+static void
+make_hard_regno_dead (int regno)
+{
+  CLEAR_HARD_REG_BIT (hard_regs_live, regno);
+}
+
+/* Record the birth of allocno A, starting a new live range for
+   it if necessary, and updating hard reg conflict information.  We also
+   record it in allocnos_live.  */
+static void
+make_allocno_born (ira_allocno_t a)
+{
+  allocno_live_range_t p = ALLOCNO_LIVE_RANGES (a);
+
+  sparseset_set_bit (allocnos_live, ALLOCNO_NUM (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);
+
+  if (p == NULL
       || (p->finish != curr_point && p->finish + 1 != curr_point))
     ALLOCNO_LIVE_RANGES (a)
       = ira_create_allocno_live_range (a, curr_point, -1,
@@ -137,56 +148,39 @@  update_allocno_pressure_excess_length (i
     }
 }
 
-/* Process the death of register REGNO.  This updates hard_regs_live
-   or finishes the current live range for the allocno corresponding to
-   REGNO.  */
+/* Process the death of allocno A.  This finishes the current live
+   range for it.  */
 static void
-make_regno_dead (int regno)
+make_allocno_dead (ira_allocno_t a)
 {
-  ira_allocno_t a;
   allocno_live_range_t p;
 
-  if (regno < FIRST_PSEUDO_REGISTER)
-    {
-      CLEAR_HARD_REG_BIT (hard_regs_live, regno);
-      return;
-    }
-  a = ira_curr_regno_allocno_map[regno];
-  if (a == NULL)
-    return;
   p = ALLOCNO_LIVE_RANGES (a);
   ira_assert (p != NULL);
   p->finish = curr_point;
   update_allocno_pressure_excess_length (a);
+  sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
 }
 
 /* The current register pressures for each cover class for the current
    basic block.  */
 static int curr_reg_pressure[N_REG_CLASSES];
 
-/* Mark allocno A as currently living and update current register
-   pressure, maximal register pressure for the current BB, start point
-   of the register pressure excess, and conflicting hard registers of
-   A.  */
+/* Record that register pressure for COVER_CLASS increased by N
+   registers.  Update the current register pressure, maximal register
+   pressure for the current BB and the start point of the register
+   pressure excess.  */
 static void
-set_allocno_live (ira_allocno_t a)
+inc_register_pressure (enum reg_class cover_class, int n)
 {
   int i;
-  enum reg_class cover_class, cl;
+  enum reg_class cl;
 
-  /* Invalidate because it is referenced.  */
-  allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
-  if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
-    return;
-  sparseset_set_bit (allocnos_live, ALLOCNO_NUM (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);
   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)];
+      curr_reg_pressure[cl] += n;
       if (high_pressure_start_point[cl] < 0
 	  && (curr_reg_pressure[cl] > ira_available_class_regs[cl]))
 	high_pressure_start_point[cl] = curr_point;
@@ -195,110 +189,87 @@  set_allocno_live (ira_allocno_t a)
     }
 }
 
-/* Mark allocno A as currently not living and update current register
-   pressure, start point of the register pressure excess, and register
-   pressure excess length for living allocnos.  */
+/* Record that register pressure for COVER_CLASS has decreased by
+   NREGS registers; update current register pressure, start point of
+   the register pressure excess, and register pressure excess length
+   for living allocnos.  */
+
 static void
-clear_allocno_live (ira_allocno_t a)
+dec_register_pressure (enum reg_class cover_class, int nregs)
 {
   int i;
   unsigned int j;
-  enum reg_class cover_class, cl;
-  bool set_p;
+  enum reg_class cl;
+  bool set_p = false;
 
-  /* Invalidate because it is referenced.  */
-  allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
-  if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
+  for (i = 0;
+       (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+       i++)
     {
-      cover_class = ALLOCNO_COVER_CLASS (a);
-      set_p = false;
+      curr_reg_pressure[cl] -= nregs;
+      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++)
-	{
-	  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;
-
-	}
+	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));
 }
 
-/* Mark the register REG as live.  Store a 1 in hard_regs_live or
-   allocnos_live for this register or the corresponding allocno,
-   record how many consecutive hardware registers it actually
-   needs.  */
+/* Mark the pseudo register REGNO as live.  Update all information about
+   live ranges and register pressure.  */
 static void
-mark_reg_live (rtx reg)
+mark_pseudo_regno_live (int regno)
 {
-  int i, regno;
+  ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+  enum reg_class cl;
+  int nregs;
 
-  gcc_assert (REG_P (reg));
-  regno = REGNO (reg);
+  if (a == NULL)
+    return;
 
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    {
-      ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+  /* Invalidate because it is referenced.  */
+  allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
 
-      if (a != NULL)
-	{
-	  if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
-	    {
-	      /* Invalidate because it is referenced.  */
-	      allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
-	      return;
-	    }
-	  set_allocno_live (a);
-	}
-      make_regno_born (regno);
-    }
-  else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
+  if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
+    return;
+
+  cl = ALLOCNO_COVER_CLASS (a);
+  nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
+  inc_register_pressure (cl, nregs);
+  make_allocno_born (a);
+}
+
+/* Mark the hard register REG as live.  Store a 1 in hard_regs_live
+   for this register, record how many consecutive hardware registers
+   it actually needs.  */
+static void
+mark_hard_reg_live (rtx reg)
+{
+  int regno = REGNO (reg);
+
+  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, cl;
 
       while (regno < last)
 	{
 	  if (! TEST_HARD_REG_BIT (hard_regs_live, regno)
 	      && ! TEST_HARD_REG_BIT (eliminable_regset, regno))
 	    {
-	      cover_class = ira_hard_regno_cover_class[regno];
-	      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]))
-		    high_pressure_start_point[cl] = curr_point;
-		}
-	      make_regno_born (regno);
-	      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];
-		}
+	      enum reg_class cover_class = ira_hard_regno_cover_class[regno];
+	      inc_register_pressure (cover_class, 1);
+	      make_hard_regno_born (regno);
 	    }
 	  regno++;
 	}
@@ -314,74 +285,55 @@  mark_ref_live (df_ref ref)
   reg = DF_REF_REG (ref);
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
-  mark_reg_live (reg);
+  if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+    mark_pseudo_regno_live (REGNO (reg));
+  else
+    mark_hard_reg_live (reg);
 }
 
-/* Mark the register REG as dead.  Store a 0 in hard_regs_live or
-   allocnos_live for the register.  */
+/* Mark the pseudo register REGNO as dead.  Update all information about
+   live ranges and register pressure.  */
 static void
-mark_reg_dead (rtx reg)
+mark_pseudo_regno_dead (int regno)
 {
-  int regno;
+  ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+  enum reg_class cl;
+  int nregs;
 
-  gcc_assert (REG_P (reg));
-  regno = REGNO (reg);
+  if (a == NULL)
+    return;
 
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    {
-      ira_allocno_t a = ira_curr_regno_allocno_map[regno];
+  /* Invalidate because it is referenced.  */
+  allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
 
-      if (a != NULL)
-	{
-	  if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
-	    {
-	      /* Invalidate because it is referenced.  */
-	      allocno_saved_at_call[ALLOCNO_NUM (a)] = 0;
-	      return;
-	    }
-	  clear_allocno_live (a);
-	}
-      make_regno_dead (regno);
-    }
-  else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
+  if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
+    return;
+
+  cl = ALLOCNO_COVER_CLASS (a);
+  nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
+  dec_register_pressure (cl, nregs);
+
+  make_allocno_dead (a);
+}
+
+/* Mark the hard register REG as dead.  Store a 0 in hard_regs_live
+   for the register.  */
+static void
+mark_hard_reg_dead (rtx reg)
+{
+  int regno = REGNO (reg);
+
+  if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
     {
-      int i;
-      unsigned int j;
       int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-      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];
-	      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)
-		{
-		  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);
+	      enum reg_class cover_class = ira_hard_regno_cover_class[regno];
+	      dec_register_pressure (cover_class, 1);
+	      make_hard_regno_dead (regno);
 	    }
 	  regno++;
 	}
@@ -402,7 +354,10 @@  mark_ref_dead (df_ref def)
   reg = DF_REF_REG (def);
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
-  mark_reg_dead (reg);
+  if (REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+    mark_pseudo_regno_dead (REGNO (reg));
+  else
+    mark_hard_reg_dead (reg);
 }
 
 /* Make pseudo REG conflicting with pseudo DREG, if the 1st pseudo
@@ -427,10 +382,10 @@  make_pseudo_conflict (rtx reg, enum reg_
   if (advance_p)
     curr_point++;
 
-  mark_reg_live (reg);
-  mark_reg_live (dreg);
-  mark_reg_dead (reg);
-  mark_reg_dead (dreg);
+  mark_pseudo_regno_live (REGNO (reg));
+  mark_pseudo_regno_live (REGNO (dreg));
+  mark_pseudo_regno_dead (REGNO (reg));
+  mark_pseudo_regno_dead (REGNO (dreg));
 
   return false;
 }
@@ -961,15 +916,7 @@  process_bb_node_lives (ira_loop_tree_nod
 	      }
 	  }
       EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
-	{
-	  ira_allocno_t a = ira_curr_regno_allocno_map[j];
-
-	  if (a == NULL)
-	    continue;
-	  ira_assert (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)));
-	  set_allocno_live (a);
-	  make_regno_born (j);
-	}
+	mark_pseudo_regno_live (j);
 
       freq = REG_FREQ_FROM_BB (bb);
       if (freq == 0)
@@ -1137,7 +1084,7 @@  process_bb_node_lives (ira_loop_tree_nod
 	    unsigned int regno = EH_RETURN_DATA_REGNO (j);
 	    if (regno == INVALID_REGNUM)
 	      break;
-	    make_regno_born (regno);
+	    make_hard_regno_born (regno);
 	  }
 #endif
 
@@ -1155,7 +1102,7 @@  process_bb_node_lives (ira_loop_tree_nod
 	      ALLOCNO_TOTAL_NO_STACK_REG_P (ira_allocnos[px]) = true;
 	    }
 	  for (px = FIRST_STACK_REG; px <= LAST_STACK_REG; px++)
-	    make_regno_born (px);
+	    make_hard_regno_born (px);
 #endif
 	  /* No need to record conflicts for call clobbered regs if we
 	     have nonlocal labels around, as we don't ever try to
@@ -1163,13 +1110,11 @@  process_bb_node_lives (ira_loop_tree_nod
 	  if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
 	    for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
 	      if (call_used_regs[px])
-		make_regno_born (px);
+		make_hard_regno_born (px);
 	}
 
       EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i)
-	{
-	  make_regno_dead (ALLOCNO_REGNO (ira_allocnos[i]));
-	}
+	make_allocno_dead (ira_allocnos[i]);
 
       curr_point++;