diff mbox

[2/9] Add a REG_NREGS macro

Message ID 87fv6tu52q.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford May 18, 2015, 6:13 p.m. UTC
This patch adds a REG_NREGS macro that by the end of the series
will simply be an rtx field access.  The definition in this patch
is just a placeholder (and so I haven't tried to avoid the double
evaluation of the parameter).

The diff has extra context because in most cases it makes it obvious
that we really are looking at hard_regno_nregs[REGNO (x)][GET_MODE (x)]
for some rtx x.  There are a couple of sites where it's more indirect
though.


gcc/
	* rtl.h (REG_NREGS): New macro
	* alias.c (record_set): Use it.
	* cfgcleanup.c (mark_effect): Likewise.
	* combine.c (likely_spilled_retval_1): Likewise.
	(likely_spilled_retval_p, can_change_dest_mode): Likewise.
	(move_deaths, distribute_notes): Likewise.
	* cselib.c (cselib_record_set): Likewise.
	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
	* df-scan.c (df_mark_reg): Likewise.
	* dse.c (look_for_hardregs): Likewise.
	* dwarf2out.c (reg_loc_descriptor): Likewise.
	(multiple_reg_loc_descriptor): Likewise.
	* expr.c (write_complex_part, read_complex_part): Likewise.
	(emit_move_complex): Likewise.
	* haifa-sched.c (setup_ref_regs): Likewise.
	* ira-lives.c (mark_hard_reg_live): Likewise.
	* lra.c (lra_set_insn_recog_data): Likewise.
	* mode-switching.c (create_pre_exit): Likewise.
	* postreload.c (reload_combine_recognize_const_pattern): Likewise.
	(reload_combine_recognize_pattern): Likewise.
	(reload_combine_note_use, move2add_record_mode): Likewise.
	(reload_cse_move2add): Likewise.
	* reg-stack.c (subst_stack_regs_pat): Likewise.
	* regcprop.c (kill_value, copy_value): Likewise.
	(copyprop_hardreg_forward_1): Likewise.
	* regrename.c (verify_reg_in_set, scan_rtx_reg): Likewise.
	(build_def_use): Likewise.
	* sched-deps.c (mark_insn_reg_birth, mark_reg_death): Likewise.
	(deps_analyze_insn): Likewise.
	* sched-rgn.c (check_live_1, update_live_1): Likewise.
	* sel-sched.c (count_occurrences_equiv): Likewise.
	* valtrack.c (dead_debug_insert_temp): Likewise.

Comments

Jeff Law May 18, 2015, 8:25 p.m. UTC | #1
On 05/18/2015 12:13 PM, Richard Sandiford wrote:
> This patch adds a REG_NREGS macro that by the end of the series
> will simply be an rtx field access.  The definition in this patch
> is just a placeholder (and so I haven't tried to avoid the double
> evaluation of the parameter).
>
> The diff has extra context because in most cases it makes it obvious
> that we really are looking at hard_regno_nregs[REGNO (x)][GET_MODE (x)]
> for some rtx x.  There are a couple of sites where it's more indirect
> though.
>
>
> gcc/
> 	* rtl.h (REG_NREGS): New macro
> 	* alias.c (record_set): Use it.
> 	* cfgcleanup.c (mark_effect): Likewise.
> 	* combine.c (likely_spilled_retval_1): Likewise.
> 	(likely_spilled_retval_p, can_change_dest_mode): Likewise.
> 	(move_deaths, distribute_notes): Likewise.
> 	* cselib.c (cselib_record_set): Likewise.
> 	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
> 	* df-scan.c (df_mark_reg): Likewise.
> 	* dse.c (look_for_hardregs): Likewise.
> 	* dwarf2out.c (reg_loc_descriptor): Likewise.
> 	(multiple_reg_loc_descriptor): Likewise.
> 	* expr.c (write_complex_part, read_complex_part): Likewise.
> 	(emit_move_complex): Likewise.
> 	* haifa-sched.c (setup_ref_regs): Likewise.
> 	* ira-lives.c (mark_hard_reg_live): Likewise.
> 	* lra.c (lra_set_insn_recog_data): Likewise.
> 	* mode-switching.c (create_pre_exit): Likewise.
> 	* postreload.c (reload_combine_recognize_const_pattern): Likewise.
> 	(reload_combine_recognize_pattern): Likewise.
> 	(reload_combine_note_use, move2add_record_mode): Likewise.
> 	(reload_cse_move2add): Likewise.
> 	* reg-stack.c (subst_stack_regs_pat): Likewise.
> 	* regcprop.c (kill_value, copy_value): Likewise.
> 	(copyprop_hardreg_forward_1): Likewise.
> 	* regrename.c (verify_reg_in_set, scan_rtx_reg): Likewise.
> 	(build_def_use): Likewise.
> 	* sched-deps.c (mark_insn_reg_birth, mark_reg_death): Likewise.
> 	(deps_analyze_insn): Likewise.
> 	* sched-rgn.c (check_live_1, update_live_1): Likewise.
> 	* sel-sched.c (count_occurrences_equiv): Likewise.
> 	* valtrack.c (dead_debug_insert_temp): Likewise.
>
OK.

Makes me wonder if we want to poison hard_regno_nregs in some way to 
avoid folks re-introducing this stuff in the future...  Your call if you 
want to tackle that as a follow-up.

