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]

Add convenience functions for compound hard registers


I'm about to submit a fix for a bug in which we only tested REGNO (X)
instead of every register in X.  I've come across problems like that
before, and I think part of the reason they keep cropping up is that
we don't have many convenience functions for dealing with multi-register
quantities.

This patch adds functions and macros for commonly-occuring constructs:

   end_hard_regno (mode, regno)
      regno + hard_regno_nregs[regno][mode]

   END_HARD_REGNO (rtx x)
      an exclusive upper bound on the registers in hard REG X.

   END_REGNO (rtx x)
      likewise hard or pseudo REG X.

   add_to_hard_reg_set (set, mode, regno)
      Add (reg:MODE REGNO) to SET

   remove_from_hard_reg_set (set, mode, regno)
      Remove (reg:MODE REGNO) from SET

   in_hard_reg_set_p (set, mode, regno)
      Return true if (reg:MODE REGNO) is contained in SET

   overlaps_hard_reg_set_p (set, mode, regno)
      Return true if (reg:MODE REGNO) overlaps SET

gcc isn't really consistent about whether the regno should come before
or after the mode; both are widely used.  I put the mode first because
that mirrors gen_rtx_REG.

I kept the END_HARD_REGNO and END_REGNO as macros for consistency with
REGNO.  I hope it's OK to have both END_HARD_REGNO and end_hard_regno;
I think it feels quite natural in practice.

I went through gcc/ to find places that could trivially use the new
constructs.  I sometimes converted inclusive bounds to exclusive bounds,
but didn't otherwise want to do anything that didn't seem totally obvious.

This exercise showed up a bug in mode-switching.c:reg_dies; it takes
a "HARD_REG_SET" argument rather than a "HARD_REG_SET *" argument,
so the caller's set is not modified for sets defined as follows:

#define HARD_REG_SET HARD_REG_ELT_TYPE

I realise that this patch will probably interfere with the dataflow
merge, so I'd be happy to hold back the *.c changes until after that,
then refresh.  I only really included them here to show that the
new constructs would be useful.

I'd like to apply the *.h part though, because it's needed by
the aforementioned bug fix.

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also
regression-tested on sh-elf (,-m2,-m3,-m4,-m4/-ml) and built
on arm-elf.  OK to install?

Richard


gcc/
	* regs.h (end_hard_regno): New function.
	(END_HARD_REGNO, END_REGNO): New macros.
	(add_to_hard_reg_set): New function.
	(remove_from_hard_reg_set): Likewise.
	(in_hard_reg_set_p): Likewise.
	(overlaps_hard_reg_set_p): Likewise.
	* bt-load.c (find_btr_reference): Use overlaps_hard_reg_set_p.
	(note_btr_set): Use END_HARD_REGNO.
	* caller-save.c (setup_save_areas): Use end_hard_regno.
	(mark_set_regs): Use END_HARD_REGNO.
	(add_stored_regs): Use end_hard_regno.
	(mark_referenced_regs): Use add_to_hard_reg_set.
	* combine.c (update_table_tick): Use END_REGNO.
	(record_value_for_reg): Likewise.
	(record_dead_and_set_regs): Likewise.
	(get_last_value_validate): Likewise.
	(use_crosses_set_p): Likewise.
	(reg_dead_at_p_1): Likewise.
	(reg_dead_at_p): Likewise.
	(mark_used_regs_combine): Use add_to_hard_reg_set.
	(move_deaths): Use END_HARD_REGNO.
	(reg_bitfield_target_p): Use end_hard_regno.
	(distribute_notes): Use END_HARD_REGNO.
	* cse.c (mention_regs): Use END_REGNO.
	(insert): Use add_to_hard_reg_set.
	(invalidate): Use END_HARD_REGNO.
	(invalidate_for_call): Likewise.
	(exp_equiv_p): Use END_REGNO.
	(cse_insn): Likewise.
	* cselib.c (cselib_invalidate_regno): Use end_hard_regno.
	* df-problems.c (df_lr_bb_local_compute): Likewise.  Use an
	exclusive upper loop bound.
	(df_urec_mark_reg_change): Use END_HARD_REGNO.
	* df-scan.c (df_ref_record): Use END_HARD_REGNO.
	(df_insn_refs_record): Use END_REGNO and an exclusive upper loop bound.
	* flow.c (mark_set_1, mark_used_reg): Use END_REGNO.
	* function.c (keep_stack_depressed): Use end_hard_regno.
	* global.c (global_alloc): Use end_hard_regno.
	(find_reg): Likewise.
	(mark_reg_store): Likewise.
	(mark_reg_conflicts): Likewise.
	(mark_reg_death): Use remove_from_hard_reg_set.
	(mark_reg_live_nc): Use add_to_hard_reg_set.
	(set_preference): Use end_hard_regno.
	* local-alloc.c (mark_life): Use add_to_hard_reg_set and
	remove_from_hard_reg_set.
	(post_mark_life): Use add_to_hard_reg_set.
	* mode-switching.c (reg_dies): Change type of second argument to
	"HARD_REG_SET *".  Use remove_from_hard_reg_set.
	(reg_becomes_live): Use add_to_hard_reg_set.
	(optimize_mode_switching): Update calls to reg_dies.
	* recog.c (reg_fits_class_p): Use in_hard_reg_set_p.
	(peep2_find_free_register): Use add_to_hard_reg_set.
	* reg-stack.c (convert_regs_exit): Use END_HARD_REGNO.
	* regclass.c (record_reg_classes): Use in_hard_reg_set_p.
	* regrename.c (note_sets): Use add_to_hard_reg_set.
	(clear_dead_regs): Use remove_from_hard_reg_set.
	(regrename_optimize): Use add_to_hard_reg_set.
	(find_oldest_value_reg): Use in_hard_reg_set_p.
	* reload.c (push_reload): Use in_hard_reg_set_p and end_hard_regno.
	(hard_reg_set_here_p): Use end_hard_regno.
	(decompose): Likewise.
	(reg_overlap_mentioned_for_reload_p): Use END_HARD_REGNO.
	(find_equiv_reg): Use in_hard_reg_set_p and end_hard_regno.
	* reload1.c (compute_use_by_pseudos): Use add_to_hard_reg_set.
	(mark_home_live): Use end_hard_regno.
	(spill_hard_reg): Likewise.
	(clear_reload_reg_in_use): Likewise.
	* reorg.c (delete_prior_computation): Use END_REGNO.
	* resource.c (update_live_status): Use END_HARD_REGNO.
	(mark_referenced_resources): Use add_to_hard_reg_set.
	(mark_set_resources): Likewise.
	(mark_target_live_regs): Likewise.  Use remove_from_hard_reg_set.
	* rtlanal.c (refers_to_regno_p): Use END_REGNO.
	(reg_overlap_mentioned_p): Likewise.
	(dead_or_set_p): Likewise.  Use an exclusive upper loop bound.
	(covers_regno_no_parallel_p): Use END_REGNO.
	(find_regno_note): Likewise.
	(find_reg_fusage): Use END_HARD_REGNO.
	* stmt.c (decl_overlaps_hard_reg_set_p): Use overlaps_hard_reg_set_p.
	* var-tracking.c (emit_note_insn_var_location): Use end_hard_regno.