jeff
Richard Sandiford May 19, 2015, 6:51 a.m. UTC | #2
Jeff Law <law@redhat.com> writes:
> On 05/18/2015 12:13 PM, Richard Sandiford wrote:
>> This patch adds a REG_NREGS macro that by the end of the series
>> will simply be an rtx field access.  The definition in this patch
>> is just a placeholder (and so I haven't tried to avoid the double
>> evaluation of the parameter).
>>
>> The diff has extra context because in most cases it makes it obvious
>> that we really are looking at hard_regno_nregs[REGNO (x)][GET_MODE (x)]
>> for some rtx x.  There are a couple of sites where it's more indirect
>> though.
>>
>>
>> gcc/
>> 	* rtl.h (REG_NREGS): New macro
>> 	* alias.c (record_set): Use it.
>> 	* cfgcleanup.c (mark_effect): Likewise.
>> 	* combine.c (likely_spilled_retval_1): Likewise.
>> 	(likely_spilled_retval_p, can_change_dest_mode): Likewise.
>> 	(move_deaths, distribute_notes): Likewise.
>> 	* cselib.c (cselib_record_set): Likewise.
>> 	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
>> 	* df-scan.c (df_mark_reg): Likewise.
>> 	* dse.c (look_for_hardregs): Likewise.
>> 	* dwarf2out.c (reg_loc_descriptor): Likewise.
>> 	(multiple_reg_loc_descriptor): Likewise.
>> 	* expr.c (write_complex_part, read_complex_part): Likewise.
>> 	(emit_move_complex): Likewise.
>> 	* haifa-sched.c (setup_ref_regs): Likewise.
>> 	* ira-lives.c (mark_hard_reg_live): Likewise.
>> 	* lra.c (lra_set_insn_recog_data): Likewise.
>> 	* mode-switching.c (create_pre_exit): Likewise.
>> 	* postreload.c (reload_combine_recognize_const_pattern): Likewise.
>> 	(reload_combine_recognize_pattern): Likewise.
>> 	(reload_combine_note_use, move2add_record_mode): Likewise.
>> 	(reload_cse_move2add): Likewise.
>> 	* reg-stack.c (subst_stack_regs_pat): Likewise.
>> 	* regcprop.c (kill_value, copy_value): Likewise.
>> 	(copyprop_hardreg_forward_1): Likewise.
>> 	* regrename.c (verify_reg_in_set, scan_rtx_reg): Likewise.
>> 	(build_def_use): Likewise.
>> 	* sched-deps.c (mark_insn_reg_birth, mark_reg_death): Likewise.
>> 	(deps_analyze_insn): Likewise.
>> 	* sched-rgn.c (check_live_1, update_live_1): Likewise.
>> 	* sel-sched.c (count_occurrences_equiv): Likewise.
>> 	* valtrack.c (dead_debug_insert_temp): Likewise.
>>
> OK.
>
> Makes me wonder if we want to poison hard_regno_nregs in some way to 
> avoid folks re-introducing this stuff in the future...  Your call if you 
> want to tackle that as a follow-up.

The problem is that many uses of hard_regno_nregs aren't about
existing REGs.  E.g. the register allocators need to know how many
registers something would occupy before allocating it, so they (rightly)
make heavy use of it with a calculated regno and/or mode.

Agree that people will probably do things the old way out of habit.
Maybe it's just something I should grep for occasionally...

Thanks,
Richard
diff mbox

Patch

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-18 08:19:43.475431381 +0100
+++ gcc/rtl.h	2015-05-18 08:19:43.459431568 +0100
@@ -1692,16 +1692,24 @@  #define LABEL_REF_LABEL(LABREF) XCEXP (L
 
 /* For a REG rtx, REGNO extracts the register number.  REGNO can only
    be used on RHS.  Use SET_REGNO to change the value.  */
 #define REGNO(RTX) (rhs_regno(RTX))
 #define SET_REGNO(RTX,N) \
   (df_ref_change_reg_with_loc (REGNO (RTX), N, RTX), XCUINT (RTX, 0, REG) = N)
 #define SET_REGNO_RAW(RTX,N) (XCUINT (RTX, 0, REG) = N)
 
+/* Return the number of consecutive registers in a REG.  This is always
+   1 for pseudo registers and is determined by HARD_REGNO_NREGS for
+   hard registers.  */
+#define REG_NREGS(RTX) \
+  (REGNO (RTX) < FIRST_PSEUDO_REGISTER \
+   ? (unsigned int) hard_regno_nregs[REGNO (RTX)][GET_MODE (RTX)] \
+   : 1)
+
 /* ORIGINAL_REGNO holds the number the register originally had; for a
    pseudo register turned into a hard reg this will hold the old pseudo
    register number.  */
 #define ORIGINAL_REGNO(RTX) \
   (RTL_FLAG_CHECK1 ("ORIGINAL_REGNO", (RTX), REG)->u2.original_regno)
 
 /* Force the REGNO macro to only be used on the lhs.  */
 static inline unsigned int
Index: gcc/alias.c
===================================================================
--- gcc/alias.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/alias.c	2015-05-18 08:19:43.455431618 +0100
@@ -1295,22 +1295,17 @@  record_set (rtx dest, const_rtx set, voi
 
   if (!REG_P (dest))
     return;
 
   regno = REGNO (dest);
 
   gcc_checking_assert (regno < reg_base_value->length ());
 
-  /* If this spans multiple hard registers, then we must indicate that every
-     register has an unusable value.  */
-  if (regno < FIRST_PSEUDO_REGISTER)
-    n = hard_regno_nregs[regno][GET_MODE (dest)];
-  else
-    n = 1;
+  n = REG_NREGS (dest);
   if (n != 1)
     {
       while (--n >= 0)
 	{
 	  bitmap_set_bit (reg_seen, regno + n);
 	  new_reg_base_value[regno + n] = 0;
 	}
       return;
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/cfgcleanup.c	2015-05-18 08:19:43.455431618 +0100
@@ -229,35 +229,33 @@  mark_effect (rtx exp, regset nonequal)
       /* In case we do clobber the register, mark it as equal, as we know the
 	 value is dead so it don't have to match.  */
     case CLOBBER:
       if (REG_P (XEXP (exp, 0)))
 	{
 	  dest = XEXP (exp, 0);
 	  regno = REGNO (dest);
 	  if (HARD_REGISTER_NUM_P (regno))
-	    bitmap_clear_range (nonequal, regno,
-				hard_regno_nregs[regno][GET_MODE (dest)]);
+	    bitmap_clear_range (nonequal, regno, REG_NREGS (dest));
 	  else
 	    bitmap_clear_bit (nonequal, regno);
 	}
       return false;
 
     case SET:
       if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
 	return false;
       dest = SET_DEST (exp);
       if (dest == pc_rtx)
 	return false;
       if (!REG_P (dest))
 	return true;
       regno = REGNO (dest);
       if (HARD_REGISTER_NUM_P (regno))
-	bitmap_set_range (nonequal, regno,
-			  hard_regno_nregs[regno][GET_MODE (dest)]);
+	bitmap_set_range (nonequal, regno, REG_NREGS (dest));
       else
 	bitmap_set_bit (nonequal, regno);
       return false;
 
     default:
       return false;
     }
 }
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/combine.c	2015-05-18 08:19:43.459431568 +0100
@@ -2329,17 +2329,17 @@  likely_spilled_retval_1 (rtx x, const_rt
   unsigned regno, nregs;
   unsigned new_mask;
 
   if (!REG_P (XEXP (set, 0)))
     return;
   regno = REGNO (x);
   if (regno >= info->regno + info->nregs)
     return;
-  nregs = hard_regno_nregs[regno][GET_MODE (x)];
+  nregs = REG_NREGS (x);
   if (regno + nregs <= info->regno)
     return;
   new_mask = (2U << (nregs - 1)) - 1;
   if (regno < info->regno)
     new_mask >>= info->regno - regno;
   else
     new_mask <<= regno - info->regno;
   info->mask &= ~new_mask;
@@ -2364,17 +2364,17 @@  likely_spilled_retval_p (rtx_insn *insn)
   struct likely_spilled_retval_info info;
 
   if (!NONJUMP_INSN_P (use) || GET_CODE (PATTERN (use)) != USE || insn == use)
     return 0;
   reg = XEXP (PATTERN (use), 0);
   if (!REG_P (reg) || !targetm.calls.function_value_regno_p (REGNO (reg)))
     return 0;
   regno = REGNO (reg);
-  nregs = hard_regno_nregs[regno][GET_MODE (reg)];
+  nregs = REG_NREGS (reg);
   if (nregs == 1)
     return 0;
   mask = (2U << (nregs - 1)) - 1;
 
   /* Disregard parts of the return value that are set later.  */
   info.regno = regno;
   info.nregs = nregs;
   info.mask = mask;
@@ -2436,18 +2436,17 @@  can_change_dest_mode (rtx x, int added_s
   if (!REG_P (x))
     return false;
 
   regno = REGNO (x);
   /* Allow hard registers if the new mode is legal, and occupies no more
      registers than the old mode.  */
   if (regno < FIRST_PSEUDO_REGISTER)
     return (HARD_REGNO_MODE_OK (regno, mode)
-	    && (hard_regno_nregs[regno][GET_MODE (x)]
-		>= hard_regno_nregs[regno][mode]));
+	    && REG_NREGS (x) >= hard_regno_nregs[regno][mode]);
 
   /* Or a pseudo that is only used once.  */
   return (regno < reg_n_sets_max
 	  && REG_N_SETS (regno) == 1
 	  && !added_sets
 	  && !REG_USERVAR_P (x));
 }
 
@@ -13331,17 +13330,17 @@  move_deaths (rtx x, rtx maybe_kill_insn,
 	     register, then to be safe we must check for REG_DEAD notes
 	     for each register other than the first.  They could have
 	     their own REG_DEAD notes lying around.  */
 	  else if ((note == 0
 		    || (note != 0
 			&& (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
 			    < GET_MODE_SIZE (GET_MODE (x)))))
 		   && regno < FIRST_PSEUDO_REGISTER
-		   && hard_regno_nregs[regno][GET_MODE (x)] > 1)
+		   && REG_NREGS (x) > 1)
 	    {
 	      unsigned int ourend = END_HARD_REGNO (x);
 	      unsigned int i, offset;
 	      rtx oldnotes = 0;
 
 	      if (note)
 		offset = hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))];
 	      else