Index: gcc/regs.h
===================================================================
--- gcc/regs.h	2007-05-21 19:58:41.000000000 +0100
+++ gcc/regs.h	2007-05-21 20:05:37.000000000 +0100
@@ -243,4 +243,88 @@ extern void clear_reg_info_regno (unsign
 /* Specify number of hard registers given machine mode occupy.  */
 extern unsigned char hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
 
+/* Return an exclusive upper bound on the registers occupied by hard
+   register (reg:MODE REGNO).  */
+
+static inline unsigned int
+end_hard_regno (enum machine_mode mode, unsigned int regno)
+{
+  return regno + hard_regno_nregs[regno][(int) mode];
+}
+
+/* Likewise for hard register X.  */
+
+#define END_HARD_REGNO(X) end_hard_regno (GET_MODE (X), REGNO (X))
+
+/* Likewise for hard or pseudo register X.  */
+
+#define END_REGNO(X) (HARD_REGISTER_P (X) ? END_HARD_REGNO (X) : REGNO (X) + 1)
+
+/* Add to REGS all the registers required to store a value of mode MODE
+   in register REGNO.  */
+
+static inline void
+add_to_hard_reg_set (HARD_REG_SET *regs, enum machine_mode mode,
+		     unsigned int regno)
+{
+  unsigned int end_regno;
+
+  end_regno = end_hard_regno (mode, regno);
+  do
+    SET_HARD_REG_BIT (*regs, regno);
+  while (++regno < end_regno);
+}
+
+/* Likewise, but remove the registers.  */
+
+static inline void
+remove_from_hard_reg_set (HARD_REG_SET *regs, enum machine_mode mode,
+			  unsigned int regno)
+{
+  unsigned int end_regno;
+
+  end_regno = end_hard_regno (mode, regno);
+  do
+    CLEAR_HARD_REG_BIT (*regs, regno);
+  while (++regno < end_regno);
+}
+
+/* Return true if REGS contains the whole of (reg:MODE REGNO).  */
+
+static inline bool
+in_hard_reg_set_p (const HARD_REG_SET regs, enum machine_mode mode,
+		   unsigned int regno)
+{
+  unsigned int end_regno;
+
+  if (!TEST_HARD_REG_BIT (regs, regno))
+    return false;
+
+  end_regno = end_hard_regno (mode, regno);
+  while (++regno < end_regno)
+    if (!TEST_HARD_REG_BIT (regs, regno))
+      return false;
+
+  return true;
+}
+
+/* Return true if (reg:MODE REGNO) includes an element of REGS.  */
+
+static inline bool
+overlaps_hard_reg_set_p (const HARD_REG_SET regs, enum machine_mode mode,
+			 unsigned int regno)
+{
+  unsigned int end_regno;
+
+  if (TEST_HARD_REG_BIT (regs, regno))
+    return true;
+
+  end_regno = end_hard_regno (mode, regno);
+  while (++regno < end_regno)
+    if (TEST_HARD_REG_BIT (regs, regno))
+      return true;
+
+  return false;
+}
+
 #endif /* GCC_REGS_H */
Index: gcc/bt-load.c
===================================================================
--- gcc/bt-load.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/bt-load.c	2007-05-21 20:05:36.000000000 +0100
@@ -193,20 +193,17 @@ basic_block_freq (basic_block bb)
 find_btr_reference (rtx *px, void *preg)
 {
   rtx x;
-  int regno, i;
 
   if (px == preg)
     return -1;
   x = *px;
   if (!REG_P (x))
     return 0;
-  regno = REGNO (x);
-  for (i = hard_regno_nregs[regno][GET_MODE (x)] - 1; i >= 0; i--)
-    if (TEST_HARD_REG_BIT (all_btrs, regno+i))
-      {
-	btr_reference_found = px;
-	return 1;
-      }
+  if (overlaps_hard_reg_set_p (all_btrs, GET_MODE (x), REGNO (x)))
+    {
+      btr_reference_found = px;
+      return 1;
+    }
   return -1;
 }
 
@@ -433,7 +430,7 @@ note_btr_set (rtx dest, rtx set ATTRIBUT
   if (!REG_P (dest))
     return;
   regno = REGNO (dest);
-  end_regno = regno + hard_regno_nregs[regno][GET_MODE (dest)];
+  end_regno = END_HARD_REGNO (dest);
   for (; regno < end_regno; regno++)
     if (TEST_HARD_REG_BIT (all_btrs, regno))
       {
Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/caller-save.c	2007-05-21 20:05:36.000000000 +0100
@@ -296,7 +296,7 @@ setup_save_areas (void)
       {
 	unsigned int regno = reg_renumber[i];
 	unsigned int endregno
-	  = regno + hard_regno_nregs[regno][GET_MODE (regno_reg_rtx[i])];
+	  = end_hard_regno (GET_MODE (regno_reg_rtx[i]), regno);
 
 	for (r = regno; r < endregno; r++)
 	  if (call_used_regs[r])
@@ -496,7 +496,6 @@ save_call_clobbered_regs (void)
 mark_set_regs (rtx reg, rtx setter ATTRIBUTE_UNUSED, void *data)
 {
   int regno, endregno, i;
-  enum machine_mode mode = GET_MODE (reg);
   HARD_REG_SET *this_insn_sets = data;
 
   if (GET_CODE (reg) == SUBREG)
@@ -511,7 +510,7 @@ mark_set_regs (rtx reg, rtx setter ATTRI
 	   && REGNO (reg) < FIRST_PSEUDO_REGISTER)
     {
       regno = REGNO (reg);
-      endregno = regno + hard_regno_nregs[regno][mode];
+      endregno = END_HARD_REGNO (reg);
     }
   else
     return;
@@ -551,7 +550,7 @@ add_stored_regs (rtx reg, rtx setter, vo
 	return;
 
       regno = REGNO (reg) + offset;
-      endregno = regno + hard_regno_nregs[regno][mode];
+      endregno = end_hard_regno (mode, regno);
     }
 
   for (i = regno; i < endregno; i++)
@@ -598,11 +597,7 @@ mark_referenced_regs (rtx x)
 		       : reg_renumber[regno]);
 
       if (hardregno >= 0)
-	{
-	  int nregs = hard_regno_nregs[hardregno][GET_MODE (x)];
-	  while (nregs-- > 0)
-	    SET_HARD_REG_BIT (referenced_regs, hardregno + nregs);
-	}
+	add_to_hard_reg_set (&referenced_regs, GET_MODE (x), hardregno);
       /* If this is a pseudo that did not get a hard register, scan its
 	 memory location, since it might involve the use of another
 	 register, which might be saved.  */
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/combine.c	2007-05-21 20:05:36.000000000 +0100
@@ -10796,9 +10796,7 @@ update_table_tick (rtx x)
   if (code == REG)
     {
       unsigned int regno = REGNO (x);
-      unsigned int endregno
-	= regno + (regno < FIRST_PSEUDO_REGISTER
-		   ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
+      unsigned int endregno = END_REGNO (x);
       unsigned int r;
 
       for (r = regno; r < endregno; r++)
@@ -10858,9 +10856,7 @@ update_table_tick (rtx x)
 record_value_for_reg (rtx reg, rtx insn, rtx value)
 {
   unsigned int regno = REGNO (reg);
-  unsigned int endregno
-    = regno + (regno < FIRST_PSEUDO_REGISTER
-	       ? hard_regno_nregs[regno][GET_MODE (reg)] : 1);
+  unsigned int endregno = END_REGNO (reg);
   unsigned int i;
 
   /* If VALUE contains REG and we have a previous value for REG, substitute
@@ -11029,10 +11025,7 @@ record_dead_and_set_regs (rtx insn)
 	  && REG_P (XEXP (link, 0)))
 	{
 	  unsigned int regno = REGNO (XEXP (link, 0));
-	  unsigned int endregno
-	    = regno + (regno < FIRST_PSEUDO_REGISTER
-		       ? hard_regno_nregs[regno][GET_MODE (XEXP (link, 0))]
-		       : 1);
+	  unsigned int endregno = END_REGNO (XEXP (link, 0));
 
 	  for (i = regno; i < endregno; i++)
 	    reg_stat[i].last_death = insn;
@@ -11231,9 +11224,7 @@ get_last_value_validate (rtx *loc, rtx i
   if (REG_P (x))
     {
       unsigned int regno = REGNO (x);
-      unsigned int endregno
-	= regno + (regno < FIRST_PSEUDO_REGISTER
-		   ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
+      unsigned int endregno = END_REGNO (x);
       unsigned int j;
 
       for (j = regno; j < endregno; j++)
@@ -11392,8 +11383,7 @@ use_crosses_set_p (rtx x, int from_cuid)
   if (code == REG)
     {
       unsigned int regno = REGNO (x);
-      unsigned endreg = regno + (regno < FIRST_PSEUDO_REGISTER
-				 ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
+      unsigned endreg = END_REGNO (x);
 
 #ifdef PUSH_ROUNDING
       /* Don't allow uses of the stack pointer to be moved,
@@ -11449,9 +11439,7 @@ reg_dead_at_p_1 (rtx dest, rtx x, void *
     return;
 
   regno = REGNO (dest);
-  endregno = regno + (regno < FIRST_PSEUDO_REGISTER
-		      ? hard_regno_nregs[regno][GET_MODE (dest)] : 1);
-
+  endregno = END_REGNO (dest);
   if (reg_dead_endregno > regno && reg_dead_regno < endregno)
     reg_dead_flag = (GET_CODE (x) == CLOBBER) ? 1 : -1;
 }
@@ -11472,10 +11460,7 @@ reg_dead_at_p (rtx reg, rtx insn)
 
   /* Set variables for reg_dead_at_p_1.  */
   reg_dead_regno = REGNO (reg);
-  reg_dead_endregno = reg_dead_regno + (reg_dead_regno < FIRST_PSEUDO_REGISTER
-					? hard_regno_nregs[reg_dead_regno]
-							  [GET_MODE (reg)]
-					: 1);
+  reg_dead_endregno = END_REGNO (reg);
 
   reg_dead_flag = 0;
 
@@ -11564,8 +11549,6 @@ mark_used_regs_combine (rtx x)
 	 If so, mark all of them just like the first.  */
       if (regno < FIRST_PSEUDO_REGISTER)
 	{
-	  unsigned int endregno, r;
-
 	  /* None of this applies to the stack, frame or arg pointers.  */
 	  if (regno == STACK_POINTER_REGNUM
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
@@ -11577,9 +11560,7 @@ mark_used_regs_combine (rtx x)
 	      || regno == FRAME_POINTER_REGNUM)
 	    return;
 
-	  endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
-	  for (r = regno; r < endregno; r++)
-	    SET_HARD_REG_BIT (newpat_used_regs, r);
+	  add_to_hard_reg_set (&newpat_used_regs, GET_MODE (x), regno);
 	}
       return;
 
@@ -11704,11 +11685,8 @@ move_deaths (rtx x, rtx maybe_kill_insn,
 		  > GET_MODE_SIZE (GET_MODE (x))))
 	    {
 	      unsigned int deadregno = REGNO (XEXP (note, 0));
-	      unsigned int deadend
-		= (deadregno + hard_regno_nregs[deadregno]
-					       [GET_MODE (XEXP (note, 0))]);
-	      unsigned int ourend
-		= regno + hard_regno_nregs[regno][GET_MODE (x)];
+	      unsigned int deadend = END_HARD_REGNO (XEXP (note, 0));
+	      unsigned int ourend = END_HARD_REGNO (x);
 	      unsigned int i;
 
 	      for (i = deadregno; i < deadend; i++)
@@ -11731,8 +11709,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
 		   && regno < FIRST_PSEUDO_REGISTER
 		   && hard_regno_nregs[regno][GET_MODE (x)] > 1)
 	    {
-	      unsigned int ourend
-		= regno + hard_regno_nregs[regno][GET_MODE (x)];
+	      unsigned int ourend = END_HARD_REGNO (x);
 	      unsigned int i, offset;
 	      rtx oldnotes = 0;
 
@@ -11850,8 +11827,8 @@ reg_bitfield_target_p (rtx x, rtx body)
       if (tregno >= FIRST_PSEUDO_REGISTER || regno >= FIRST_PSEUDO_REGISTER)
 	return target == x;
 
-      endtregno = tregno + hard_regno_nregs[tregno][GET_MODE (target)];
-      endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
+      endtregno = end_hard_regno (GET_MODE (target), tregno);
+      endregno = end_hard_regno (GET_MODE (x), regno);
 
       return endregno > tregno && regno < endtregno;
     }
@@ -12352,9 +12329,7 @@ distribute_notes (rtx notes, rtx from_in
 	      if (place && regno < FIRST_PSEUDO_REGISTER
 		  && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] > 1)
 		{
-		  unsigned int endregno
-		    = regno + hard_regno_nregs[regno]
-					      [GET_MODE (XEXP (note, 0))];
+		  unsigned int endregno = END_HARD_REGNO (XEXP (note, 0));
 		  int all_used = 1;
 		  unsigned int i;
 
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/cse.c	2007-05-21 20:11:55.000000000 +0100
@@ -1045,9 +1045,7 @@ mention_regs (rtx x)
   if (code == REG)
     {
       unsigned int regno = REGNO (x);
-      unsigned int endregno
-	= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-		   : hard_regno_nregs[regno][GET_MODE (x)]);
+      unsigned int endregno = END_REGNO (x);
       unsigned int i;
 
       for (i = regno; i < endregno; i++)
@@ -1429,14 +1427,7 @@ insert (rtx x, struct table_elt *classp,
 
   /* If X is a hard register, show it is being put in the table.  */
   if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
-    {
-      unsigned int regno = REGNO (x);
-      unsigned int endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
-      unsigned int i;
-
-      for (i = regno; i < endregno; i++)
-	SET_HARD_REG_BIT (hard_regs_in_table, i);
-    }
+    add_to_hard_reg_set (&hard_regs_in_table, GET_MODE (x), REGNO (x));
 
   /* Put an element for X into the right hash bucket.  */
 
@@ -1739,8 +1730,7 @@ invalidate (rtx x, enum machine_mode ful
 	  {
 	    HOST_WIDE_INT in_table
 	      = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
-	    unsigned int endregno
-	      = regno + hard_regno_nregs[regno][GET_MODE (x)];
+	    unsigned int endregno = END_HARD_REGNO (x);
 	    unsigned int tregno, tendregno, rn;
 	    struct table_elt *p, *next;
 
@@ -1766,8 +1756,7 @@ invalidate (rtx x, enum machine_mode ful
 		      continue;
 
 		    tregno = REGNO (p->exp);
-		    tendregno
-		      = tregno + hard_regno_nregs[tregno][GET_MODE (p->exp)];
+		    tendregno = END_HARD_REGNO (p->exp);
 		    if (tendregno > regno && tregno < endregno)
 		      remove_from_table (p, hash);
 		  }
@@ -1978,7 +1967,7 @@ invalidate_for_call (void)
 	    continue;
 
 	  regno = REGNO (p->exp);
-	  endregno = regno + hard_regno_nregs[regno][GET_MODE (p->exp)];
+	  endregno = END_HARD_REGNO (p->exp);
 
 	  for (i = regno; i < endregno; i++)
 	    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
@@ -2447,9 +2436,7 @@ exp_equiv_p (rtx x, rtx y, int validate,
 	{
 	  unsigned int regno = REGNO (y);
 	  unsigned int i;
-	  unsigned int endregno
-	    = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-		       : hard_regno_nregs[regno][GET_MODE (y)]);
+	  unsigned int endregno = END_REGNO (y);
 
 	  /* If the quantities are not the same, the expressions are not
 	     equivalent.  If there are and we are not to validate, they
@@ -5380,9 +5367,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 		 but it knows that reg_tick has been incremented, and
 		 it leaves reg_in_table as -1 .  */
 	      unsigned int regno = REGNO (x);
-	      unsigned int endregno
-		= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-			   : hard_regno_nregs[regno][GET_MODE (x)]);
+	      unsigned int endregno = END_REGNO (x);
 	      unsigned int i;
 
 	      for (i = regno; i < endregno; i++)
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/cselib.c	2007-05-21 20:05:37.000000000 +0100
@@ -1029,7 +1029,7 @@ cselib_invalidate_regno (unsigned int re
       else
 	i = regno - max_value_regs;
 
-      endregno = regno + hard_regno_nregs[regno][mode];
+      endregno = end_hard_regno (mode, regno);
     }
   else
     {
@@ -1050,7 +1050,7 @@ cselib_invalidate_regno (unsigned int re
 	  unsigned int this_last = i;
 
 	  if (i < FIRST_PSEUDO_REGISTER && v != NULL)
-	    this_last += hard_regno_nregs[i][GET_MODE (v->val_rtx)] - 1;
+	    this_last = end_hard_regno (GET_MODE (v->val_rtx), i) - 1;
 
 	  if (this_last < regno || v == NULL)
 	    {
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/df-problems.c	2007-05-21 20:05:37.000000000 +0100
@@ -1510,9 +1510,9 @@ df_lr_bb_local_compute (struct dataflow 
 		  && dregno < FIRST_PSEUDO_REGISTER)
 		{
 		  unsigned int i;
-		  unsigned int end = dregno 
-		    + hard_regno_nregs[dregno][GET_MODE (DF_REF_REG (def))] - 1;
-		  for (i = dregno; i <= end; ++i)
+		  unsigned int end
+		    = end_hard_regno (GET_MODE (DF_REF_REG (def)), dregno);
+		  for (i = dregno; i < end; ++i)
 		    regs_asm_clobbered[i] = 1;
 		}
 	      /* If the def is to only part of the reg, it does
@@ -2259,12 +2259,10 @@ df_urec_mark_reg_change (rtx reg, rtx se
   if (!REG_P (reg))
     return;
   
-  
-  endregno = regno = REGNO (reg);
+  regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
     {
-      endregno +=hard_regno_nregs[regno][GET_MODE (reg)];
-      
+      endregno = END_HARD_REGNO (reg);
       for (i = regno; i < endregno; i++)
 	{
 	  bitmap_set_bit (bb_info->kill, i);
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/df-scan.c	2007-05-21 20:05:37.000000000 +0100
@@ -1093,11 +1093,10 @@ df_ref_record (struct dataflow *dflow, r
 	{
 	  regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
 					SUBREG_BYTE (reg), GET_MODE (reg));
-	  endregno = subreg_nregs (reg);
+	  endregno = regno + subreg_nregs (reg);
 	}
       else
-	endregno = hard_regno_nregs[regno][GET_MODE (reg)];
-      endregno += regno;
+	endregno = END_HARD_REGNO (reg);
 
       /*  If this is a multiword hardreg, we create some extra datastructures that 
 	  will enable us to easily build REG_DEAD and REG_UNUSED notes.  */
@@ -1564,15 +1563,13 @@ df_insn_refs_record (struct dataflow *df
 		  if (REG_P (XEXP (XEXP (note, 0), 0)))
 		    {
 		      rtx reg = XEXP (XEXP (note, 0), 0);
-		      int regno_last;
-		      int regno_first;
+		      int regno;
+		      int end_regno;
 		      int i;
 		
-		      regno_last = regno_first = REGNO (reg);
-		      if (regno_first < FIRST_PSEUDO_REGISTER)
-			regno_last 
-			  += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1;
-		      for (i = regno_first; i <= regno_last; i++)
+		      regno = REGNO (reg);
+		      end_regno = END_REGNO (reg);
+		      for (i = regno; i < end_regno; i++)
 			regs_ever_live[i] = 1;
 		    }
 		}
Index: gcc/flow.c
===================================================================
--- gcc/flow.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/flow.c	2007-05-21 20:05:37.000000000 +0100
@@ -2771,9 +2771,8 @@ mark_set_1 (struct propagate_block_info 
       /* Fall through.  */
 
     case REG:
-      regno_last = regno_first = REGNO (reg);
-      if (regno_first < FIRST_PSEUDO_REGISTER)
-	regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1;
+      regno_first = REGNO (reg);
+      regno_last = END_REGNO (reg) - 1;
       break;
 
     case SUBREG:
@@ -3756,9 +3755,8 @@ mark_used_reg (struct propagate_block_in
   unsigned int regno_first, regno_last, i;
   int some_was_live, some_was_dead, some_not_set;
 
-  regno_last = regno_first = REGNO (reg);
-  if (regno_first < FIRST_PSEUDO_REGISTER)
-    regno_last += hard_regno_nregs[regno_first][GET_MODE (reg)] - 1;
+  regno_first = REGNO (reg);
+  regno_last = END_REGNO (reg) - 1;
 
   /* Find out if any of this register is live after this instruction.  */
   some_was_live = some_was_dead = 0;
Index: gcc/function.c
===================================================================
--- gcc/function.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/function.c	2007-05-21 20:05:37.000000000 +0100
@@ -4771,8 +4771,7 @@ keep_stack_depressed (rtx insns)
 		    && !REGNO_REG_SET_P
 		         (EXIT_BLOCK_PTR->il.rtl->global_live_at_start, regno)
 		    && !refers_to_regno_p (regno,
-					   regno + hard_regno_nregs[regno]
-								   [Pmode],
+					   end_hard_regno (Pmode, regno),
 					   info.equiv_reg_src, NULL)
 		    && info.const_equiv[regno] == 0)
 		  break;
Index: gcc/global.c
===================================================================
--- gcc/global.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/global.c	2007-05-21 20:05:37.000000000 +0100
@@ -529,7 +529,7 @@ global_alloc (void)
     if (reg_renumber[i] >= 0)
       {
 	int regno = reg_renumber[i];
-	int endregno = regno + hard_regno_nregs[regno][PSEUDO_REGNO_MODE (i)];
+	int endregno = end_hard_regno (PSEUDO_REGNO_MODE (i), regno);
 	int j;
 
 	for (j = regno; j < endregno; j++)
@@ -1132,7 +1132,7 @@ find_reg (int num, HARD_REG_SET losers, 
 		  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
 	    {
 	      int j;
-	      int lim = regno + hard_regno_nregs[regno][mode];
+	      int lim = end_hard_regno (mode, regno);
 	      for (j = regno + 1;
 		   (j < lim
 		    && ! TEST_HARD_REG_BIT (used, j));
@@ -1177,7 +1177,7 @@ find_reg (int num, HARD_REG_SET losers, 
 				       REGNO_REG_CLASS (i))))
 	    {
 	      int j;
-	      int lim = i + hard_regno_nregs[i][mode];
+	      int lim = end_hard_regno (mode, i);
 	      for (j = i + 1;
 		   (j < lim
 		    && ! TEST_HARD_REG_BIT (used, j)
@@ -1213,7 +1213,7 @@ find_reg (int num, HARD_REG_SET losers, 
 				       REGNO_REG_CLASS (i))))
 	    {
 	      int j;
-	      int lim = i + hard_regno_nregs[i][mode];
+	      int lim = end_hard_regno (mode, i);
 	      for (j = i + 1;
 		   (j < lim
 		    && ! TEST_HARD_REG_BIT (used, j)
@@ -1339,7 +1339,7 @@ find_reg (int num, HARD_REG_SET losers, 
 		      {
 			int r = reg_renumber[k];
 			int endregno
-			  = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (k)];
+			  = end_hard_regno (PSEUDO_REGNO_MODE (k), r);
 
 			if (regno >= r && regno < endregno)
 			  {
@@ -1374,7 +1374,7 @@ find_reg (int num, HARD_REG_SET losers, 
 
       /* Make a set of the hard regs being allocated.  */
       CLEAR_HARD_REG_SET (this_reg);
-      lim = best_reg + hard_regno_nregs[best_reg][mode];
+      lim = end_hard_regno (mode, best_reg);
       for (j = best_reg; j < lim; j++)
 	{
 	  SET_HARD_REG_BIT (this_reg, j);
@@ -1555,7 +1555,7 @@ mark_reg_store (rtx reg, rtx setter, voi
   /* Handle hardware regs (and pseudos allocated to hard regs).  */
   if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
     {
-      int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
+      int last = end_hard_regno (GET_MODE (reg), regno);
       while (regno < last)
 	{
 	  record_one_conflict (regno);
@@ -1604,7 +1604,7 @@ mark_reg_conflicts (rtx reg)
   /* Handle hardware regs (and pseudos allocated to hard regs).  */
   if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
     {
-      int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
+      int last = end_hard_regno (GET_MODE (reg), regno);
       while (regno < last)
 	{
 	  record_one_conflict (regno);
@@ -1635,16 +1635,9 @@ mark_reg_death (rtx reg)
 
   /* Handle hardware regs (and pseudos allocated to hard regs).  */
   if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
-    {
-      /* Pseudo regs already assigned hardware regs are treated
-	 almost the same as explicit hardware regs.  */
-      int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-      while (regno < last)
-	{
-	  CLEAR_HARD_REG_BIT (hard_regs_live, regno);
-	  regno++;
-	}
-    }
+    /* Pseudo regs already assigned hardware regs are treated
+       almost the same as explicit hardware regs.  */
+    remove_from_hard_reg_set (&hard_regs_live, GET_MODE (reg), regno);
 }
 
 /* Mark hard reg REGNO as currently live, assuming machine mode MODE
@@ -1655,12 +1648,7 @@ mark_reg_death (rtx reg)
 static void
 mark_reg_live_nc (int regno, enum machine_mode mode)
 {
-  int last = regno + hard_regno_nregs[regno][mode];
-  while (regno < last)
-    {
-      SET_HARD_REG_BIT (hard_regs_live, regno);
-      regno++;
-    }
+  add_to_hard_reg_set (&hard_regs_live, mode, regno);
 }
 
 /* Try to set a preference for an allocno to a hard register.
@@ -1675,7 +1663,7 @@ mark_reg_live_nc (int regno, enum machin
 static void
 set_preference (rtx dest, rtx src)
 {
-  unsigned int src_regno, dest_regno;
+  unsigned int src_regno, dest_regno, end_regno;
   /* Amount to add to the hard regno for SRC, or subtract from that for DEST,
      to compensate for subregs in SRC or DEST.  */
   int offset = 0;
@@ -1747,9 +1735,8 @@ set_preference (rtx dest, rtx src)
 
 	  SET_REGBIT (hard_reg_preferences,
 		      reg_allocno[src_regno], dest_regno);
-	  for (i = dest_regno;
-	       i < dest_regno + hard_regno_nregs[dest_regno][GET_MODE (dest)];
-	       i++)
+	  end_regno = end_hard_regno (GET_MODE (dest), dest_regno);
+	  for (i = dest_regno; i < end_regno; i++)
 	    SET_REGBIT (hard_reg_full_preferences, reg_allocno[src_regno], i);
 	}
     }
@@ -1766,9 +1753,8 @@ set_preference (rtx dest, rtx src)
 
 	  SET_REGBIT (hard_reg_preferences,
 		      reg_allocno[dest_regno], src_regno);
-	  for (i = src_regno;
-	       i < src_regno + hard_regno_nregs[src_regno][GET_MODE (src)];
-	       i++)
+	  end_regno = end_hard_regno (GET_MODE (src), src_regno);
+	  for (i = src_regno; i < end_regno; i++)
 	    SET_REGBIT (hard_reg_full_preferences, reg_allocno[dest_regno], i);
 	}
     }
Index: gcc/local-alloc.c
===================================================================
--- gcc/local-alloc.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/local-alloc.c	2007-05-21 20:05:37.000000000 +0100
@@ -2363,13 +2363,10 @@ find_free_reg (enum reg_class class, enu
 static void
 mark_life (int regno, enum machine_mode mode, int life)
 {
-  int j = hard_regno_nregs[regno][mode];
   if (life)
-    while (--j >= 0)
-      SET_HARD_REG_BIT (regs_live, regno + j);
+    add_to_hard_reg_set (&regs_live, mode, regno);
   else
-    while (--j >= 0)
-      CLEAR_HARD_REG_BIT (regs_live, regno + j);
+    remove_from_hard_reg_set (&regs_live, mode, regno);
 }
 
 /* Mark register number REGNO (with machine-mode MODE) as live (if LIFE
@@ -2380,12 +2377,10 @@ mark_life (int regno, enum machine_mode 
 post_mark_life (int regno, enum machine_mode mode, int life, int birth,
 		int death)
 {
-  int j = hard_regno_nregs[regno][mode];
   HARD_REG_SET this_reg;
 
   CLEAR_HARD_REG_SET (this_reg);
-  while (--j >= 0)
-    SET_HARD_REG_BIT (this_reg, regno + j);
+  add_to_hard_reg_set (&this_reg, mode, regno);
 
   if (life)
     while (birth < death)
Index: gcc/mode-switching.c
===================================================================
--- gcc/mode-switching.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/mode-switching.c	2007-05-21 20:05:37.000000000 +0100
@@ -92,7 +92,7 @@ struct bb_info
 
 static struct seginfo * new_seginfo (int, rtx, int, HARD_REG_SET);
 static void add_seginfo (struct bb_info *, struct seginfo *);
-static void reg_dies (rtx, HARD_REG_SET);
+static void reg_dies (rtx, HARD_REG_SET *);
 static void reg_becomes_live (rtx, rtx, void *);
 static void make_preds_opaque (basic_block, int);
 
@@ -160,18 +160,16 @@ make_preds_opaque (basic_block b, int j)
 /* Record in LIVE that register REG died.  */
 
 static void
-reg_dies (rtx reg, HARD_REG_SET live)
+reg_dies (rtx reg, HARD_REG_SET *live)
 {
-  int regno, nregs;
+  int regno;
 
   if (!REG_P (reg))
     return;
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    for (nregs = hard_regno_nregs[regno][GET_MODE (reg)] - 1; nregs >= 0;
-	 nregs--)
-      CLEAR_HARD_REG_BIT (live, regno + nregs);
+    remove_from_hard_reg_set (live, GET_MODE (reg), regno);
 }
 
 /* Record in LIVE that register REG became live.
@@ -180,7 +178,7 @@ reg_dies (rtx reg, HARD_REG_SET live)
 static void
 reg_becomes_live (rtx reg, rtx setter ATTRIBUTE_UNUSED, void *live)
 {
-  int regno, nregs;
+  int regno;
 
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
@@ -190,9 +188,7 @@ reg_becomes_live (rtx reg, rtx setter AT
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    for (nregs = hard_regno_nregs[regno][GET_MODE (reg)] - 1; nregs >= 0;
-	 nregs--)
-      SET_HARD_REG_BIT (* (HARD_REG_SET *) live, regno + nregs);
+    add_to_hard_reg_set ((HARD_REG_SET *) live, GET_MODE (reg), regno);
 }
 
 /* Make sure if MODE_ENTRY is defined the MODE_EXIT is defined
@@ -500,12 +496,12 @@ #define N_ENTITIES ARRAY_SIZE (num_modes
 		  /* Update LIVE_NOW.  */
 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
 		    if (REG_NOTE_KIND (link) == REG_DEAD)
-		      reg_dies (XEXP (link, 0), live_now);
+		      reg_dies (XEXP (link, 0), &live_now);
 
 		  note_stores (PATTERN (insn), reg_becomes_live, &live_now);
 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
 		    if (REG_NOTE_KIND (link) == REG_UNUSED)
-		      reg_dies (XEXP (link, 0), live_now);
+		      reg_dies (XEXP (link, 0), &live_now);
 		}
 	    }
 
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/recog.c	2007-05-21 20:05:37.000000000 +0100
@@ -2713,21 +2713,9 @@ reg_fits_class_p (rtx operand, enum reg_
   if (cl == NO_REGS)
     return 0;
 
-  if (regno < FIRST_PSEUDO_REGISTER
-      && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
-			    regno + offset))
-    {
-      int sr;
-      regno += offset;
-      for (sr = hard_regno_nregs[regno][mode] - 1;
-	   sr > 0; sr--)
-	if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
-				 regno + sr))
-	  break;
-      return sr == 0;
-    }
-
-  return 0;
+  return (regno < FIRST_PSEUDO_REGISTER
+	  && in_hard_reg_set_p (reg_class_contents[(int) cl],
+				mode, regno + offset));
 }
 
 /* Split single instruction.  Helper function for split_all_insns and
@@ -3054,8 +3042,7 @@ peep2_find_free_register (int from, int 
 	}
       if (success)
 	{
-	  for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--)
-	    SET_HARD_REG_BIT (*reg_set, regno + j);
+	  add_to_hard_reg_set (reg_set, mode, regno);
 
 	  /* Start the next search with the next register.  */
 	  if (++raw_regno >= FIRST_PSEUDO_REGISTER)
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/reg-stack.c	2007-05-21 20:05:37.000000000 +0100
@@ -2625,8 +2625,7 @@ convert_regs_exit (void)
   if (retvalue)
     {
       value_reg_low = REGNO (retvalue);
-      value_reg_high = value_reg_low
-	+ hard_regno_nregs[value_reg_low][GET_MODE (retvalue)] - 1;
+      value_reg_high = END_HARD_REGNO (retvalue) - 1;
     }
 
   output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in;
Index: gcc/regclass.c
===================================================================
--- gcc/regclass.c	2007-05-21 19:59:34.000000000 +0100
+++ gcc/regclass.c	2007-05-21 20:05:37.000000000 +0100
@@ -1765,7 +1765,6 @@ record_reg_classes (int n_alts, int n_op
 	  unsigned int regno = REGNO (ops[!i]);
 	  enum machine_mode mode = GET_MODE (ops[!i]);
 	  int class;
-	  unsigned int nr;
 
 	  if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0
 	      && reg_pref[regno].prefclass != NO_REGS)
@@ -1784,18 +1783,9 @@ record_reg_classes (int n_alts, int n_op
 		{
 		  if (reg_class_size[class] == 1)
 		    op_costs[i].cost[class] = -1;
-		  else
-		    {
-		      for (nr = 0; nr < (unsigned) hard_regno_nregs[regno][mode]; nr++)
-			{
-			  if (! TEST_HARD_REG_BIT (reg_class_contents[class],
-						   regno + nr))
-			    break;
-			}
-
-		      if (nr == (unsigned) hard_regno_nregs[regno][mode])
-			op_costs[i].cost[class] = -1;
-		    }
+		  else if (in_hard_reg_set_p (reg_class_contents[class],
+					     mode, regno))
+		    op_costs[i].cost[class] = -1;
 		}
 	}
 }
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/regrename.c	2007-05-21 20:05:37.000000000 +0100
@@ -100,21 +100,14 @@ static void merge_overlapping_regs (basi
 note_sets (rtx x, rtx set ATTRIBUTE_UNUSED, void *data)
 {
   HARD_REG_SET *pset = (HARD_REG_SET *) data;
-  unsigned int regno;
-  int nregs;
 
   if (GET_CODE (x) == SUBREG)
     x = SUBREG_REG (x);
   if (!REG_P (x))
     return;
-  regno = REGNO (x);
-  nregs = hard_regno_nregs[regno][GET_MODE (x)];
-
   /* There must not be pseudos at this point.  */
-  gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
-
-  while (nregs-- > 0)
-    SET_HARD_REG_BIT (*pset, regno + nregs);
+  gcc_assert (HARD_REGISTER_P (x));
+  add_to_hard_reg_set (pset, GET_MODE (x), REGNO (x));
 }
 
 /* Clear all registers from *PSET for which a note of kind KIND can be found
@@ -128,14 +121,9 @@ clear_dead_regs (HARD_REG_SET *pset, enu
     if (REG_NOTE_KIND (note) == kind && REG_P (XEXP (note, 0)))
       {
 	rtx reg = XEXP (note, 0);
-	unsigned int regno = REGNO (reg);
-	int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
-
 	/* There must not be pseudos at this point.  */
-	gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
-
-	while (nregs-- > 0)
-	  CLEAR_HARD_REG_BIT (*pset, regno + nregs);
+	gcc_assert (HARD_REGISTER_P (reg));
+	remove_from_hard_reg_set (pset, GET_MODE (reg), REGNO (reg));
       }
 }
 
@@ -218,14 +206,9 @@ regrename_optimize (void)
       /* Don't clobber traceback for noreturn functions.  */
       if (frame_pointer_needed)
 	{
-	  int i;
-
-	  for (i = hard_regno_nregs[FRAME_POINTER_REGNUM][Pmode]; i--;)
-	    SET_HARD_REG_BIT (unavailable, FRAME_POINTER_REGNUM + i);
-
+	  add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-	  for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;)
-	    SET_HARD_REG_BIT (unavailable, HARD_FRAME_POINTER_REGNUM + i);
+	  add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
 #endif
 	}
 
@@ -1388,11 +1371,9 @@ find_oldest_value_reg (enum reg_class cl
     {
       enum machine_mode oldmode = vd->e[i].mode;
       rtx new;
-      unsigned int last;
 
-      for (last = i; last < i + hard_regno_nregs[i][mode]; last++)
-	if (!TEST_HARD_REG_BIT (reg_class_contents[cl], last))
-	  return NULL_RTX;
+      if (!in_hard_reg_set_p (reg_class_contents[cl], mode, i))
+	return NULL_RTX;
 
       new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
       if (new)
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/reload.c	2007-05-21 20:05:37.000000000 +0100
@@ -1259,17 +1259,8 @@ push_reload (rtx in, rtx out, rtx *inloc
 	}
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
 	if (HARD_REGNO_MODE_OK (i, mode)
-	    && TEST_HARD_REG_BIT (reg_class_contents[(int) class], i))
-	  {
-	    int nregs = hard_regno_nregs[i][mode];
-
-	    int j;
-	    for (j = 1; j < nregs; j++)
-	      if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class], i + j))
-		break;
-	    if (j == nregs)
-	      break;
-	  }
+	    && in_hard_reg_set_p (reg_class_contents[(int) class], mode, i))
+	  break;
       if (i == FIRST_PSEUDO_REGISTER)
 	{
 	  error_for_asm (this_insn, "impossible register constraint "
@@ -1533,18 +1524,15 @@ push_reload (rtx in, rtx out, rtx *inloc
 		|| ! bitmap_bit_p (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end,
 				   ORIGINAL_REGNO (XEXP (note, 0))))
 	    && ! refers_to_regno_for_reload_p (regno,
-					       (regno
-						+ hard_regno_nregs[regno]
-								  [rel_mode]),
+					       end_hard_regno (rel_mode,
+							       regno),
 					       PATTERN (this_insn), inloc)
 	    /* If this is also an output reload, IN cannot be used as
 	       the reload register if it is set in this insn unless IN
 	       is also OUT.  */
 	    && (out == 0 || in == out
 		|| ! hard_reg_set_here_p (regno,
-					  (regno
-					   + hard_regno_nregs[regno]
-							     [rel_mode]),
+					  end_hard_regno (rel_mode, regno),
 					  PATTERN (this_insn)))
 	    /* ??? Why is this code so different from the previous?
 	       Is there any simple coherent way to describe the two together?
@@ -1573,8 +1561,7 @@ push_reload (rtx in, rtx out, rtx *inloc
 
 	    if (offs == nregs
 		&& (! (refers_to_regno_for_reload_p
-		       (regno, (regno + hard_regno_nregs[regno][inmode]),
-				in, (rtx *)0))
+		       (regno, end_hard_regno (inmode, regno), in, (rtx *) 0))
 		    || can_reload_into (in, regno, inmode)))
 	      {
 		rld[i].reg_rtx = gen_rtx_REG (rel_mode, regno);
@@ -2089,7 +2076,7 @@ hard_reg_set_here_p (unsigned int beg_re
 
 	  /* See if this reg overlaps range under consideration.  */
 	  if (r < end_regno
-	      && r + hard_regno_nregs[r][GET_MODE (op0)] > beg_regno)
+	      && end_hard_regno (GET_MODE (op0), r) > beg_regno)
 	    return 1;
 	}
     }
@@ -2409,7 +2396,7 @@ decompose (rtx x)
 	}
       else
 	/* A hard reg.  */
-	val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
+	val.end = end_hard_regno (GET_MODE (x), val.start);
       break;
 
     case SUBREG:
@@ -6500,7 +6487,7 @@ reg_overlap_mentioned_for_reload_p (rtx 
 	  return 0;
 	}
 
-      endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
+      endregno = END_HARD_REGNO (x);
 
       return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
     }
@@ -6733,17 +6720,9 @@ find_equiv_reg (rtx goal, rtx insn, enum
 		}
 	      else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
 		continue;
-	      else
-		{
-		  int i;
-
-		  for (i = hard_regno_nregs[valueno][mode] - 1; i >= 0; i--)
-		    if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
-					     valueno + i))
-		      break;
-		  if (i >= 0)
-		    continue;
-		}
+	      else if (!in_hard_reg_set_p (reg_class_contents[(int) class],
+					  mode, valueno))
+		continue;
 	      value = valtry;
 	      where = p;
 	      break;
@@ -6777,9 +6756,7 @@ find_equiv_reg (rtx goal, rtx insn, enum
      and is also a register that appears in the address of GOAL.  */
 
   if (goal_mem && value == SET_DEST (single_set (where))
-      && refers_to_regno_for_reload_p (valueno,
-				       (valueno
-					+ hard_regno_nregs[valueno][mode]),
+      && refers_to_regno_for_reload_p (valueno, end_hard_regno (mode, valueno),
 				       goal, (rtx*) 0))
     return 0;
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	2007-05-21 19:58:43.000000000 +0100
+++ gcc/reload1.c	2007-05-21 20:05:37.000000000 +0100
@@ -542,7 +542,6 @@ compute_use_by_pseudos (HARD_REG_SET *to
   EXECUTE_IF_SET_IN_REG_SET (from, FIRST_PSEUDO_REGISTER, regno, rsi)
     {
       int r = reg_renumber[regno];
-      int nregs;
 
       if (r < 0)
 	{
@@ -553,11 +552,7 @@ compute_use_by_pseudos (HARD_REG_SET *to
 	  gcc_assert (reload_completed);
 	}
       else
-	{
-	  nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
-	  while (nregs-- > 0)
-	    SET_HARD_REG_BIT (*to, r + nregs);
-	}
+	add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
     }
 }
 
@@ -2136,7 +2131,7 @@ mark_home_live (int regno)
   i = reg_renumber[regno];
   if (i < 0)
     return;
-  lim = i + hard_regno_nregs[i][PSEUDO_REGNO_MODE (regno)];
+  lim = end_hard_regno (PSEUDO_REGNO_MODE (regno), i);
   while (i < lim)
     regs_ever_live[i++] = 1;
 }
@@ -3705,10 +3700,7 @@ spill_hard_reg (unsigned int regno, int 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_renumber[i] >= 0
 	&& (unsigned int) reg_renumber[i] <= regno
-	&& ((unsigned int) reg_renumber[i]
-	    + hard_regno_nregs[(unsigned int) reg_renumber[i]]
-			      [PSEUDO_REGNO_MODE (i)]
-	    > regno))
+	&& end_hard_regno (PSEUDO_REGNO_MODE (i), reg_renumber[i]) > regno)
       SET_REGNO_REG_SET (&spilled_pseudos, i);
 }
 
@@ -4528,8 +4520,7 @@ clear_reload_reg_in_use (unsigned int re
 	    {
 	      unsigned int conflict_start = true_regnum (rld[i].reg_rtx);
 	      unsigned int conflict_end
-		= (conflict_start
-		   + hard_regno_nregs[conflict_start][rld[i].mode]);
+		= end_hard_regno (rld[i].mode, conflict_start);
 
 	      /* If there is an overlap with the first to-be-freed register,
 		 adjust the interval start.  */
Index: gcc/reorg.c
===================================================================
--- gcc/reorg.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/reorg.c	2007-05-21 20:05:37.000000000 +0100
@@ -3170,16 +3170,9 @@ delete_prior_computation (rtx note, rtx 
 		   && REG_P (SET_DEST (pat)))
 	    {
 	      int dest_regno = REGNO (SET_DEST (pat));
-	      int dest_endregno
-		= (dest_regno
-		   + (dest_regno < FIRST_PSEUDO_REGISTER
-		      ? hard_regno_nregs[dest_regno]
-					[GET_MODE (SET_DEST (pat))] : 1));
+	      int dest_endregno = END_REGNO (SET_DEST (pat));
 	      int regno = REGNO (reg);
-	      int endregno
-		= (regno
-		   + (regno < FIRST_PSEUDO_REGISTER
-		      ? hard_regno_nregs[regno][GET_MODE (reg)] : 1));
+	      int endregno = END_REGNO (reg);
 
 	      if (dest_regno >= regno
 		  && dest_endregno <= endregno)
Index: gcc/resource.c
===================================================================
--- gcc/resource.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/resource.c	2007-05-21 20:05:37.000000000 +0100
@@ -107,8 +107,7 @@ update_live_status (rtx dest, rtx x, voi
   else
     {
       first_regno = REGNO (dest);
-      last_regno
-	= first_regno + hard_regno_nregs[first_regno][GET_MODE (dest)];
+      last_regno = END_HARD_REGNO (dest);
     }
 
   if (GET_CODE (x) == CLOBBER)
@@ -244,15 +243,8 @@ mark_referenced_resources (rtx x, struct
       return;
 
     case REG:
-	{
-	  unsigned int regno = REGNO (x);
-	  unsigned int last_regno
-	    = regno + hard_regno_nregs[regno][GET_MODE (x)];
-
-	  gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
-	  for (r = regno; r < last_regno; r++)
-	    SET_HARD_REG_BIT (res->regs, r);
-	}
+      gcc_assert (HARD_REGISTER_P (x));
+      add_to_hard_reg_set (&res->regs, GET_MODE (x), REGNO (x));
       return;
 
     case MEM:
@@ -780,13 +772,8 @@ mark_set_resources (rtx x, struct resour
     case REG:
       if (in_dest)
 	{
-	  unsigned int regno = REGNO (x);
-	  unsigned int last_regno
-	    = regno + hard_regno_nregs[regno][GET_MODE (x)];
-
-	  gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
-	  for (r = regno; r < last_regno; r++)
-	    SET_HARD_REG_BIT (res->regs, r);
+	  gcc_assert (HARD_REGISTER_P (x));
+	  add_to_hard_reg_set (&res->regs, GET_MODE (x), REGNO (x));
 	}
       return;
 
@@ -970,8 +957,6 @@ mark_target_live_regs (rtx insns, rtx ta
   if (b != -1)
     {
       regset regs_live = BASIC_BLOCK (b)->il.rtl->global_live_at_start;
-      unsigned int j;
-      unsigned int regno;
       rtx start_insn, stop_insn;
       reg_set_iterator rsi;
 
@@ -984,13 +969,8 @@ mark_target_live_regs (rtx insns, rtx ta
       EXECUTE_IF_SET_IN_REG_SET (regs_live, FIRST_PSEUDO_REGISTER, i, rsi)
 	{
 	  if (reg_renumber[i] >= 0)
-	    {
-	      regno = reg_renumber[i];
-	      for (j = regno;
-		   j < regno + hard_regno_nregs[regno][PSEUDO_REGNO_MODE (i)];
-		   j++)
-		SET_HARD_REG_BIT (current_live_regs, j);
-	    }
+	    add_to_hard_reg_set (&current_live_regs, PSEUDO_REGNO_MODE (i),
+				reg_renumber[i]);
 	}
 
       /* Get starting and ending insn, handling the case where each might
@@ -1056,16 +1036,9 @@ mark_target_live_regs (rtx insns, rtx ta
 		if (REG_NOTE_KIND (link) == REG_DEAD
 		    && REG_P (XEXP (link, 0))
 		    && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
-		  {
-		    unsigned int first_regno = REGNO (XEXP (link, 0));
-		    unsigned int last_regno
-		      = (first_regno
-			 + hard_regno_nregs[first_regno]
-					   [GET_MODE (XEXP (link, 0))]);
-
-		    for (i = first_regno; i < last_regno; i++)
-		      SET_HARD_REG_BIT (pending_dead_regs, i);
-		  }
+		  add_to_hard_reg_set (&pending_dead_regs,
+				      GET_MODE (XEXP (link, 0)),
+				      REGNO (XEXP (link, 0)));
 
 	      note_stores (PATTERN (real_insn), update_live_status, NULL);
 
@@ -1075,16 +1048,9 @@ mark_target_live_regs (rtx insns, rtx ta
 		if (REG_NOTE_KIND (link) == REG_UNUSED
 		    && REG_P (XEXP (link, 0))
 		    && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
-		  {
-		    unsigned int first_regno = REGNO (XEXP (link, 0));
-		    unsigned int last_regno
-		      = (first_regno
-			 + hard_regno_nregs[first_regno]
-					   [GET_MODE (XEXP (link, 0))]);
-
-		    for (i = first_regno; i < last_regno; i++)
-		      CLEAR_HARD_REG_BIT (current_live_regs, i);
-		  }
+		  remove_from_hard_reg_set (&current_live_regs,
+					   GET_MODE (XEXP (link, 0)),
+					   REGNO (XEXP (link, 0)));
 	    }
 
 	  else if (LABEL_P (real_insn))
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/rtlanal.c	2007-05-21 20:05:37.000000000 +0100
@@ -1233,10 +1233,7 @@ refers_to_regno_p (unsigned int regno, u
 	  && regno >= FIRST_VIRTUAL_REGISTER && regno <= LAST_VIRTUAL_REGISTER)
 	return 1;
 
-      return (endregno > x_regno
-	      && regno < x_regno + (x_regno < FIRST_PSEUDO_REGISTER
-				    ? hard_regno_nregs[x_regno][GET_MODE (x)]
-			      : 1));
+      return endregno > x_regno && regno < END_REGNO (x);
 
     case SUBREG:
       /* If this is a SUBREG of a hard reg, we can see exactly which
@@ -1343,8 +1340,7 @@ reg_overlap_mentioned_p (rtx x, rtx in)
 
     case REG:
       regno = REGNO (x);
-      endregno = regno + (regno < FIRST_PSEUDO_REGISTER
-			  ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
+      endregno = END_REGNO (x);
     do_reg:
       return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
 
@@ -1551,7 +1547,7 @@ note_uses (rtx *pbody, void (*fun) (rtx 
 int
 dead_or_set_p (rtx insn, rtx x)
 {
-  unsigned int regno, last_regno;
+  unsigned int regno, end_regno;
   unsigned int i;
 
   /* Can't use cc0_rtx below since this file is used by genattrtab.c.  */
@@ -1561,10 +1557,8 @@ dead_or_set_p (rtx insn, rtx x)
   gcc_assert (REG_P (x));
 
   regno = REGNO (x);
-  last_regno = (regno >= FIRST_PSEUDO_REGISTER ? regno
-		: regno + hard_regno_nregs[regno][GET_MODE (x)] - 1);
-
-  for (i = regno; i <= last_regno; i++)
+  end_regno = END_REGNO (x);
+  for (i = regno; i < end_regno; i++)
     if (! dead_or_set_regno_p (insn, i))
       return 0;
 
@@ -1591,8 +1585,7 @@ covers_regno_no_parallel_p (rtx dest, un
     return false;
 
   regno = REGNO (dest);
-  endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
-	      : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
+  endregno = END_REGNO (dest);
   return (test_regno >= regno && test_regno < endregno);
 }
 
@@ -1713,11 +1706,7 @@ find_regno_note (rtx insn, enum reg_note
 	   problem here.  */
 	&& REG_P (XEXP (link, 0))
 	&& REGNO (XEXP (link, 0)) <= regno
-	&& ((REGNO (XEXP (link, 0))
-	     + (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1
-		: hard_regno_nregs[REGNO (XEXP (link, 0))]
-				  [GET_MODE (XEXP (link, 0))]))
-	    > regno))
+	&& END_REGNO (XEXP (link, 0)) > regno)
       return link;
   return 0;
 }
@@ -1807,8 +1796,7 @@ find_reg_fusage (rtx insn, enum rtx_code
 
       if (regno < FIRST_PSEUDO_REGISTER)
 	{
-	  unsigned int end_regno
-	    = regno + hard_regno_nregs[regno][GET_MODE (datum)];
+	  unsigned int end_regno = END_HARD_REGNO (datum);
 	  unsigned int i;
 
 	  for (i = regno; i < end_regno; i++)
@@ -1837,13 +1825,12 @@ find_regno_fusage (rtx insn, enum rtx_co
 
   for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
     {
-      unsigned int regnote;
       rtx op, reg;
 
       if (GET_CODE (op = XEXP (link, 0)) == code
 	  && REG_P (reg = XEXP (op, 0))
-	  && (regnote = REGNO (reg)) <= regno
-	  && regnote + hard_regno_nregs[regnote][GET_MODE (reg)] > regno)
+	  && REGNO (reg) <= regno
+	  && END_HARD_REGNO (reg) > regno)
 	return 1;
     }
 
Index: gcc/stmt.c
===================================================================
--- gcc/stmt.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/stmt.c	2007-05-21 20:05:37.000000000 +0100
@@ -575,14 +575,9 @@ decl_overlaps_hard_reg_set_p (tree *decl
 	  && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
 	{
 	  rtx reg = DECL_RTL (decl);
-	  unsigned int regno;
 
-	  for (regno = REGNO (reg);
-	       regno < (REGNO (reg)
-			+ hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
-	       regno++)
-	    if (TEST_HARD_REG_BIT (*regs, regno))
-	      return decl;
+	  if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg)))
+	    return decl;
 	}
       walk_subtrees = 0;
     }
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2007-05-21 19:58:41.000000000 +0100
+++ gcc/var-tracking.c	2007-05-21 20:05:37.000000000 +0100
@@ -2389,8 +2389,7 @@ emit_note_insn_var_location (void **varp
 	  if (REG_P (loc[n_var_parts])
 	      && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
 		 == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
-	      && REGNO (loc[n_var_parts])
-		 + hard_regno_nregs[REGNO (loc[n_var_parts])][mode]
+	      && end_hard_regno (mode, REGNO (loc[n_var_parts]))
 		 == REGNO (loc2))
 	    {
 	      if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)


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