@@ -13926,18 +13925,17 @@  distribute_notes (rtx notes, rtx_insn *f
 		 multiple registers, ensure that we are still using all
 		 parts of the object.  If we find a piece of the object
 		 that is unused, we must arrange for an appropriate REG_DEAD
 		 note to be added for it.  However, we can't just emit a USE
 		 and tag the note to it, since the register might actually
 		 be dead; so we recourse, and the recursive call then finds
 		 the previous insn that used this register.  */
 
-	      if (place && regno < FIRST_PSEUDO_REGISTER
-		  && hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] > 1)
+	      if (place && REG_NREGS (XEXP (note, 0)) > 1)
 		{
 		  unsigned int endregno = END_HARD_REGNO (XEXP (note, 0));
 		  bool all_used = true;
 		  unsigned int i;
 
 		  for (i = regno; i < endregno; i++)
 		    if ((! refers_to_regno_p (i, PATTERN (place))
 			 && ! find_regno_fusage (place, USE, i))
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/cselib.c	2015-05-18 08:19:43.459431568 +0100
@@ -2366,26 +2366,25 @@  cselib_invalidate_rtx_note_stores (rtx d
 
 /* Record the result of a SET instruction.  DEST is being set; the source
    contains the value described by SRC_ELT.  If DEST is a MEM, DEST_ADDR_ELT
    describes its address.  */
 
 static void
 cselib_record_set (rtx dest, cselib_val *src_elt, cselib_val *dest_addr_elt)
 {
-  int dreg = REG_P (dest) ? (int) REGNO (dest) : -1;
-
   if (src_elt == 0 || side_effects_p (dest))
     return;
 
-  if (dreg >= 0)
+  if (REG_P (dest))
     {
+      unsigned int dreg = REGNO (dest);
       if (dreg < FIRST_PSEUDO_REGISTER)
 	{
-	  unsigned int n = hard_regno_nregs[dreg][GET_MODE (dest)];
+	  unsigned int n = REG_NREGS (dest);
 
 	  if (n > max_value_regs)
 	    max_value_regs = n;
 	}
 
       if (REG_VALUES (dreg) == 0)
 	{
 	  used_regs[n_used_regs++] = dreg;
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/df-problems.c	2015-05-18 08:19:43.459431568 +0100
@@ -3571,18 +3571,17 @@  df_simulate_one_insn_forwards (basic_blo
       switch (REG_NOTE_KIND (link))
 	{
 	case REG_DEAD:
 	case REG_UNUSED:
 	  {
 	    rtx reg = XEXP (link, 0);
 	    int regno = REGNO (reg);
 	    if (HARD_REGISTER_NUM_P (regno))
-	      bitmap_clear_range (live, regno,
-				  hard_regno_nregs[regno][GET_MODE (reg)]);
+	      bitmap_clear_range (live, regno, REG_NREGS (reg));
 	    else
 	      bitmap_clear_bit (live, regno);
 	  }
 	  break;
 	default:
 	  break;
 	}
     }
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/df-scan.c	2015-05-18 08:19:43.459431568 +0100
@@ -3511,20 +3511,17 @@  df_get_eh_block_artificial_uses (bitmap
 df_mark_reg (rtx reg, void *vset)
 {
   bitmap set = (bitmap) vset;
   int regno = REGNO (reg);
 
   gcc_assert (GET_MODE (reg) != BLKmode);
 
   if (regno < FIRST_PSEUDO_REGISTER)
-    {
-      int n = hard_regno_nregs[regno][GET_MODE (reg)];
-      bitmap_set_range (set, regno, n);
-    }
+    bitmap_set_range (set, regno, REG_NREGS (reg));
   else
     bitmap_set_bit (set, regno);
 }
 
 
 /* Set the bit for regs that are considered being defined at the entry. */
 
 static void
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/dse.c	2015-05-18 08:19:43.471431430 +0100
@@ -1871,21 +1871,17 @@  find_shift_sequence (int access_size,
 
 static void
 look_for_hardregs (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   bitmap regs_set = (bitmap) data;
 
   if (REG_P (x)
       && HARD_REGISTER_P (x))
-    {
-      unsigned int regno = REGNO (x);
-      bitmap_set_range (regs_set, regno,
-			hard_regno_nregs[regno][GET_MODE (x)]);
-    }
+    bitmap_set_range (regs_set, REGNO (x), REG_NREGS (x));
 }
 
 /* Helper function for replace_read and record_store.
    Attempt to return a value stored in STORE_INFO, from READ_BEGIN
    to one before READ_END bytes read in READ_MODE.  Return NULL
    if not successful.  If REQUIRE_CST is true, return always constant.  */
 
 static rtx
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/dwarf2out.c	2015-05-18 08:19:43.463431525 +0100
@@ -11142,17 +11142,17 @@  reg_loc_descriptor (rtx rtl, enum var_in
 	    add_loc_descr (&result,
 			   new_loc_descr (DW_OP_stack_value, 0, 0));
 	}
       return result;
     }
 
   regs = targetm.dwarf_register_span (rtl);
 
-  if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
+  if (REG_NREGS (rtl) > 1 || regs)
     return multiple_reg_loc_descriptor (rtl, regs, initialized);
   else
     {
       unsigned int dbx_regnum = dbx_reg_number (rtl);
       if (dbx_regnum == IGNORED_DWARF_REGNUM)
 	return 0;
       return one_reg_loc_descriptor (dbx_regnum, initialized);
     }
@@ -11199,17 +11199,17 @@  multiple_reg_loc_descriptor (rtx rtl, rt
 	{
 	  int leaf_reg = LEAF_REG_REMAP (reg);
 	  if (leaf_reg != -1)
 	    reg = (unsigned) leaf_reg;
 	}
 #endif
 
       gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
-      nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
+      nregs = REG_NREGS (rtl);
 
       size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;
 
       loc_result = NULL;
       while (nregs--)
 	{
 	  dw_loc_descr_ref t;
 
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/expr.c	2015-05-18 08:19:43.463431525 +0100
@@ -3046,17 +3046,17 @@  write_complex_part (rtx cplx, rtx val, b
      correspond to TCmode.  */
   if (ibitsize >= BITS_PER_WORD
       /* For hard regs we have exact predicates.  Assume we can split
 	 the original object if it spans an even number of hard regs.
 	 This special case is important for SCmode on 64-bit platforms
 	 where the natural size of floating-point regs is 32-bit.  */
       || (REG_P (cplx)
 	  && REGNO (cplx) < FIRST_PSEUDO_REGISTER
-	  && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
+	  && REG_NREGS (cplx) % 2 == 0))
     {
       rtx part = simplify_gen_subreg (imode, cplx, cmode,
 				      imag_p ? GET_MODE_SIZE (imode) : 0);
       if (part)
         {
 	  emit_move_insn (part, val);
 	  return;
 	}
@@ -3111,17 +3111,17 @@  read_complex_part (rtx cplx, bool imag_p
      correspond to TCmode.  */
   if (ibitsize >= BITS_PER_WORD
       /* For hard regs we have exact predicates.  Assume we can split
 	 the original object if it spans an even number of hard regs.
 	 This special case is important for SCmode on 64-bit platforms
 	 where the natural size of floating-point regs is 32-bit.  */
       || (REG_P (cplx)
 	  && REGNO (cplx) < FIRST_PSEUDO_REGISTER
-	  && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
+	  && REG_NREGS (cplx) % 2 == 0))
     {
       rtx ret = simplify_gen_subreg (imode, cplx, cmode,
 				     imag_p ? GET_MODE_SIZE (imode) : 0);
       if (ret)
         return ret;
       else
 	/* simplify_gen_subreg may fail for sub-word MEMs.  */
 	gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
@@ -3341,20 +3341,20 @@  emit_move_complex (machine_mode mode, rt
     return emit_move_complex_push (mode, x, y);
 
   /* See if we can coerce the target into moving both values at once, except
      for floating point where we favor moving as parts if this is easy.  */
   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
       && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
       && !(REG_P (x)
 	   && HARD_REGISTER_P (x)
-	   && hard_regno_nregs[REGNO (x)][mode] == 1)
+	   && REG_NREGS (x) == 1)
       && !(REG_P (y)
 	   && HARD_REGISTER_P (y)
-	   && hard_regno_nregs[REGNO (y)][mode] == 1))
+	   && REG_NREGS (y) == 1))
     try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
   else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
     try_int = false;
   /* Is possible if both are registers (or subregs of registers).  */
   else if (register_operand (x, mode) && register_operand (y, mode))
     try_int = true;
   /* If one of the operands is a memory, and alignment constraints
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/haifa-sched.c	2015-05-18 08:19:43.467431478 +0100
@@ -1035,18 +1035,17 @@  setup_ref_regs (rtx x)
   int i, j, regno;
   const RTX_CODE code = GET_CODE (x);
   const char *fmt;
 
   if (REG_P (x))
     {
       regno = REGNO (x);
       if (HARD_REGISTER_NUM_P (regno))
-	bitmap_set_range (region_ref_regs, regno,
-			  hard_regno_nregs[regno][GET_MODE (x)]);
+	bitmap_set_range (region_ref_regs, regno, REG_NREGS (x));
       else
 	bitmap_set_bit (region_ref_regs, REGNO (x));
       return;
     }
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
       setup_ref_regs (XEXP (x, i));
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/ira-lives.c	2015-05-18 08:19:43.467431478 +0100
@@ -347,17 +347,17 @@  mark_pseudo_regno_subword_live (int regn
    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)];
+      int last = END_REGNO (reg);
       enum reg_class aclass, pclass;
 
       while (regno < last)
 	{
 	  if (! TEST_HARD_REG_BIT (hard_regs_live, regno)
 	      && ! TEST_HARD_REG_BIT (eliminable_regset, regno))
 	    {
 	      aclass = ira_hard_regno_allocno_class[regno];
Index: gcc/lra.c
===================================================================
--- gcc/lra.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/lra.c	2015-05-18 08:19:43.467431478 +0100
@@ -1099,20 +1099,17 @@  lra_set_insn_recog_data (rtx_insn *insn)
 	   link != NULL_RTX;
 	   link = XEXP (link, 1))
 	if (GET_CODE (XEXP (link, 0)) == USE
 	    && REG_P (XEXP (XEXP (link, 0), 0)))
 	  {
 	    regno = REGNO (XEXP (XEXP (link, 0), 0));
 	    lra_assert (regno < FIRST_PSEUDO_REGISTER);
 	    /* It is an argument register.  */
-	    for (i = (hard_regno_nregs
-		      [regno][GET_MODE (XEXP (XEXP (link, 0), 0))]) - 1;
-		 i >= 0;
-		 i--)
+	    for (i = REG_NREGS (XEXP (XEXP (link, 0), 0)) - 1; i >= 0; i--)
 	      arg_hard_regs[n_hard_regs++] = regno + i;
 	  }
       if (n_hard_regs != 0)
 	{
 	  arg_hard_regs[n_hard_regs++] = -1;
 	  data->arg_hard_regs = XNEWVEC (int, n_hard_regs);
 	  memcpy (data->arg_hard_regs, arg_hard_regs,
 		  sizeof (int) * n_hard_regs);
Index: gcc/mode-switching.c
===================================================================
--- gcc/mode-switching.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/mode-switching.c	2015-05-18 08:19:43.467431478 +0100
@@ -262,17 +262,17 @@  create_pre_exit (int n_entities, int *en
 	   insert the final mode switch before the return value copy
 	   to its hard register.  */
 	if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
 	    && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
 	    && GET_CODE (PATTERN (last_insn)) == USE
 	    && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
 	  {
 	    int ret_start = REGNO (ret_reg);
-	    int nregs = hard_regno_nregs[ret_start][GET_MODE (ret_reg)];
+	    int nregs = REG_NREGS (ret_reg);
 	    int ret_end = ret_start + nregs;
 	    bool short_block = false;
 	    bool multi_reg_return = false;
 	    bool forced_late_switch = false;
 	    rtx_insn *before_return_copy;
 
 	    do
 	      {
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/postreload.c	2015-05-18 08:19:43.455431618 +0100
@@ -969,17 +969,17 @@  reload_combine_recognize_const_pattern (
 
   set = single_set (insn);
   if (set == NULL_RTX)
     return false;
 
   reg = SET_DEST (set);
   src = SET_SRC (set);
   if (!REG_P (reg)
-      || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1
+      || REG_NREGS (reg) != 1
       || GET_MODE (reg) != Pmode
       || reg == stack_pointer_rtx)
     return false;
 
   regno = REGNO (reg);
 
   /* We look for a REG1 = REG2 + CONSTANT insn, followed by either
      uses of REG1 inside an address, or inside another add insn.  If
@@ -1104,18 +1104,17 @@  reload_combine_recognize_pattern (rtx_in
   unsigned int regno;
 
   set = single_set (insn);
   if (set == NULL_RTX)
     return false;
 
   reg = SET_DEST (set);
   src = SET_SRC (set);
-  if (!REG_P (reg)
-      || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
+  if (!REG_P (reg) || REG_NREGS (reg) != 1)
     return false;
 
   regno = REGNO (reg);
 
   /* Look for (set (REGX) (CONST_INT))
      (set (REGX) (PLUS (REGX) (REGY)))
      ...
      ... (MEM (REGX)) ...
@@ -1561,17 +1560,17 @@  reload_combine_note_use (rtx *xp, rtx_in
       {
 	int regno = REGNO (x);
 	int use_index;
 	int nregs;
 
 	/* No spurious USEs of pseudo registers may remain.  */
 	gcc_assert (regno < FIRST_PSEUDO_REGISTER);
 
-	nregs = hard_regno_nregs[regno][GET_MODE (x)];
+	nregs = REG_NREGS (x);
 
 	/* We can't substitute into multi-hard-reg uses.  */
 	if (nregs > 1)
 	  {
 	    while (--nregs >= 0)
 	      reg_state[regno + nregs].use_index = -1;
 	    return;
 	  }
@@ -1693,17 +1692,17 @@  move2add_record_mode (rtx reg)
   if (GET_CODE (reg) == SUBREG)
     {
       regno = subreg_regno (reg);
       nregs = subreg_nregs (reg);
     }
   else if (REG_P (reg))
     {
       regno = REGNO (reg);
-      nregs = hard_regno_nregs[regno][mode];
+      nregs = REG_NREGS (reg);
     }
   else
     gcc_unreachable ();
   for (int i = nregs - 1; i > 0; i--)
     reg_mode[regno + i] = BLKmode;
   reg_mode[regno] = mode;
 }
 
@@ -2133,17 +2132,17 @@  reload_cse_move2add (rtx_insn *first)
 	      && GET_CODE (cnd) == NE
 	      && REG_P (XEXP (cnd, 0))
 	      && !reg_set_p (XEXP (cnd, 0), insn)
 	      /* The following two checks, which are also in
 		 move2add_note_store, are intended to reduce the
 		 number of calls to gen_rtx_SET to avoid memory
 		 allocation if possible.  */
 	      && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0)))
-	      && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1
+	      && REG_NREGS (XEXP (cnd, 0)) == 1
 	      && CONST_INT_P (XEXP (cnd, 1)))
 	    {
 	      rtx implicit_set =
 		gen_rtx_SET (XEXP (cnd, 0), XEXP (cnd, 1));
 	      move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
 	    }
 	}
 
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/reg-stack.c	2015-05-18 08:19:43.467431478 +0100
@@ -1475,18 +1475,17 @@  subst_stack_regs_pat (rtx_insn *insn, st
 	  {
 	  case COMPARE:
 	    compare_for_stack_reg (insn, regstack, pat_src);
 	    break;
 
 	  case CALL:
 	    {
 	      int count;
-	      for (count = hard_regno_nregs[REGNO (*dest)][GET_MODE (*dest)];
-		   --count >= 0;)
+	      for (count = REG_NREGS (*dest); --count >= 0;)
 		{
 		  regstack->reg[++regstack->top] = REGNO (*dest) + count;
 		  SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);
 		}
 	    }
 	    replace_reg (dest, FIRST_STACK_REG);
 	    break;
 
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/regcprop.c	2015-05-18 08:19:43.467431478 +0100
@@ -202,22 +202,17 @@  kill_value (const_rtx x, struct value_da
 {
   if (GET_CODE (x) == SUBREG)
     {
       rtx tmp = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
 				 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
       x = tmp ? tmp : SUBREG_REG (x);
     }
   if (REG_P (x))
-    {
-      unsigned int regno = REGNO (x);
-      unsigned int n = hard_regno_nregs[regno][GET_MODE (x)];
-
-      kill_value_regno (regno, n, vd);
-    }
+    kill_value_regno (REGNO (x), REG_NREGS (x), vd);
 }
 
 /* Remember that REGNO is valid in MODE.  */
 
 static void
 set_value_regno (unsigned int regno, machine_mode mode,
 		 struct value_data *vd)
 {
@@ -328,18 +323,18 @@  copy_value (rtx dest, rtx src, struct va
 
   /* Do not propagate copies to fixed or global registers, patterns
      can be relying to see particular fixed register or users can
      expect the chosen global register in asm.  */
   if (fixed_regs[dr] || global_regs[dr])
     return;
 
   /* If SRC and DEST overlap, don't record anything.  */
-  dn = hard_regno_nregs[dr][GET_MODE (dest)];
-  sn = hard_regno_nregs[sr][GET_MODE (dest)];
+  dn = REG_NREGS (dest);
+  sn = REG_NREGS (src);
   if ((dr > sr && dr < sr + sn)
       || (sr > dr && sr < dr + dn))
     return;
 
   /* If SRC had no assigned mode (i.e. we didn't know it was live)
      assign it now and assume the value came from an input argument
      or somesuch.  */
   if (vd->e[sr].mode == VOIDmode)
@@ -1030,18 +1025,17 @@  copyprop_hardreg_forward_1 (basic_block
 	      if (GET_CODE (x) == SET)
 		{
 		  rtx dest = SET_DEST (x);
 		  kill_value (dest, vd);
 		  set_value_regno (REGNO (dest), GET_MODE (dest), vd);
 		  copy_value (dest, SET_SRC (x), vd);
 		  ksvd.ignore_set_reg = dest;
 		  set_regno = REGNO (dest);
-		  set_nregs
-		    = hard_regno_nregs[set_regno][GET_MODE (dest)];
+		  set_nregs = REG_NREGS (dest);
 		  break;
 		}
 	    }
 
 	  get_call_reg_set_usage (insn,
 				  &regs_invalidated_by_this_call,
 				  regs_invalidated_by_call);
 	  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/regrename.c	2015-05-18 08:19:43.467431478 +0100
@@ -978,17 +978,17 @@  regrename_do_replace (struct du_head *he
 verify_reg_in_set (rtx op, HARD_REG_SET *pset)
 {
   unsigned regno, nregs;
   bool all_live, all_dead;
   if (!REG_P (op))
     return false;
 
   regno = REGNO (op);
-  nregs = hard_regno_nregs[regno][GET_MODE (op)];
+  nregs = REG_NREGS (op);
   all_live = all_dead = true;
   while (nregs-- > 0)
     if (TEST_HARD_REG_BIT (*pset, regno + nregs))
       all_dead = false;
     else
       all_live = false;
   if (!all_dead && !all_live)
     {
@@ -1031,19 +1031,18 @@  note_sets_clobbers (rtx x, const_rtx set
 }
 
 static void
 scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
 	      enum op_type type)
 {
   struct du_head **p;
   rtx x = *loc;
-  machine_mode mode = GET_MODE (x);
   unsigned this_regno = REGNO (x);
-  int this_nregs = hard_regno_nregs[this_regno][mode];
+  int this_nregs = REG_NREGS (x);
 
   if (action == mark_write)
     {
       if (type == OP_OUT)
 	create_new_chain (this_regno, this_nregs, loc, insn, cl);
       return;
     }
 
@@ -1619,23 +1618,18 @@  build_def_use (basic_block bb)
 		    }
 		}
 	      /* If there's an in-out operand with a register that is not
 		 being tracked at all yet, open a chain.  */
 	      if (recog_data.operand_type[i] == OP_INOUT
 		  && !(untracked_operands & (1 << i))
 		  && REG_P (op)
 		  && !verify_reg_tracked (op))
-		{
-		  machine_mode mode = GET_MODE (op);
-		  unsigned this_regno = REGNO (op);
-		  unsigned this_nregs = hard_regno_nregs[this_regno][mode];
-		  create_new_chain (this_regno, this_nregs, NULL, NULL,
-				    NO_REGS);
-		}
+		create_new_chain (REGNO (op), REG_NREGS (op), NULL, NULL,
+				  NO_REGS);
 	    }
 
 	  if (fail_current_block)
 	    break;
 
 	  /* Step 1a: Mark hard registers that are clobbered in this insn,
 	     outside an operand, as live.  */
 	  hide_operands (n_ops, old_operands, old_dups, untracked_operands,
Index: gcc/sched-deps.c
===================================================================
--- gcc/sched-deps.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/sched-deps.c	2015-05-18 08:19:43.467431478 +0100
@@ -2120,18 +2120,17 @@  mark_insn_reg_birth (rtx insn, rtx reg,
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
 
   if (! REG_P (reg))
     return;
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    mark_insn_hard_regno_birth (insn, regno,
-				hard_regno_nregs[regno][GET_MODE (reg)],
+    mark_insn_hard_regno_birth (insn, regno, REG_NREGS (reg),
 				clobber_p, unused_p);
   else
     mark_insn_pseudo_birth (insn, regno, clobber_p, unused_p);
 }
 
 /* Update the register pressure info after death of pseudo register
    REGNO.  */
 static void
@@ -2180,17 +2179,17 @@  mark_reg_death (rtx reg)
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
 
   if (! REG_P (reg))
     return;
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    mark_hard_regno_death (regno, hard_regno_nregs[regno][GET_MODE (reg)]);
+    mark_hard_regno_death (regno, REG_NREGS (reg));
   else
     mark_pseudo_death (regno);
 }
 
 /* Process SETTER of REG.  DATA is an insn containing the setter.  */
 static void
 mark_insn_reg_store (rtx reg, const_rtx setter, void *data)
 {
@@ -3640,17 +3639,17 @@  deps_analyze_insn (struct deps_desc *dep
 	  && REG_P (XEXP (t, 0))
 	  && CONSTANT_P (XEXP (t, 1)))
 	{
 	  unsigned int regno;
 	  int nregs;
 	  rtx_insn_list *cond_deps = NULL;
 	  t = XEXP (t, 0);
 	  regno = REGNO (t);
-	  nregs = hard_regno_nregs[regno][GET_MODE (t)];
+	  nregs = REG_NREGS (t);
 	  while (nregs-- > 0)
 	    {
 	      struct deps_reg *reg_last = &deps->reg_last[regno + nregs];
 	      cond_deps = concat_INSN_LIST (reg_last->sets, cond_deps);
 	      cond_deps = concat_INSN_LIST (reg_last->clobbers, cond_deps);
 	      cond_deps = concat_INSN_LIST (reg_last->implicit_sets, cond_deps);
 	    }
 	  INSN_COND_DEPS (insn) = cond_deps;
Index: gcc/sched-rgn.c
===================================================================
--- gcc/sched-rgn.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/sched-rgn.c	2015-05-18 08:19:43.467431478 +0100
@@ -1715,17 +1715,17 @@  check_live_1 (int src, rtx x)
       /* Global registers are assumed live.  */
       return 0;
     }
   else
     {
       if (regno < FIRST_PSEUDO_REGISTER)
 	{
 	  /* Check for hard registers.  */
-	  int j = hard_regno_nregs[regno][GET_MODE (reg)];
+	  int j = REG_NREGS (reg);
 	  while (--j >= 0)
 	    {
 	      for (i = 0; i < candidate_table[src].split_bbs.nr_members; i++)
 		{
 		  basic_block b = candidate_table[src].split_bbs.first_member[i];
 		  int t = bitmap_bit_p (&not_in_df, b->index);
 
 		  /* We can have split blocks, that were recently generated.
@@ -1798,18 +1798,17 @@  update_live_1 (int src, rtx x)
   if (! HARD_REGISTER_NUM_P (regno)
       || !global_regs[regno])
     {
       for (i = 0; i < candidate_table[src].update_bbs.nr_members; i++)
 	{
 	  basic_block b = candidate_table[src].update_bbs.first_member[i];
 
 	  if (HARD_REGISTER_NUM_P (regno))
-	    bitmap_set_range (df_get_live_in (b), regno,
-			      hard_regno_nregs[regno][GET_MODE (reg)]);
+	    bitmap_set_range (df_get_live_in (b), regno, REG_NREGS (reg));
 	  else
 	    bitmap_set_bit (df_get_live_in (b), regno);
 	}
     }
 }
 
 /* Return 1 if insn can be speculatively moved from block src to trg,
    otherwise return 0.  Called before first insertion of insn to
Index: gcc/sel-sched.c
===================================================================
--- gcc/sel-sched.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/sel-sched.c	2015-05-18 08:19:43.471431430 +0100
@@ -820,19 +820,17 @@  count_occurrences_equiv (const_rtx what,
   subrtx_iterator::array_type array;
   FOR_EACH_SUBRTX (iter, array, where, NONCONST)
     {
       const_rtx x = *iter;
       if (REG_P (x) && REGNO (x) == REGNO (what))
 	{
 	  /* Bail out if mode is different or more than one register is
 	     used.  */
-	  if (GET_MODE (x) != GET_MODE (what)
-	      || (HARD_REGISTER_P (x)
-		  && hard_regno_nregs[REGNO (x)][GET_MODE (x)] > 1))
+	  if (GET_MODE (x) != GET_MODE (what) || REG_NREGS (x) > 1)
 	    return 0;
 	  count += 1;
 	}
       else if (GET_CODE (x) == SUBREG
 	       && (!REG_P (SUBREG_REG (x))
 		   || REGNO (SUBREG_REG (x)) == REGNO (what)))
 	/* ??? Do not support substituting regs inside subregs.  In that case,
 	   simplify_subreg will be called by validate_replace_rtx, and
Index: gcc/valtrack.c
===================================================================
--- gcc/valtrack.c	2015-05-18 08:19:43.475431381 +0100
+++ gcc/valtrack.c	2015-05-18 08:19:43.471431430 +0100
@@ -666,19 +666,17 @@  dead_debug_insert_temp (struct dead_debu
 	  /* Hmm...  Something's fishy, we should be setting REG here.  */
 	  if (REGNO (dest) != REGNO (reg))
 	    breg = NULL;
 	  /* If we're not overwriting all the hardware registers that
 	     setting REG in its mode would, we won't know what to bind
 	     the debug temp to.  ??? We could bind the debug_expr to a
 	     CONCAT or PARALLEL with the split multi-registers, and
 	     replace them as we found the corresponding sets.  */
-	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
-		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
-		       != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
+	  else if (REG_NREGS (reg) != REG_NREGS (dest))
 	    breg = NULL;
 	  /* Ok, it's the same (hardware) REG, but with a different
 	     mode, so SUBREG it.  */
 	  else
 	    breg = debug_lowpart_subreg (GET_MODE (reg),
 					 cleanup_auto_inc_dec (src, VOIDmode),
 					 GET_MODE (dest));
 	}
@@ -690,17 +688,17 @@  dead_debug_insert_temp (struct dead_debu
 	  /* Lose if we're setting something other than the lowpart of
 	     REG.  */
 	  else if (!subreg_lowpart_p (dest))
 	    breg = NULL;
 	  /* If we're not overwriting all the hardware registers that
 	     setting REG in its mode would, we won't know what to bind
 	     the debug temp to.  */
 	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
-		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
+		   && (REG_NREGS (reg)
 		       != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
 	    breg = NULL;
 	  /* Yay, we can use SRC, just adjust its mode.  */
 	  else
 	    breg = debug_lowpart_subreg (GET_MODE (reg),
 					 cleanup_auto_inc_dec (src, VOIDmode),
 					 GET_MODE (dest));
 	}