public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [0/9] Record number of hard registers in a REG
@ 2015-05-18 18:11 Richard Sandiford
  2015-05-18 18:13 ` [1/9] Make more use of END_REGNO Richard Sandiford
                   ` (9 more replies)
  0 siblings, 10 replies; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:11 UTC (permalink / raw)
  To: gcc-patches

While looking at a profile of gcc, I noticed one thing fairly high
up the list was a loop iterating over all the registers in a REG,
apparently due to the delay in computing the index for hard_regno_nregs
and then loading the value (which would often be an L1 cache miss).

When we were adding CONST_WIDE_INT, the general opinion seemed to be
that we should lay out rtxes for LP64 hosts rather than try to have two
alternative layouts, one optimised for ILP32 and one for LP64.  We therefore
unconditionally filled the 32-bit hole (on LP64) between the rtx header and
the main union with extra data.  That area is already used by REGs to store
ORIGINAL_REGNO, but on LP64 hosts there's another hole in the REGNO
field itself.  This series takes that idea a step further and uses the
hole to store the number of registers in a REG.

This still leaves 24 redundant bits that could be used for other things
in future.  That's actually enough to store a SUBREG of a REG (8 bits
for the inner mode, 16 for the offset), but having a single rtx for that
would probably cause too many problems.

The series sped up an --enable-checking=release gcc by just over 0.5%
for various tests on my box.  Not a big saving, but hopefully the
patches also count as a clean-up.

As a follow-on, I'd like to add a FOR_EACH_* macro that iterates over
all the registers in a REG.  These loops always execute at least once,
and rarely more than once, and it would be good to model that in the
iterator so that all use sites benefit.

Each patch in the series was individually bootstrapped & regression-tested
on x86_64-linux-gnu.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [1/9] Make more use of END_REGNO
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
@ 2015-05-18 18:13 ` Richard Sandiford
  2015-05-18 19:06   ` Jeff Law
  2015-05-18 18:15 ` [2/9] Add a REG_NREGS macro Richard Sandiford
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:13 UTC (permalink / raw)
  To: gcc-patches

This patch just handles some obvious cases where END_REGNO could be used.


gcc/
	* cfgcleanup.c (mentions_nonequal_regs): Use END_REGNO.
	* dse.c (note_add_store): Likewise.
	* ira-lives.c (mark_hard_reg_dead): Likewise.
	* loop-invariant.c (mark_reg_store): Likewise.
	(mark_reg_death): Likewise.
	* postreload.c (reload_combine): Likewise.
	(reload_combine_note_store): Likewise.
	(reload_combine_note_use): Likewise.
	* recog.c (peep2_reg_dead_p): Likewise.

Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/cfgcleanup.c	2015-05-18 08:19:52.000000000 +0100
@@ -267,26 +267,20 @@ mark_effect (rtx exp, regset nonequal)
 mentions_nonequal_regs (const_rtx x, regset nonequal)
 {
   subrtx_iterator::array_type array;
   FOR_EACH_SUBRTX (iter, array, x, NONCONST)
     {
       const_rtx x = *iter;
       if (REG_P (x))
 	{
-	  unsigned int regno = REGNO (x);
-	  if (REGNO_REG_SET_P (nonequal, regno))
-	    return true;
-	  if (regno < FIRST_PSEUDO_REGISTER)
-	    {
-	      int n = hard_regno_nregs[regno][GET_MODE (x)];
-	      while (--n > 0)
-		if (REGNO_REG_SET_P (nonequal, regno + n))
-		  return true;
-	    }
+	  unsigned int end_regno = END_REGNO (x);
+	  for (unsigned int regno = REGNO (x); regno < end_regno; ++regno)
+	    if (REGNO_REG_SET_P (nonequal, regno))
+	      return true;
 	}
     }
   return false;
 }
 
 /* Attempt to prove that the basic block B will have no side effects and
    always continues in the same edge if reached via E.  Return the edge
    if exist, NULL otherwise.  */
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/dse.c	2015-05-18 08:19:52.000000000 +0100
@@ -850,17 +850,16 @@ typedef struct
 /* Callback for emit_inc_dec_insn_before via note_stores.
    Check if a register is clobbered which is live afterwards.  */
 
 static void
 note_add_store (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *data)
 {
   rtx_insn *insn;
   note_add_store_info *info = (note_add_store_info *) data;
-  int r, n;
 
   if (!REG_P (loc))
     return;
 
   /* If this register is referenced by the current or an earlier insn,
      that's OK.  E.g. this applies to the register that is being incremented
      with this addition.  */
   for (insn = info->first;
@@ -869,25 +868,24 @@ note_add_store (rtx loc, const_rtx expr
     if (reg_referenced_p (loc, PATTERN (insn)))
       return;
 
   /* If we come here, we have a clobber of a register that's only OK
      if that register is not live.  If we don't have liveness information
      available, fail now.  */
   if (!info->fixed_regs_live)
     {
-      info->failure =  true;
+      info->failure = true;
       return;
     }
   /* Now check if this is a live fixed register.  */
-  r = REGNO (loc);
-  n = hard_regno_nregs[r][GET_MODE (loc)];
-  while (--n >=  0)
-    if (REGNO_REG_SET_P (info->fixed_regs_live, r+n))
-      info->failure =  true;
+  unsigned int end_regno = END_REGNO (loc);
+  for (unsigned int regno = REGNO (loc); regno < end_regno; ++regno)
+    if (REGNO_REG_SET_P (info->fixed_regs_live, regno))
+      info->failure = true;
 }
 
 /* Callback for for_each_inc_dec that emits an INSN that sets DEST to
    SRC + SRCOFF before insn ARG.  */
 
 static int
 emit_inc_dec_insn_before (rtx mem ATTRIBUTE_UNUSED,
 			  rtx op ATTRIBUTE_UNUSED,
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/ira-lives.c	2015-05-18 08:19:52.000000000 +0100
@@ -473,17 +473,17 @@ mark_pseudo_regno_subword_dead (int regn
    register.  */
 static void
 mark_hard_reg_dead (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))
 	    {
 	      aclass = ira_hard_regno_allocno_class[regno];
 	      pclass = ira_pressure_class_translate[aclass];
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/loop-invariant.c	2015-05-18 08:19:38.719489341 +0100
@@ -1802,68 +1802,44 @@ mark_regno_death (int regno)
   change_pressure (regno, false);
 }
 
 /* Mark setting register REG.  */
 static void
 mark_reg_store (rtx reg, const_rtx setter ATTRIBUTE_UNUSED,
 		void *data ATTRIBUTE_UNUSED)
 {
-  int regno;
-
   if (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
 
   if (! REG_P (reg))
     return;
 
   regs_set[n_regs_set++] = reg;
 
-  regno = REGNO (reg);
-
-  if (regno >= FIRST_PSEUDO_REGISTER)
+  unsigned int end_regno = END_REGNO (reg);
+  for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
     mark_regno_live (regno);
-  else
-    {
-      int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-
-      while (regno < last)
-	{
-	  mark_regno_live (regno);
-	  regno++;
-	}
-    }
 }
 
 /* Mark clobbering register REG.  */
 static void
 mark_reg_clobber (rtx reg, const_rtx setter, void *data)
 {
   if (GET_CODE (setter) == CLOBBER)
     mark_reg_store (reg, setter, data);
 }
 
 /* Mark register REG death.  */
 static void
 mark_reg_death (rtx reg)
 {
-  int regno = REGNO (reg);
-
-  if (regno >= FIRST_PSEUDO_REGISTER)
+  unsigned int end_regno = END_REGNO (reg);
+  for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
     mark_regno_death (regno);
-  else
-    {
-      int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
-
-      while (regno < last)
-	{
-	  mark_regno_death (regno);
-	  regno++;
-	}
-    }
 }
 
 /* Mark occurrence of registers in X for the current loop.  */
 static void
 mark_ref_regs (rtx x)
 {
   RTX_CODE code;
   int i;
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/postreload.c	2015-05-18 08:19:52.000000000 +0100
@@ -1372,22 +1372,18 @@ reload_combine (void)
 	  for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
 	       link = XEXP (link, 1))
 	    {
 	      rtx setuse = XEXP (link, 0);
 	      rtx usage_rtx = XEXP (setuse, 0);
 	      if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER)
 		  && REG_P (usage_rtx))
 	        {
-		  unsigned int i;
-		  unsigned int start_reg = REGNO (usage_rtx);
-		  unsigned int num_regs
-		    = hard_regno_nregs[start_reg][GET_MODE (usage_rtx)];
-		  unsigned int end_reg = start_reg + num_regs - 1;
-		  for (i = start_reg; i <= end_reg; i++)
+		  unsigned int end_regno = END_REGNO (usage_rtx);
+		  for (unsigned int i = REGNO (usage_rtx); i < end_regno; ++i)
 		    if (GET_CODE (XEXP (link, 0)) == CLOBBER)
 		      {
 		        reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
 		        reg_state[i].store_ruid = reload_combine_ruid;
 		      }
 		    else
 		      reg_state[i].use_index = -1;
 	         }
@@ -1459,19 +1455,18 @@ reload_combine_note_store (rtx dst, cons
 
   if (MEM_P (dst))
     {
       dst = XEXP (dst, 0);
       if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
 	  || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC
 	  || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY)
 	{
-	  regno = REGNO (XEXP (dst, 0));
-	  mode = GET_MODE (XEXP (dst, 0));
-	  for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
+	  unsigned int end_regno = END_REGNO (XEXP (dst, 0));
+	  for (unsigned int i = REGNO (XEXP (dst, 0)); i < end_regno; ++i)
 	    {
 	      /* We could probably do better, but for now mark the register
 		 as used in an unknown fashion and set/clobbered at this
 		 insn.  */
 	      reg_state[i].use_index = -1;
 	      reg_state[i].store_ruid = reload_combine_ruid;
 	      reg_state[i].real_store_ruid = reload_combine_ruid;
 	    }
@@ -1531,23 +1526,21 @@ reload_combine_note_use (rtx *xp, rtx_in
 	  return;
 	}
       break;
 
     case USE:
       /* If this is the USE of a return value, we can't change it.  */
       if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
 	{
-	/* Mark the return register as used in an unknown fashion.  */
+	  /* Mark the return register as used in an unknown fashion.  */
 	  rtx reg = XEXP (x, 0);
-	  int regno = REGNO (reg);
-	  int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
-
-	  while (--nregs >= 0)
-	    reg_state[regno + nregs].use_index = -1;
+	  unsigned int end_regno = END_REGNO (reg);
+	  for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
+	    reg_state[regno].use_index = -1;
 	  return;
 	}
       break;
 
     case CLOBBER:
       if (REG_P (SET_DEST (x)))
 	{
 	  /* No spurious CLOBBERs of pseudo registers may remain.  */
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	2015-05-18 08:19:38.719489341 +0100
+++ gcc/recog.c	2015-05-18 08:19:38.719489341 +0100
@@ -3123,28 +3123,25 @@ peep2_regno_dead_p (int ofs, int regno)
   return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
 }
 
 /* Similarly for a REG.  */
 
 int
 peep2_reg_dead_p (int ofs, rtx reg)
 {
-  int regno, n;
-
   gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
 
   ofs = peep2_buf_position (peep2_current + ofs);
 
   gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
 
-  regno = REGNO (reg);
-  n = hard_regno_nregs[regno][GET_MODE (reg)];
-  while (--n >= 0)
-    if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
+  unsigned int end_regno = END_REGNO (reg);
+  for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
+    if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno))
       return 0;
   return 1;
 }
 
 /* Regno offset to be used in the register search.  */
 static int search_ofs;
 
 /* Try to find a hard register of mode MODE, matching the register class in

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [2/9] Add a REG_NREGS macro
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
  2015-05-18 18:13 ` [1/9] Make more use of END_REGNO Richard Sandiford
@ 2015-05-18 18:15 ` Richard Sandiford
  2015-05-18 20:27   ` Jeff Law
  2015-05-18 18:19 ` [3/9] Clean up df_ref_change_reg_with_loc Richard Sandiford
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:15 UTC (permalink / raw)
  To: gcc-patches

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.

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
 \f
 /* 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));
 	}

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [3/9] Clean up df_ref_change_reg_with_loc
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
  2015-05-18 18:13 ` [1/9] Make more use of END_REGNO Richard Sandiford
  2015-05-18 18:15 ` [2/9] Add a REG_NREGS macro Richard Sandiford
@ 2015-05-18 18:19 ` Richard Sandiford
  2015-05-18 20:33   ` Jeff Law
  2015-05-18 18:22 ` [4/9] Add a dedicated rtx union member for REGs Richard Sandiford
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:19 UTC (permalink / raw)
  To: gcc-patches

This patch cleans up the interface to df_ref_change_reg_with_loc.
The function is used only by SET_REGNO_RAW, so the old regno is
always REGNO (x) and the caller always goes on to set REGNO.
(And the fuction doesn't make much sense otherwise.)

The patch therefore gets df_ref_change_reg_with_loc to work out the old
regno itself and to install the new register number once it's done.

The check for the old register being -1 was redundant.  Only expr.c
and postreload.c create -1 registers ("fixed" in a later patch).
Both sites are just creating temporary registers in order to query
backend hooks and neither site needs the check.  expr.c does use
SET_REGNO and so does go through this function, but only at a time
when there's no df information.  (And it wouldn't work if the df
machinery were set up, since any change after the first would
look like a "normal" change.)  postreload.c uses SET_REGNO_RAW
and so bypasses the code altogether.

expr.c bypasses the code too by the end of the series.


gcc/
	* df.h (df_ref_change_reg_with_loc): Remove old_regno parameter.
	Change type of new_regno to unsigned int.
	* df-scan.c (df_ref_change_reg_with_loc_1): Change type of
	new_regno to unsigned int.
	(df_ref_change_reg_with_loc): Remove old_regno parameter.
	Change type of new_regno to unsigned int.  Use SET_REGNO_RAW.
	* rtl.h (SET_REGNO): Update call to df_ref_change_reg_with_loc.
	(SET_REGNO_RAW): Add space after ",".

Index: gcc/df.h
===================================================================
--- gcc/df.h	2015-05-18 07:53:09.890871253 +0100
+++ gcc/df.h	2015-05-18 07:53:09.890871253 +0100
@@ -1049,7 +1049,7 @@ extern void df_recompute_luids (basic_bl
 extern void df_insn_change_bb (rtx_insn *, basic_block);
 extern void df_maybe_reorganize_use_refs (enum df_ref_order);
 extern void df_maybe_reorganize_def_refs (enum df_ref_order);
-extern void df_ref_change_reg_with_loc (int, int, rtx);
+extern void df_ref_change_reg_with_loc (rtx, unsigned int);
 extern void df_notes_rescan (rtx_insn *);
 extern void df_hard_reg_init (void);
 extern void df_update_entry_block_defs (void);
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2015-05-18 07:53:09.890871253 +0100
+++ gcc/df-scan.c	2015-05-18 07:53:09.890871253 +0100
@@ -1819,7 +1819,7 @@ df_insn_change_bb (rtx_insn *insn, basic
 static void
 df_ref_change_reg_with_loc_1 (struct df_reg_info *old_df,
 			      struct df_reg_info *new_df,
-			      int new_regno, rtx loc)
+			      unsigned int new_regno, rtx loc)
 {
   df_ref the_ref = old_df->reg_chain;
 
@@ -1904,25 +1904,33 @@ df_ref_change_reg_with_loc_1 (struct df_
 }
 
 
-/* Change the regno of all refs that contained LOC from OLD_REGNO to
-   NEW_REGNO.  Refs that do not match LOC are not changed which means
-   that artificial refs are not changed since they have no loc.  This
-   call is to support the SET_REGNO macro. */
+/* Change the regno of register LOC to NEW_REGNO and update the df
+   information accordingly.  Refs that do not match LOC are not changed
+   which means that artificial refs are not changed since they have no loc.
+   This call is to support the SET_REGNO macro. */
 
 void
-df_ref_change_reg_with_loc (int old_regno, int new_regno, rtx loc)
+df_ref_change_reg_with_loc (rtx loc, unsigned int new_regno)
 {
-  if ((!df) || (old_regno == -1) || (old_regno == new_regno))
+  unsigned int old_regno = REGNO (loc);
+  if (old_regno == new_regno)
     return;
 
-  df_grow_reg_info ();
+  if (df)
+    {
+      df_grow_reg_info ();
 
-  df_ref_change_reg_with_loc_1 (DF_REG_DEF_GET (old_regno),
-				DF_REG_DEF_GET (new_regno), new_regno, loc);
-  df_ref_change_reg_with_loc_1 (DF_REG_USE_GET (old_regno),
-				DF_REG_USE_GET (new_regno), new_regno, loc);
-  df_ref_change_reg_with_loc_1 (DF_REG_EQ_USE_GET (old_regno),
-				DF_REG_EQ_USE_GET (new_regno), new_regno, loc);
+      df_ref_change_reg_with_loc_1 (DF_REG_DEF_GET (old_regno),
+				    DF_REG_DEF_GET (new_regno),
+				    new_regno, loc);
+      df_ref_change_reg_with_loc_1 (DF_REG_USE_GET (old_regno),
+				    DF_REG_USE_GET (new_regno),
+				    new_regno, loc);
+      df_ref_change_reg_with_loc_1 (DF_REG_EQ_USE_GET (old_regno),
+				    DF_REG_EQ_USE_GET (new_regno),
+				    new_regno, loc);
+    }
+  SET_REGNO_RAW (loc, new_regno);
 }
 
 
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-18 07:53:09.890871253 +0100
+++ gcc/rtl.h	2015-05-18 07:53:09.886871176 +0100
@@ -1693,9 +1693,8 @@ #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)
+#define SET_REGNO(RTX, N) (df_ref_change_reg_with_loc (RTX, 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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [4/9] Add a dedicated rtx union member for REGs
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (2 preceding siblings ...)
  2015-05-18 18:19 ` [3/9] Clean up df_ref_change_reg_with_loc Richard Sandiford
@ 2015-05-18 18:22 ` Richard Sandiford
  2015-05-18 20:41   ` Jeff Law
  2015-05-18 18:23 ` [5/9] Create sensible dummy registers Richard Sandiford
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:22 UTC (permalink / raw)
  To: gcc-patches

This patch replaces the current REG "i0" format with a dedicated structure,
so that we can make use of the extra 32 bits in the "i" field.

Of the places that iterate on formats and do something for 'i's,
most already handled REGs specially before the format walk and
so don't need to check for 'r'.  Otherwise it's mostly just a case
of adding dummy 'r' cases in order avoid the default gcc_unreachable ()
(in cases where we do the same for 'i').  The main exceptions are the
cselib.c and lra-constraints.c changes.

final.c:leaf_renumber_regs_insn handled REGs specially but then
went on to do a no-op walk of the format.  I just added an early
exit instead of an empty 'r' case.


gcc/
	* rtl.def (REG): Change format to "r".
	* rtl.h (rtunion): Remove rt_reg.
	(reg_info): New structure.
	(rtx_def): Add reg field to main union.
	(X0REGATTR): Delete.
	(REG_CHECK): New macro.
	(SET_REGNO_RAW, rhs_regno, REG_ATTRS): Use it.
	* rtl.c (rtx_format): Document "r".
	(rtx_code_size): Handle REG specially.
	* gengenrtl.c (special_format): Return true for formats
	that include 'r'.
	* gengtype.c (adjust_field_rtx_def): Handle 'r' fields.
	Deal with REG_ATTRS after the field loop.
	* emit-rtl.c (gen_raw_REG): Call rtx_alloc_stat directly.
	* expmed.c (init_expmed): Call gen_raw_REG instead of
	gen_rtx_raw_REG.
	* expr.c (init_expr_target): Likewise.
	* regcprop.c (maybe_mode_change): Likewise.
	* varasm.c (make_decl_rtl): Likewise.
	* final.c (leaf_renumber_regs_insn): Return early after
	handling REGs.
	* genemit.c (gen_exp): Handle 'r' fields.
	* genpeep.c (match_rtx): Likewise.
	* gensupport.c (subst_pattern_match): Likewise.
	(get_alternatives_number, collect_insn_data, alter_predicate_for_insn)
	(alter_constraints, subst_dup): Likewise.
	* read-rtl.c (read_rtx_code): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* genrecog.c (find_operand, find_matching_operand): Likewise.
	(validate_pattern, match_pattern_2): Likewise.
	(parameter::UINT, rtx_test::REGNO_FIELD): New enum values.
	(rtx_test::regno_field): New function.
	(operator ==, safe_to_hoist_p, transition_parameter_type)
	(parameter_type_string, print_parameter_value)
	(print_nonbool_test, print_test): Handle new enum values.
	* cselib.c (rtx_equal_for_cselib_1): Handle REG specially.
	* lra-constraints.c (operands_match_p): Likewise.

Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def	2015-05-18 07:53:15.014808321 +0100
+++ gcc/rtl.def	2015-05-18 07:53:15.010808427 +0100
@@ -381,7 +381,7 @@ DEF_RTL_EXPR(PC, "pc", "", RTX_OBJ)
    points to a reg_attrs structure.
    This rtx needs to have as many (or more) fields as a MEM, since we
    can change REG rtx's into MEMs during reload.  */
-DEF_RTL_EXPR(REG, "reg", "i0", RTX_OBJ)
+DEF_RTL_EXPR(REG, "reg", "r", RTX_OBJ)
 
 /* A scratch register.  This represents a register used only within a
    single insn.  It will be replaced by a REG during register allocation
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-18 07:53:15.014808321 +0100
+++ gcc/rtl.h	2015-05-18 07:53:15.014808321 +0100
@@ -201,11 +201,21 @@ struct GTY((for_user)) reg_attrs {
   tree rt_tree;
   basic_block rt_bb;
   mem_attrs *rt_mem;
-  reg_attrs *rt_reg;
   struct constant_descriptor_rtx *rt_constant;
   struct dw_cfi_node *rt_cfi;
 };
 
+/* Describes the properties of a REG.  */
+struct GTY(()) reg_info {
+  /* The value of REGNO.  */
+  unsigned int regno;
+
+  unsigned int unused : 32;
+
+  /* The value of REG_ATTRS.  */
+  reg_attrs *attrs;
+};
+
 /* This structure remembers the position of a SYMBOL_REF within an
    object_block structure.  A SYMBOL_REF only provides this information
    if SYMBOL_REF_HAS_BLOCK_INFO_P is true.  */
@@ -395,6 +405,7 @@ struct GTY((desc("0"), tag("0"),
   union u {
     rtunion fld[1];
     HOST_WIDE_INT hwint[1];
+    struct reg_info reg;
     struct block_symbol block_sym;
     struct real_value rv;
     struct fixed_value fv;
@@ -1070,6 +1081,13 @@ #define XCNMPFV(RTX, C, M) __extension__
 				 __LINE__, __FUNCTION__);		\
    &_rtx->u.fv; })
 
+#define REG_CHECK(RTX) __extension__					\
+({ __typeof (RTX) const _rtx = (RTX);					\
+   if (GET_CODE (_rtx) != REG)						\
+     rtl_check_failed_code1 (_rtx, REG,  __FILE__, __LINE__,		\
+			     __FUNCTION__);				\
+   &_rtx->u.reg; })
+
 #define BLOCK_SYMBOL_CHECK(RTX) __extension__				\
 ({ __typeof (RTX) const _symbol = (RTX);				\
    const unsigned int flags = SYMBOL_REF_FLAGS (_symbol);		\
@@ -1124,6 +1142,7 @@ #define XCMWINT(RTX, N, C, M)	    ((RTX)
 #define XCNMWINT(RTX, N, C, M)	    ((RTX)->u.hwint[N])
 #define XCNMPRV(RTX, C, M)	    (&(RTX)->u.rv)
 #define XCNMPFV(RTX, C, M)	    (&(RTX)->u.fv)
+#define REG_CHECK(RTX)		    (&(RTX)->u.reg)
 #define BLOCK_SYMBOL_CHECK(RTX)	    (&(RTX)->u.block_sym)
 #define HWIVEC_CHECK(RTX,C)	    (&(RTX)->u.hwiv)
 
@@ -1248,7 +1267,6 @@ #define X0BBDEF(RTX, N)	   (RTL_CHECK1 (
 #define X0ADVFLAGS(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_addr_diff_vec_flags)
 #define X0CSELIB(RTX, N)   (RTL_CHECK1 (RTX, N, '0').rt_cselib)
 #define X0MEMATTR(RTX, N)  (RTL_CHECKC1 (RTX, N, MEM).rt_mem)
-#define X0REGATTR(RTX, N)  (RTL_CHECKC1 (RTX, N, REG).rt_reg)
 #define X0CONSTANT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_constant)
 
 /* Access a '0' field with any type.  */
@@ -1694,7 +1712,7 @@ #define LABEL_REF_LABEL(LABREF) XCEXP (L
    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 (RTX, N))
-#define SET_REGNO_RAW(RTX, N) (XCUINT (RTX, 0, REG) = N)
+#define SET_REGNO_RAW(RTX, N) (REG_CHECK (RTX)->regno = 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
@@ -1714,7 +1732,7 @@ #define ORIGINAL_REGNO(RTX) \
 static inline unsigned int
 rhs_regno (const_rtx x)
 {
-  return XCUINT (x, 0, REG);
+  return REG_CHECK (x)->regno;
 }
 
 
@@ -2271,7 +2289,7 @@ #define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1
 
 /* The register attribute block.  We provide access macros for each value
    in the block and provide defaults if none specified.  */
-#define REG_ATTRS(RTX) X0REGATTR (RTX, 1)
+#define REG_ATTRS(RTX) (REG_CHECK (RTX)->attrs)
 
 #ifndef GENERATOR_FILE
 /* For a MEM rtx, the alias set.  If 0, this MEM is not in any alias
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/rtl.c	2015-05-18 07:53:15.010808427 +0100
@@ -89,7 +89,8 @@ const char * const rtx_format[NUM_RTX_CO
          prints the uid of the insn.
      "b" is a pointer to a bitmap header.
      "B" is a basic block pointer.
-     "t" is a tree pointer.  */
+     "t" is a tree pointer.
+     "r" a register.  */
 
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
 #include "rtl.def"		/* rtl expressions are defined here */
@@ -112,6 +113,8 @@ #define DEF_RTL_EXPR(ENUM, NAME, FORMAT,
   (((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE			\
     || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT)		\
    ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT)	\
+   : (ENUM) == REG							\
+   ? RTX_HDR_SIZE + sizeof (reg_info)					\
    : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
 
 #include "rtl.def"
Index: gcc/gengenrtl.c
===================================================================
--- gcc/gengenrtl.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/gengenrtl.c	2015-05-18 07:53:15.006808572 +0100
@@ -113,7 +113,8 @@ special_format (const char *fmt)
   return (strchr (fmt, '*') != 0
 	  || strchr (fmt, 'V') != 0
 	  || strchr (fmt, 'S') != 0
-	  || strchr (fmt, 'n') != 0);
+	  || strchr (fmt, 'n') != 0
+	  || strchr (fmt, 'r') != 0);
 }
 
 /* Return true if CODE always has VOIDmode.  */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/gengtype.c	2015-05-18 07:53:15.010808427 +0100
@@ -1241,6 +1241,7 @@ adjust_field_rtx_def (type_p t, options_
 	    case 'i':
 	    case 'n':
 	    case 'w':
+	    case 'r':
 	      t = scalar_tp;
 	      subname = "rt_int";
 	      break;
@@ -1268,8 +1269,6 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == DEBUG_EXPR && aindex == 0)
 		t = tree_tp, subname = "rt_tree";
-	      else if (i == REG && aindex == 1)
-		t = reg_attrs_tp, subname = "rt_reg";
 	      else if (i == SYMBOL_REF && aindex == 1)
 		t = symbol_union_tp, subname = "";
 	      else if (i == JUMP_TABLE_DATA && aindex >= 4)
@@ -1344,6 +1343,9 @@ adjust_field_rtx_def (type_p t, options_
 				    "CONSTANT_POOL_ADDRESS_P (&%0)");
 	}
 
+      if (i == REG)
+	subfields = create_field (subfields, reg_attrs_tp, "reg.attrs");
+
       if (i == SYMBOL_REF)
 	{
 	  /* Add the "block_sym" field if SYMBOL_REF_HAS_BLOCK_INFO_P
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/emit-rtl.c	2015-05-18 07:53:15.006808572 +0100
@@ -437,7 +437,10 @@ gen_blockage (void)
 rtx
 gen_raw_REG (machine_mode mode, int regno)
 {
-  rtx x = gen_rtx_raw_REG (mode, regno);
+  rtx x = rtx_alloc_stat (REG PASS_MEM_STAT);
+  PUT_MODE (x, mode);
+  SET_REGNO_RAW (x, regno);
+  REG_ATTRS (x) = NULL;
   ORIGINAL_REGNO (x) = regno;
   return x;
 }
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/expmed.c	2015-05-18 07:53:15.006808572 +0100
@@ -260,7 +260,7 @@ init_expmed (void)
     }
 
   /* Avoid using hard regs in ways which may be unsupported.  */
-  all.reg = gen_rtx_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1);
+  all.reg = gen_raw_REG (mode, LAST_VIRTUAL_REGISTER + 1);
   all.plus = gen_rtx_PLUS (mode, all.reg, all.reg);
   all.neg = gen_rtx_NEG (mode, all.reg);
   all.mult = gen_rtx_MULT (mode, all.reg, all.reg);
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/expr.c	2015-05-18 07:53:15.006808572 +0100
@@ -258,7 +258,7 @@ init_expr_target (void)
 	  }
     }
 
-  mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
+  mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER));
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/regcprop.c	2015-05-18 07:53:15.010808427 +0100
@@ -410,7 +410,7 @@ maybe_mode_change (machine_mode orig_mod
     return NULL_RTX;
 
   if (orig_mode == new_mode)
-    return gen_rtx_raw_REG (new_mode, regno);
+    return gen_raw_REG (new_mode, regno);
   else if (mode_change_ok (orig_mode, new_mode, regno))
     {
       int copy_nregs = hard_regno_nregs[copy_regno][copy_mode];
@@ -426,7 +426,7 @@ maybe_mode_change (machine_mode orig_mod
 		+ (BYTES_BIG_ENDIAN ? byteoffset : 0));
       regno += subreg_regno_offset (regno, orig_mode, offset, new_mode);
       if (HARD_REGNO_MODE_OK (regno, new_mode))
-	return gen_rtx_raw_REG (new_mode, regno);
+	return gen_raw_REG (new_mode, regno);
     }
   return NULL_RTX;
 }
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/varasm.c	2015-05-18 07:53:15.014808321 +0100
@@ -1429,7 +1429,7 @@ make_decl_rtl (tree decl)
 	     confused with that register and be eliminated.  This usage is
 	     somewhat suspect...  */
 
-	  SET_DECL_RTL (decl, gen_rtx_raw_REG (mode, reg_number));
+	  SET_DECL_RTL (decl, gen_raw_REG (mode, reg_number));
 	  ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
 	  REG_USERVAR_P (DECL_RTL (decl)) = 1;
 
Index: gcc/final.c
===================================================================
--- gcc/final.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/final.c	2015-05-18 07:53:15.006808572 +0100
@@ -4438,6 +4438,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
       df_set_regs_ever_live (newreg, true);
       SET_REGNO (in_rtx, newreg);
       in_rtx->used = 1;
+      return;
     }
 
   if (INSN_P (in_rtx))
Index: gcc/genemit.c
===================================================================
--- gcc/genemit.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/genemit.c	2015-05-18 07:53:15.006808572 +0100
@@ -240,6 +240,10 @@ gen_exp (rtx x, enum rtx_code subroutine
 	  printf ("%u", XINT (x, i));
 	  break;
 
+	case 'r':
+	  printf ("%u", REGNO (x));
+	  break;
+
 	case 's':
 	  printf ("\"%s\"", XSTR (x, i));
 	  break;
Index: gcc/genpeep.c
===================================================================
--- gcc/genpeep.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/genpeep.c	2015-05-18 07:53:15.010808427 +0100
@@ -276,6 +276,12 @@ match_rtx (rtx x, struct link *path, int
 	  printf ("  if (XINT (x, %d) != %d) goto L%d;\n",
 		  i, XINT (x, i), fail_label);
 	}
+      else if (fmt[i] == 'r')
+	{
+	  gcc_assert (i == 0);
+	  printf ("  if (REGNO (x) != %d) goto L%d;\n",
+		  REGNO (x), fail_label);
+	}
       else if (fmt[i] == 'w')
 	{
 	  /* Make sure that at run time `x' is the RTX we want to test.  */
Index: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/gensupport.c	2015-05-18 07:53:15.010808427 +0100
@@ -880,7 +880,7 @@ subst_pattern_match (rtx x, rtx pt, int
 
       switch (fmt[i])
 	{
-	case 'i': case 'w': case 's':
+	case 'i': case 'r': case 'w': case 's':
 	  continue;
 
 	case 'e': case 'u':
@@ -1045,7 +1045,7 @@ get_alternatives_number (rtx pattern, in
 		return 0;
 	  break;
 
-	case 'i': case 'w': case '0': case 's': case 'S': case 'T':
+	case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
 	  break;
 
 	default:
@@ -1104,7 +1104,7 @@ collect_insn_data (rtx pattern, int *pal
 	    collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
 	  break;
 
-	case 'i': case 'w': case '0': case 's': case 'S': case 'T':
+	case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
 	  break;
 
 	default:
@@ -1188,7 +1188,7 @@ alter_predicate_for_insn (rtx pattern, i
 	    }
 	  break;
 
-	case 'i': case 'w': case '0': case 's':
+	case 'i': case 'r': case 'w': case '0': case 's':
 	  break;
 
 	default:
@@ -1246,7 +1246,7 @@ alter_constraints (rtx pattern, int n_du
 	    }
 	  break;
 
-	case 'i': case 'w': case '0': case 's':
+	case 'i': case 'r': case 'w': case '0': case 's':
 	  break;
 
 	default:
@@ -2184,7 +2184,7 @@ subst_dup (rtx pattern, int n_alt, int n
 						   n_alt, n_subst_alt);
 	  break;
 
-	case 'i': case 'w': case '0': case 's': case 'S': case 'T':
+	case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
 	  break;
 
 	default:
Index: gcc/read-rtl.c
===================================================================
--- gcc/read-rtl.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/read-rtl.c	2015-05-18 07:53:15.010808427 +0100
@@ -1346,6 +1346,13 @@ read_rtx_code (const char *code_name)
 				       name.string);
 	break;
 
+      case 'r':
+	read_name (&name);
+	validate_const_int (name.string);
+	SET_REGNO_RAW (return_rtx, atoi (name.string));
+	REG_ATTRS (return_rtx) = NULL;
+	break;
+
       default:
 	gcc_unreachable ();
       }
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/print-rtl.c	2015-05-18 07:53:15.010808427 +0100
@@ -462,55 +462,12 @@ print_rtx (const_rtx in_rtx)
 	    int value = XINT (in_rtx, i);
 	    const char *name;
 
-#ifndef GENERATOR_FILE
-	    if (REG_P (in_rtx) && (unsigned) value < FIRST_PSEUDO_REGISTER)
-	      fprintf (outfile, " %d %s", value, reg_names[value]);
-	    else if (REG_P (in_rtx)
-		     && (unsigned) value <= LAST_VIRTUAL_REGISTER)
-	      {
-		if (value == VIRTUAL_INCOMING_ARGS_REGNUM)
-		  fprintf (outfile, " %d virtual-incoming-args", value);
-		else if (value == VIRTUAL_STACK_VARS_REGNUM)
-		  fprintf (outfile, " %d virtual-stack-vars", value);
-		else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM)
-		  fprintf (outfile, " %d virtual-stack-dynamic", value);
-		else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM)
-		  fprintf (outfile, " %d virtual-outgoing-args", value);
-		else if (value == VIRTUAL_CFA_REGNUM)
-		  fprintf (outfile, " %d virtual-cfa", value);
-		else if (value == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
-		  fprintf (outfile, " %d virtual-preferred-stack-boundary",
-			   value);
-		else
-		  fprintf (outfile, " %d virtual-reg-%d", value,
-			   value-FIRST_VIRTUAL_REGISTER);
-	      }
-	    else
-#endif
-	      if (flag_dump_unnumbered
-		     && (is_insn || NOTE_P (in_rtx)))
+	    if (flag_dump_unnumbered
+		&& (is_insn || NOTE_P (in_rtx)))
 	      fputc ('#', outfile);
 	    else
 	      fprintf (outfile, " %d", value);
 
-#ifndef GENERATOR_FILE
-	    if (REG_P (in_rtx) && REG_ATTRS (in_rtx))
-	      {
-		fputs (" [", outfile);
-		if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx))
-		  fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
-		if (REG_EXPR (in_rtx))
-		  print_mem_expr (outfile, REG_EXPR (in_rtx));
-
-		if (REG_OFFSET (in_rtx))
-		  fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
-			   REG_OFFSET (in_rtx));
-		fputs (" ]", outfile);
-	      }
-	    if (REG_P (in_rtx) && REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
-	      fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
-#endif
-
 	    if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
 		&& XINT (in_rtx, i) >= 0
 		&& (name = get_insn_name (XINT (in_rtx, i))) != NULL)
@@ -519,6 +476,58 @@ print_rtx (const_rtx in_rtx)
 	  }
 	break;
 
+      case 'r':
+	{
+	  unsigned int regno = REGNO (in_rtx);
+#ifndef GENERATOR_FILE
+	  if (regno < FIRST_PSEUDO_REGISTER)
+	    fprintf (outfile, " %d %s", regno, reg_names[regno]);
+	  else if (regno <= LAST_VIRTUAL_REGISTER)
+	    {
+	      if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
+		fprintf (outfile, " %d virtual-incoming-args", regno);
+	      else if (regno == VIRTUAL_STACK_VARS_REGNUM)
+		fprintf (outfile, " %d virtual-stack-vars", regno);
+	      else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
+		fprintf (outfile, " %d virtual-stack-dynamic", regno);
+	      else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
+		fprintf (outfile, " %d virtual-outgoing-args", regno);
+	      else if (regno == VIRTUAL_CFA_REGNUM)
+		fprintf (outfile, " %d virtual-cfa", regno);
+	      else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
+		fprintf (outfile, " %d virtual-preferred-stack-boundary",
+			 regno);
+	      else
+		fprintf (outfile, " %d virtual-reg-%d", regno,
+			 regno-FIRST_VIRTUAL_REGISTER);
+	    }
+	  else
+#endif
+	    if (flag_dump_unnumbered && is_insn)
+	      fputc ('#', outfile);
+	    else
+	      fprintf (outfile, " %d", regno);
+
+#ifndef GENERATOR_FILE
+	  if (REG_ATTRS (in_rtx))
+	    {
+	      fputs (" [", outfile);
+	      if (regno != ORIGINAL_REGNO (in_rtx))
+		fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
+	      if (REG_EXPR (in_rtx))
+		print_mem_expr (outfile, REG_EXPR (in_rtx));
+
+	      if (REG_OFFSET (in_rtx))
+		fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
+			 REG_OFFSET (in_rtx));
+	      fputs (" ]", outfile);
+	    }
+	  if (regno != ORIGINAL_REGNO (in_rtx))
+	    fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
+#endif
+	  break;
+	}
+
       /* Print NOTE_INSN names rather than integer codes.  */
 
       case 'n':
Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/genrecog.c	2015-05-18 07:53:15.010808427 +0100
@@ -396,7 +396,7 @@ find_operand (rtx pattern, int n, rtx st
 	      return r;
 	  break;
 
-	case 'i': case 'w': case '0': case 's':
+	case 'i': case 'r': case 'w': case '0': case 's':
 	  break;
 
 	default:
@@ -447,7 +447,7 @@ find_matching_operand (rtx pattern, int
 	      return r;
 	  break;
 
-	case 'i': case 'w': case '0': case 's':
+	case 'i': case 'r': case 'w': case '0': case 's':
 	  break;
 
 	default:
@@ -747,7 +747,7 @@ validate_pattern (rtx pattern, rtx insn,
 	    validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
 	  break;
 
-	case 'i': case 'w': case '0': case 's':
+	case 'i': case 'r': case 'w': case '0': case 's':
 	  break;
 
 	default:
@@ -967,6 +967,9 @@ struct parameter
     /* An int parameter.  */
     INT,
 
+    /* An unsigned int parameter.  */
+    UINT,
+
     /* A HOST_WIDE_INT parameter.  */
     WIDE_INT
   };
@@ -1063,6 +1066,9 @@ struct rtx_test
     /* Check GET_MODE (X) == LABEL.  */
     MODE,
 
+    /* Check REGNO (X) == LABEL.  */
+    REGNO_FIELD,
+
     /* Check XINT (X, u.opno) == LABEL.  */
     INT_FIELD,
 
@@ -1142,6 +1148,7 @@ struct rtx_test
 
   static rtx_test code (position *);
   static rtx_test mode (position *);
+  static rtx_test regno_field (position *);
   static rtx_test int_field (position *, int);
   static rtx_test wide_int_field (position *, int);
   static rtx_test veclen (position *);
@@ -1180,6 +1187,13 @@ rtx_test::mode (position *pos)
 }
 
 rtx_test
+rtx_test::regno_field (position *pos)
+{
+  rtx_test res (pos, rtx_test::REGNO_FIELD);
+  return res;
+}
+
+rtx_test
 rtx_test::int_field (position *pos, int opno)
 {
   rtx_test res (pos, rtx_test::INT_FIELD);
@@ -1299,6 +1313,7 @@ operator == (const rtx_test &a, const rt
     {
     case rtx_test::CODE:
     case rtx_test::MODE:
+    case rtx_test::REGNO_FIELD:
     case rtx_test::VECLEN:
     case rtx_test::HAVE_NUM_CLOBBERS:
       return true;
@@ -1753,6 +1768,7 @@ safe_to_hoist_p (decision *d, const rtx_
 	}
       gcc_unreachable ();
 
+    case rtx_test::REGNO_FIELD:
     case rtx_test::INT_FIELD:
     case rtx_test::WIDE_INT_FIELD:
     case rtx_test::VECLEN:
@@ -1959,6 +1975,9 @@ transition_parameter_type (rtx_test::kin
     case rtx_test::MODE:
       return parameter::MODE;
 
+    case rtx_test::REGNO_FIELD:
+      return parameter::UINT;
+
     case rtx_test::INT_FIELD:
     case rtx_test::VECLEN:
     case rtx_test::PATTERN:
@@ -3970,6 +3989,13 @@ match_pattern_2 (state *s, rtx top_patte
 				      XINT (pattern, i), false);
 		    break;
 
+		  case 'r':
+		    /* Make sure that REGNO (X) has the right value.  */
+		    gcc_assert (i == 0);
+		    s = add_decision (s, rtx_test::regno_field (pos),
+				      REGNO (pattern), false);
+		    break;
+
 		  case 'w':
 		    /* Make sure that XWINT (X, I) has the right value.  */
 		    s = add_decision (s, rtx_test::wide_int_field (pos, i),
@@ -4232,6 +4258,9 @@ parameter_type_string (parameter::type_e
     case parameter::INT:
       return "int";
 
+    case parameter::UINT:
+      return "unsigned int";
+
     case parameter::WIDE_INT:
       return "HOST_WIDE_INT";
     }
@@ -4451,6 +4480,10 @@ print_parameter_value (const parameter &
 	printf ("%d", (int) param.value);
 	break;
 
+      case parameter::UINT:
+	printf ("%u", (unsigned int) param.value);
+	break;
+
       case parameter::WIDE_INT:
 	print_host_wide_int (param.value);
 	break;
@@ -4499,6 +4532,12 @@ print_nonbool_test (output_state *os, co
       printf (", %d)", test.u.opno);
       break;
 
+    case rtx_test::REGNO_FIELD:
+      printf ("REGNO (");
+      print_test_rtx (os, test);
+      printf (")");
+      break;
+
     case rtx_test::WIDE_INT_FIELD:
       printf ("XWINT (");
       print_test_rtx (os, test);
@@ -4572,6 +4611,7 @@ print_test (output_state *os, const rtx_
     case rtx_test::CODE:
     case rtx_test::MODE:
     case rtx_test::VECLEN:
+    case rtx_test::REGNO_FIELD:
     case rtx_test::INT_FIELD:
     case rtx_test::WIDE_INT_FIELD:
     case rtx_test::PATTERN:
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/cselib.c	2015-05-18 07:53:15.002808721 +0100
@@ -976,6 +976,9 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, ma
     case LABEL_REF:
       return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
 
+    case REG:
+      return REGNO (x) == REGNO (y);
+
     case MEM:
       /* We have to compare any autoinc operations in the addresses
 	 using this MEM's mode.  */
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	2015-05-18 07:53:15.014808321 +0100
+++ gcc/lra-constraints.c	2015-05-18 07:53:15.010808427 +0100
@@ -749,6 +749,9 @@ operands_match_p (rtx x, rtx y, int y_ha
 
  slow:
 
+  if (code == REG && REG_P (y))
+    return REGNO (x) == REGNO (y);
+
   if (code == REG && GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))
       && x == SUBREG_REG (y))
     return true;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [5/9] Create sensible dummy registers
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (3 preceding siblings ...)
  2015-05-18 18:22 ` [4/9] Add a dedicated rtx union member for REGs Richard Sandiford
@ 2015-05-18 18:23 ` Richard Sandiford
  2015-05-18 21:29   ` Jeff Law
  2015-05-19  9:02   ` Eric Botcazou
  2015-05-18 18:24 ` [7/9] Record the number of registers in a REG Richard Sandiford
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:23 UTC (permalink / raw)
  To: gcc-patches

Some pieces of code create a temporary REG or MEM and only fill it
in later when they're testing the cost of a particular rtx.  This patch
makes sure that even the dummy REG or MEM is valid, rather than force
the gen_* code to handle garbage values.


gcc/
	* caller-save.c (init_caller_save): Use word_mode and
	FIRST_PSEUDO_REGISTER when creating temporary rtxes.
	* expr.c (init_expr_target): Likewise.
	* ira.c (setup_prohibited_mode_move_regs): Likewise.
	* postreload.c (reload_cse_regs_1): Likewise.

Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2015-05-16 15:50:58.063567104 +0100
+++ gcc/caller-save.c	2015-05-16 15:50:58.055567198 +0100
@@ -287,8 +287,8 @@ init_caller_save (void)
      To avoid lots of unnecessary RTL allocation, we construct all the RTL
      once, then modify the memory and register operands in-place.  */
 
-  test_reg = gen_rtx_REG (VOIDmode, 0);
-  test_mem = gen_rtx_MEM (VOIDmode, address);
+  test_reg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  test_mem = gen_rtx_MEM (word_mode, address);
   savepat = gen_rtx_SET (test_mem, test_reg);
   restpat = gen_rtx_SET (test_reg, test_mem);
 
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2015-05-16 15:50:58.063567104 +0100
+++ gcc/expr.c	2015-05-16 15:50:58.059567152 +0100
@@ -202,12 +202,12 @@ init_expr_target (void)
   /* Try indexing by frame ptr and try by stack ptr.
      It is known that on the Convex the stack ptr isn't a valid index.
      With luck, one or the other is valid on any machine.  */
-  mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
-  mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
+  mem = gen_rtx_MEM (word_mode, stack_pointer_rtx);
+  mem1 = gen_rtx_MEM (word_mode, frame_pointer_rtx);
 
   /* A scratch register we can modify in-place below to avoid
      useless RTL allocations.  */
-  reg = gen_rtx_REG (VOIDmode, -1);
+  reg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
 
   insn = rtx_alloc (INSN);
   pat = gen_rtx_SET (NULL_RTX, NULL_RTX);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2015-05-16 15:50:58.063567104 +0100
+++ gcc/ira.c	2015-05-16 15:50:58.055567198 +0100
@@ -1767,8 +1767,8 @@ setup_prohibited_mode_move_regs (void)
   if (ira_prohibited_mode_move_regs_initialized_p)
     return;
   ira_prohibited_mode_move_regs_initialized_p = true;
-  test_reg1 = gen_rtx_REG (VOIDmode, 0);
-  test_reg2 = gen_rtx_REG (VOIDmode, 0);
+  test_reg1 = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  test_reg2 = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
   move_pat = gen_rtx_SET (test_reg1, test_reg2);
   move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, move_pat, 0, -1, 0);
   for (i = 0; i < NUM_MACHINE_MODES; i++)
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2015-05-16 15:50:58.063567104 +0100
+++ gcc/postreload.c	2015-05-16 15:50:58.055567198 +0100
@@ -234,7 +234,7 @@ reload_cse_regs_1 (void)
   bool cfg_changed = false;
   basic_block bb;
   rtx_insn *insn;
-  rtx testreg = gen_rtx_REG (VOIDmode, -1);
+  rtx testreg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
 
   cselib_init (CSELIB_RECORD_MEMORY);
   init_alias_analysis ();

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [6/9] Pass REG changes through a new function
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (5 preceding siblings ...)
  2015-05-18 18:24 ` [7/9] Record the number of registers in a REG Richard Sandiford
@ 2015-05-18 18:24 ` Richard Sandiford
  2015-05-18 21:32   ` Jeff Law
  2015-05-18 18:26 ` [8/9] Remove END_HARD_REGNO Richard Sandiford
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:24 UTC (permalink / raw)
  To: gcc-patches

This patch adds a new function to set both the mode and regno
of a REG.  It makes sure that all REG PUT_MODE and SET_REGNO changes
go through this function.  There's a new PUT_MODE_RAW (analogous
to SET_REGNO_RAW) for the cases where the caller doesn't want that.

There's a small consistency fix: gen_rtx_REG was declared with
"unsigned" and defined with "unsigned int".  The latter is usual
GCC style.


gcc/
	* rtl.h (PUT_MODE_RAW): New macro.
	(PUT_REG_NOTE_KIND): Use it.
	(set_mode_and_regno): Declare.
	(gen_raw_REG): Change regno to "unsigned int".
	(gen_rtx_REG): Change "unsigned" to "unsigned int".
	(PUT_MODE): Forward to PUT_MODE_RAW for generators, otherwise
	use set_mode_and_regno to change the mode of registers.
	* gengenrtl.c (gendef): Use PUT_MODE_RAW.
	* emit-rtl.c (set_mode_and_regno): New function.
	(gen_raw_REG): Change regno to unsigned int.  Use set_mode_and_regno.
	* caller-save.c (reg_save_code): Use set_mode_and_regno.
	* expr.c (init_expr_target): Likewise.
	* ira.c (setup_prohibited_mode_move_regs): Likewise.
	* postreload.c (reload_cse_simplify_operands): Likewise.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-17 21:26:44.375213705 +0100
+++ gcc/rtl.h	2015-05-17 21:29:52.068986873 +0100
@@ -668,8 +668,8 @@ #define RTX_PREV(X) ((INSN_P (X)
 #define GET_CODE(RTX)	    ((enum rtx_code) (RTX)->code)
 #define PUT_CODE(RTX, CODE) ((RTX)->code = (CODE))
 
-#define GET_MODE(RTX)	    ((machine_mode) (RTX)->mode)
-#define PUT_MODE(RTX, MODE) ((RTX)->mode = (MODE))
+#define GET_MODE(RTX)		((machine_mode) (RTX)->mode)
+#define PUT_MODE_RAW(RTX, MODE)	((RTX)->mode = (MODE))
 
 /* RTL vector.  These appear inside RTX's when there is a need
    for a variable number of things.  The principle use is inside
@@ -1509,7 +1509,7 @@ #define DEF_REG_NOTE(NAME) NAME,
 /* Define macros to extract and insert the reg-note kind in an EXPR_LIST.  */
 #define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
 #define PUT_REG_NOTE_KIND(LINK, KIND) \
-  PUT_MODE (LINK, (machine_mode) (KIND))
+  PUT_MODE_RAW (LINK, (machine_mode) (KIND))
 
 /* Names for REG_NOTE's in EXPR_LIST insn's.  */
 
@@ -3216,13 +3216,27 @@ gen_rtx_INSN (machine_mode mode, rtx_ins
 	      rtx reg_notes);
 extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
 extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
-extern rtx gen_raw_REG (machine_mode, int);
-extern rtx gen_rtx_REG (machine_mode, unsigned);
+extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx gen_raw_REG (machine_mode, unsigned int);
+extern rtx gen_rtx_REG (machine_mode, unsigned int);
 extern rtx gen_rtx_SUBREG (machine_mode, rtx, int);
 extern rtx gen_rtx_MEM (machine_mode, rtx);
 extern rtx gen_rtx_VAR_LOCATION (machine_mode, tree, rtx,
 				 enum var_init_status);
 
+#ifdef GENERATOR_FILE
+#define PUT_MODE(RTX, MODE) PUT_MODE_RAW (RTX, MODE)
+#else
+static inline void
+PUT_MODE (rtx x, machine_mode mode)
+{
+  if (REG_P (x))
+    set_mode_and_regno (x, mode, REGNO (x));
+  else
+    PUT_MODE_RAW (x, mode);
+}
+#endif
+
 #define GEN_INT(N)  gen_rtx_CONST_INT (VOIDmode, (N))
 
 /* Virtual registers are used during RTL generation to refer to locations into
Index: gcc/gengenrtl.c
===================================================================
--- gcc/gengenrtl.c	2015-05-15 21:12:56.172234508 +0100
+++ gcc/gengenrtl.c	2015-05-17 21:31:16.143988041 +0100
@@ -252,7 +252,7 @@ gendef (const char *format)
   puts ("  rtx rt;");
   puts ("  rt = rtx_alloc_stat (code PASS_MEM_STAT);\n");
 
-  puts ("  PUT_MODE (rt, mode);");
+  puts ("  PUT_MODE_RAW (rt, mode);");
 
   for (p = format, i = j = 0; *p ; ++p, ++i)
     if (*p != '0')
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2015-05-17 21:26:44.375213705 +0100
+++ gcc/emit-rtl.c	2015-05-17 21:30:18.484672892 +0100
@@ -430,16 +430,24 @@ gen_blockage (void)
 #endif
 
 
+/* Set the mode and register number of X to MODE and REGNO.  */
+
+void
+set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
+{
+  PUT_MODE_RAW (x, mode);
+  SET_REGNO_RAW (x, regno);
+}
+
 /* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
    don't attempt to share with the various global pieces of rtl (such as
    frame_pointer_rtx).  */
 
 rtx
-gen_raw_REG (machine_mode mode, int regno)
+gen_raw_REG (machine_mode mode, unsigned int regno)
 {
   rtx x = rtx_alloc_stat (REG PASS_MEM_STAT);
-  PUT_MODE (x, mode);
-  SET_REGNO_RAW (x, regno);
+  set_mode_and_regno (x, mode, regno);
   REG_ATTRS (x) = NULL;
   ORIGINAL_REGNO (x) = regno;
   return x;
Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2015-05-17 21:26:44.375213705 +0100
+++ gcc/caller-save.c	2015-05-17 21:26:44.363212664 +0100
@@ -150,8 +150,7 @@ reg_save_code (int reg, machine_mode mod
 
   /* Update the register number and modes of the register
      and memory operand.  */
-  SET_REGNO_RAW (test_reg, reg);
-  PUT_MODE (test_reg, mode);
+  set_mode_and_regno (test_reg, mode, reg);
   PUT_MODE (test_mem, mode);
 
   /* Force re-recognition of the modified insns.  */
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2015-05-17 21:26:44.375213705 +0100
+++ gcc/expr.c	2015-05-17 21:26:44.371213229 +0100
@@ -221,7 +221,6 @@ init_expr_target (void)
       direct_load[(int) mode] = direct_store[(int) mode] = 0;
       PUT_MODE (mem, mode);
       PUT_MODE (mem1, mode);
-      PUT_MODE (reg, mode);
 
       /* See if there is some register that can be used in this mode and
 	 directly loaded or stored from memory.  */
@@ -234,7 +233,7 @@ init_expr_target (void)
 	    if (! HARD_REGNO_MODE_OK (regno, mode))
 	      continue;
 
-	    SET_REGNO (reg, regno);
+	    set_mode_and_regno (reg, mode, regno);
 
 	    SET_SRC (pat) = mem;
 	    SET_DEST (pat) = reg;
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2015-05-17 21:26:44.375213705 +0100
+++ gcc/ira.c	2015-05-17 21:26:44.363212664 +0100
@@ -1778,10 +1778,8 @@ setup_prohibited_mode_move_regs (void)
 	{
 	  if (! HARD_REGNO_MODE_OK (j, (machine_mode) i))
 	    continue;
-	  SET_REGNO_RAW (test_reg1, j);
-	  PUT_MODE (test_reg1, (machine_mode) i);
-	  SET_REGNO_RAW (test_reg2, j);
-	  PUT_MODE (test_reg2, (machine_mode) i);
+	  set_mode_and_regno (test_reg1, (machine_mode) i, j);
+	  set_mode_and_regno (test_reg2, (machine_mode) i, j);
 	  INSN_CODE (move_insn) = -1;
 	  recog_memoized (move_insn);
 	  if (INSN_CODE (move_insn) < 0)
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2015-05-17 21:26:44.375213705 +0100
+++ gcc/postreload.c	2015-05-17 21:26:44.367212817 +0100
@@ -562,8 +562,7 @@ reload_cse_simplify_operands (rtx_insn *
 	  if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
 	    continue;
 
-	  SET_REGNO_RAW (testreg, regno);
-	  PUT_MODE (testreg, mode);
+	  set_mode_and_regno (testreg, mode, regno);
 
 	  /* We found a register equal to this operand.  Now look for all
 	     alternatives that can accept this register and have not been

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [7/9] Record the number of registers in a REG
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (4 preceding siblings ...)
  2015-05-18 18:23 ` [5/9] Create sensible dummy registers Richard Sandiford
@ 2015-05-18 18:24 ` Richard Sandiford
  2015-05-18 21:33   ` Jeff Law
  2015-05-18 18:24 ` [6/9] Pass REG changes through a new function Richard Sandiford
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:24 UTC (permalink / raw)
  To: gcc-patches

This is the main patch, to record REG_NREGS in the REG itself.
The END_REGNO/END_HARD_REGNO distinction goes away in the next patch.


gcc/
	* rtl.h (reg_info): Add an nregs field.
	(REG_NREGS): Use it.
	(SET_REGNO_RAW): Delete.
	(set_regno_raw): New function.
	* regs.h (END_HARD_REGNO): Make equivalent to END_REGNO.
	(END_REGNO): Redefine in terms of REG_NREGS.
	* read-rtl.c (read_rtx_code): Call set_regno_raw instead of
	SET_REGNO_RAW.
	* emit-rtl.c (set_mode_and_regno): Likewise.
	* df-scan.c (df_ref_change_reg_with_loc): Use set_mode_and_regno
	instead of SET_REGNO_RAW.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-18 08:34:38.532523211 +0100
+++ gcc/rtl.h	2015-05-18 08:36:23.407245048 +0100
@@ -210,7 +210,9 @@ struct GTY(()) reg_info {
   /* The value of REGNO.  */
   unsigned int regno;
 
-  unsigned int unused : 32;
+  /* The value of REG_NREGS.  */
+  unsigned int nregs : 8;
+  unsigned int unused : 24;
 
   /* The value of REG_ATTRS.  */
   reg_attrs *attrs;
@@ -1712,15 +1714,11 @@ #define LABEL_REF_LABEL(LABREF) XCEXP (L
    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 (RTX, N))
-#define SET_REGNO_RAW(RTX, N) (REG_CHECK (RTX)->regno = 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)
+#define REG_NREGS(RTX) (REG_CHECK (RTX)->nregs)
 
 /* ORIGINAL_REGNO holds the number the register originally had; for a
    pseudo register turned into a hard reg this will hold the old pseudo
@@ -1735,6 +1733,15 @@ rhs_regno (const_rtx x)
   return REG_CHECK (x)->regno;
 }
 
+/* Change the REGNO and REG_NREGS of REG X to the specified values,
+   bypassing the df machinery.  */
+static inline void
+set_regno_raw (rtx x, unsigned int regno, unsigned int nregs)
+{
+  reg_info *reg = REG_CHECK (x);
+  reg->regno = regno;
+  reg->nregs = nregs;
+}
 
 /* 1 if RTX is a reg or parallel that is the current function's return
    value.  */
Index: gcc/regs.h
===================================================================
--- gcc/regs.h	2015-05-18 08:34:38.532523211 +0100
+++ gcc/regs.h	2015-05-18 08:36:11.000000000 +0100
@@ -288,11 +288,11 @@ end_hard_regno (machine_mode mode, unsig
 
 /* Likewise for hard register X.  */
 
-#define END_HARD_REGNO(X) end_hard_regno (GET_MODE (X), REGNO (X))
+#define END_HARD_REGNO(X) END_REGNO (X)
 
 /* Likewise for hard or pseudo register X.  */
 
-#define END_REGNO(X) (HARD_REGISTER_P (X) ? END_HARD_REGNO (X) : REGNO (X) + 1)
+#define END_REGNO(X) (REGNO (X) + REG_NREGS (X))
 
 /* Add to REGS all the registers required to store a value of mode MODE
    in register REGNO.  */
Index: gcc/read-rtl.c
===================================================================
--- gcc/read-rtl.c	2015-05-18 08:34:38.532523211 +0100
+++ gcc/read-rtl.c	2015-05-18 08:34:38.532523211 +0100
@@ -1349,7 +1349,7 @@ read_rtx_code (const char *code_name)
       case 'r':
 	read_name (&name);
 	validate_const_int (name.string);
-	SET_REGNO_RAW (return_rtx, atoi (name.string));
+	set_regno_raw (return_rtx, atoi (name.string), 1);
 	REG_ATTRS (return_rtx) = NULL;
 	break;
 
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2015-05-18 08:34:38.532523211 +0100
+++ gcc/emit-rtl.c	2015-05-18 08:34:38.532523211 +0100
@@ -435,8 +435,11 @@ gen_blockage (void)
 void
 set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
 {
+  unsigned int nregs = (HARD_REGISTER_NUM_P (regno)
+			? hard_regno_nregs[regno][mode]
+			: 1);
   PUT_MODE_RAW (x, mode);
-  SET_REGNO_RAW (x, regno);
+  set_regno_raw (x, regno, nregs);
 }
 
 /* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2015-05-18 08:34:38.532523211 +0100
+++ gcc/df-scan.c	2015-05-18 08:36:11.000000000 +0100
@@ -1930,7 +1930,7 @@ df_ref_change_reg_with_loc (rtx loc, uns
 				    DF_REG_EQ_USE_GET (new_regno),
 				    new_regno, loc);
     }
-  SET_REGNO_RAW (loc, new_regno);
+  set_mode_and_regno (loc, GET_MODE (loc), new_regno);
 }
 
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [8/9] Remove END_HARD_REGNO
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (6 preceding siblings ...)
  2015-05-18 18:24 ` [6/9] Pass REG changes through a new function Richard Sandiford
@ 2015-05-18 18:26 ` Richard Sandiford
  2015-05-18 21:34   ` Jeff Law
  2015-05-18 18:31 ` [9/9] Simplify register bitmap operations Richard Sandiford
  2015-05-19 15:21 ` breakage with series "[0/9] Record number of hard registers in a REG" Hans-Peter Nilsson
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:26 UTC (permalink / raw)
  To: gcc-patches

This patch replaces calls to END_HARD_REGNO with calls to END_REGNO and
moves END_REGNO to rtl.h (since it's now just a REG access).


gcc/
	* regs.h (END_HARD_REGNO): Delete.
	(END_REGNO): Move to...
	* rtl.h: ...here.
	* bt-load.c (note_btr_set): Use END_REGNO instead of END_HARD_REGNO.
	* caller-save.c (mark_set_regs): Likewise.
	* combine.c (move_deaths, distribute_notes): Likewise.
	* cse.c (invalidate, invalidate_for_call): Likewise.
	* df-scan.c (df_ref_record): Likewise.
	* postreload-gcse.c (reg_changed_after_insn_p): Likewise.
	(record_last_reg_set_info): Likewise.
	* reg-stack.c (convert_regs_exit): Likewise.
	* reload.c (reg_overlap_mentioned_for_reload_p): Likewise.
	* resource.c (update_live_status): Likewise.
	* rtlanal.c (find_reg_fusage, find_regno_fusage): Likewise.

Index: gcc/regs.h
===================================================================
--- gcc/regs.h	2015-05-18 08:36:41.951019042 +0100
+++ gcc/regs.h	2015-05-18 08:36:41.947019063 +0100
@@ -286,14 +286,6 @@ end_hard_regno (machine_mode mode, unsig
   return regno + hard_regno_nregs[regno][(int) mode];
 }
 
-/* Likewise for hard register X.  */
-
-#define END_HARD_REGNO(X) END_REGNO (X)
-
-/* Likewise for hard or pseudo register X.  */
-
-#define END_REGNO(X) (REGNO (X) + REG_NREGS (X))
-
 /* Add to REGS all the registers required to store a value of mode MODE
    in register REGNO.  */
 
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2015-05-18 08:36:41.951019042 +0100
+++ gcc/rtl.h	2015-05-18 08:37:14.494621384 +0100
@@ -1733,6 +1733,13 @@ rhs_regno (const_rtx x)
   return REG_CHECK (x)->regno;
 }
 
+/* Return the final register in REG X plus one.  */
+static inline unsigned int
+END_REGNO (const_rtx x)
+{
+  return REGNO (x) + REG_NREGS (x);
+}
+
 /* Change the REGNO and REG_NREGS of REG X to the specified values,
    bypassing the df machinery.  */
 static inline void
Index: gcc/bt-load.c
===================================================================
--- gcc/bt-load.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/bt-load.c	2015-05-18 08:36:41.943019110 +0100
@@ -443,7 +443,7 @@ note_btr_set (rtx dest, const_rtx set AT
   if (!REG_P (dest))
     return;
   regno = REGNO (dest);
-  end_regno = END_HARD_REGNO (dest);
+  end_regno = END_REGNO (dest);
   for (; regno < end_regno; regno++)
     if (TEST_HARD_REG_BIT (all_btrs, regno))
       {
Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/caller-save.c	2015-05-18 08:36:41.947019063 +0100
@@ -992,7 +992,7 @@ mark_set_regs (rtx reg, const_rtx setter
 	   && REGNO (reg) < FIRST_PSEUDO_REGISTER)
     {
       regno = REGNO (reg);
-      endregno = END_HARD_REGNO (reg);
+      endregno = END_REGNO (reg);
     }
   else
     return;
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/combine.c	2015-05-18 08:36:41.947019063 +0100
@@ -13316,8 +13316,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 = END_HARD_REGNO (XEXP (note, 0));
-	      unsigned int ourend = END_HARD_REGNO (x);
+	      unsigned int deadend = END_REGNO (XEXP (note, 0));
+	      unsigned int ourend = END_REGNO (x);
 	      unsigned int i;
 
 	      for (i = deadregno; i < deadend; i++)
@@ -13337,7 +13337,7 @@ move_deaths (rtx x, rtx maybe_kill_insn,
 		   && regno < FIRST_PSEUDO_REGISTER
 		   && REG_NREGS (x) > 1)
 	    {
-	      unsigned int ourend = END_HARD_REGNO (x);
+	      unsigned int ourend = END_REGNO (x);
 	      unsigned int i, offset;
 	      rtx oldnotes = 0;
 
@@ -13932,7 +13932,7 @@ distribute_notes (rtx notes, rtx_insn *f
 
 	      if (place && REG_NREGS (XEXP (note, 0)) > 1)
 		{
-		  unsigned int endregno = END_HARD_REGNO (XEXP (note, 0));
+		  unsigned int endregno = END_REGNO (XEXP (note, 0));
 		  bool all_used = true;
 		  unsigned int i;
 
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/cse.c	2015-05-18 08:36:41.947019063 +0100
@@ -1894,7 +1894,7 @@ invalidate (rtx x, machine_mode full_mod
 	  {
 	    HOST_WIDE_INT in_table
 	      = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
-	    unsigned int endregno = END_HARD_REGNO (x);
+	    unsigned int endregno = END_REGNO (x);
 	    unsigned int tregno, tendregno, rn;
 	    struct table_elt *p, *next;
 
@@ -1920,7 +1920,7 @@ invalidate (rtx x, machine_mode full_mod
 		      continue;
 
 		    tregno = REGNO (p->exp);
-		    tendregno = END_HARD_REGNO (p->exp);
+		    tendregno = END_REGNO (p->exp);
 		    if (tendregno > regno && tregno < endregno)
 		      remove_from_table (p, hash);
 		  }
@@ -2139,7 +2139,7 @@ invalidate_for_call (void)
 	    continue;
 
 	  regno = REGNO (p->exp);
-	  endregno = END_HARD_REGNO (p->exp);
+	  endregno = END_REGNO (p->exp);
 
 	  for (i = regno; i < endregno; i++)
 	    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/df-scan.c	2015-05-18 08:36:41.947019063 +0100
@@ -2624,7 +2624,7 @@ df_ref_record (enum df_ref_class cl,
 	  endregno = regno + subreg_nregs (reg);
 	}
       else
-	endregno = END_HARD_REGNO (reg);
+	endregno = END_REGNO (reg);
 
       /*  If this is a multiword hardreg, we create some extra
 	  datastructures that will enable us to easily build REG_DEAD
Index: gcc/postreload-gcse.c
===================================================================
--- gcc/postreload-gcse.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/postreload-gcse.c	2015-05-18 08:36:41.947019063 +0100
@@ -551,7 +551,7 @@ reg_changed_after_insn_p (rtx x, int cui
   unsigned int regno, end_regno;
 
   regno = REGNO (x);
-  end_regno = END_HARD_REGNO (x);
+  end_regno = END_REGNO (x);
   do
     if (reg_avail_info[regno] > cuid)
       return true;
@@ -720,7 +720,7 @@ record_last_reg_set_info (rtx_insn *insn
   unsigned int regno, end_regno;
 
   regno = REGNO (reg);
-  end_regno = END_HARD_REGNO (reg);
+  end_regno = END_REGNO (reg);
   do
     reg_avail_info[regno] = INSN_CUID (insn);
   while (++regno < end_regno);
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/reg-stack.c	2015-05-18 08:36:41.947019063 +0100
@@ -2689,7 +2689,7 @@ convert_regs_exit (void)
   if (retvalue)
     {
       value_reg_low = REGNO (retvalue);
-      value_reg_high = END_HARD_REGNO (retvalue) - 1;
+      value_reg_high = END_REGNO (retvalue) - 1;
     }
 
   output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR_FOR_FN (cfun))->stack_in;
Index: gcc/reload.c
===================================================================
--- gcc/reload.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/reload.c	2015-05-18 08:36:41.951019042 +0100
@@ -6612,7 +6612,7 @@ reg_overlap_mentioned_for_reload_p (rtx
 	  return 0;
 	}
 
-      endregno = END_HARD_REGNO (x);
+      endregno = END_REGNO (x);
 
       return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
     }
Index: gcc/resource.c
===================================================================
--- gcc/resource.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/resource.c	2015-05-18 08:36:41.951019042 +0100
@@ -115,7 +115,7 @@ update_live_status (rtx dest, const_rtx
   else
     {
       first_regno = REGNO (dest);
-      last_regno = END_HARD_REGNO (dest);
+      last_regno = END_REGNO (dest);
     }
 
   if (GET_CODE (x) == CLOBBER)
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2015-05-18 08:36:41.951019042 +0100
+++ gcc/rtlanal.c	2015-05-18 08:36:41.951019042 +0100
@@ -2018,7 +2018,7 @@ find_reg_fusage (const_rtx insn, enum rt
 
       if (regno < FIRST_PSEUDO_REGISTER)
 	{
-	  unsigned int end_regno = END_HARD_REGNO (datum);
+	  unsigned int end_regno = END_REGNO (datum);
 	  unsigned int i;
 
 	  for (i = regno; i < end_regno; i++)
@@ -2052,7 +2052,7 @@ find_regno_fusage (const_rtx insn, enum
       if (GET_CODE (op = XEXP (link, 0)) == code
 	  && REG_P (reg = XEXP (op, 0))
 	  && REGNO (reg) <= regno
-	  && END_HARD_REGNO (reg) > regno)
+	  && END_REGNO (reg) > regno)
 	return 1;
     }
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [9/9] Simplify register bitmap operations
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (7 preceding siblings ...)
  2015-05-18 18:26 ` [8/9] Remove END_HARD_REGNO Richard Sandiford
@ 2015-05-18 18:31 ` Richard Sandiford
  2015-05-18 21:39   ` Jeff Law
  2015-05-19 15:21 ` breakage with series "[0/9] Record number of hard registers in a REG" Hans-Peter Nilsson
  9 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-18 18:31 UTC (permalink / raw)
  To: gcc-patches

After the previous changes, several callers are left with code like:

  if (HARD_REGISTER_P (x))
    bitmap_foo_range (x, REGNO (x), REG_NREGS (x));
  else
    bitmap_foo (x, REGNO (x));

These might as well now be:

  if (REG_NREGS (x) > 1)
    bitmap_foo_range (x, REGNO (x), REG_NREGS (x));
  else
    bitmap_foo (x, REGNO (x));

since REG_NREGS is as cheap to test, and since single-register hard REGs
are the common case.  But if separating out the cases is a win -- and it
seems to be, very slightly -- then it would be better to add the shortcut
to the range functions themselves.


gcc/
	* bitmap.c (bitmap_set_range): Handle count==1 specially.
	(bitmap_clear_range): Likewise.
	* cfgcleanup.c (mark_effect): Use bitmap_clear_range and
	bitmap_set_range unconditionally.
	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
	* df-scan.c (df_mark_reg): Likewise.
	* haifa-sched.c (setup_ref_regs): Likewise.
	* sched-rgn.c (update_live_1): Likewise.

Index: gcc/bitmap.c
===================================================================
--- gcc/bitmap.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/bitmap.c	2015-05-18 08:38:25.841752865 +0100
@@ -1212,6 +1212,12 @@ bitmap_set_range (bitmap head, unsigned
   if (!count)
     return;
 
+  if (count == 1)
+    {
+      bitmap_set_bit (head, start);
+      return;
+    }
+
   first_index = start / BITMAP_ELEMENT_ALL_BITS;
   end_bit_plus1 = start + count;
   last_index = (end_bit_plus1 - 1) / BITMAP_ELEMENT_ALL_BITS;
@@ -1311,6 +1317,12 @@ bitmap_clear_range (bitmap head, unsigne
   if (!count)
     return;
 
+  if (count == 1)
+    {
+      bitmap_clear_bit (head, start);
+      return;
+    }
+
   first_index = start / BITMAP_ELEMENT_ALL_BITS;
   end_bit_plus1 = start + count;
   last_index = (end_bit_plus1 - 1) / BITMAP_ELEMENT_ALL_BITS;
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/cfgcleanup.c	2015-05-18 08:38:25.841752865 +0100
@@ -222,22 +222,15 @@ try_simplify_condjump (basic_block cbran
 static bool
 mark_effect (rtx exp, regset nonequal)
 {
-  int regno;
   rtx dest;
   switch (GET_CODE (exp))
     {
       /* 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, REG_NREGS (dest));
-	  else
-	    bitmap_clear_bit (nonequal, regno);
-	}
+      dest = XEXP (exp, 0);
+      if (REG_P (dest))
+	bitmap_clear_range (nonequal, REGNO (dest), REG_NREGS (dest));
       return false;
 
     case SET:
@@ -248,11 +241,7 @@ mark_effect (rtx exp, regset nonequal)
 	return false;
       if (!REG_P (dest))
 	return true;
-      regno = REGNO (dest);
-      if (HARD_REGISTER_NUM_P (regno))
-	bitmap_set_range (nonequal, regno, REG_NREGS (dest));
-      else
-	bitmap_set_bit (nonequal, regno);
+      bitmap_set_range (nonequal, REGNO (dest), REG_NREGS (dest));
       return false;
 
     default:
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/df-problems.c	2015-05-18 08:38:25.845752816 +0100
@@ -3574,11 +3574,7 @@ df_simulate_one_insn_forwards (basic_blo
 	case REG_UNUSED:
 	  {
 	    rtx reg = XEXP (link, 0);
-	    int regno = REGNO (reg);
-	    if (HARD_REGISTER_NUM_P (regno))
-	      bitmap_clear_range (live, regno, REG_NREGS (reg));
-	    else
-	      bitmap_clear_bit (live, regno);
+	    bitmap_clear_range (live, REGNO (reg), REG_NREGS (reg));
 	  }
 	  break;
 	default:
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/df-scan.c	2015-05-18 08:38:25.841752865 +0100
@@ -3518,15 +3518,7 @@ df_get_eh_block_artificial_uses (bitmap
 static void
 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)
-    bitmap_set_range (set, regno, REG_NREGS (reg));
-  else
-    bitmap_set_bit (set, regno);
+  bitmap_set_range ((bitmap) vset, REGNO (reg), REG_NREGS (reg));
 }
 
 
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/haifa-sched.c	2015-05-18 08:38:25.845752816 +0100
@@ -1032,17 +1032,13 @@ initiate_reg_pressure_info (bitmap live)
 static void
 setup_ref_regs (rtx x)
 {
-  int i, j, regno;
+  int i, j;
   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, REG_NREGS (x));
-      else
-	bitmap_set_bit (region_ref_regs, REGNO (x));
+      bitmap_set_range (region_ref_regs, REGNO (x), REG_NREGS (x));
       return;
     }
   fmt = GET_RTX_FORMAT (code);
Index: gcc/sched-rgn.c
===================================================================
--- gcc/sched-rgn.c	2015-05-18 08:38:25.845752816 +0100
+++ gcc/sched-rgn.c	2015-05-18 08:38:25.845752816 +0100
@@ -1801,11 +1801,7 @@ update_live_1 (int src, rtx x)
       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, REG_NREGS (reg));
-	  else
-	    bitmap_set_bit (df_get_live_in (b), regno);
+	  bitmap_set_range (df_get_live_in (b), regno, REG_NREGS (reg));
 	}
     }
 }

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [1/9] Make more use of END_REGNO
  2015-05-18 18:13 ` [1/9] Make more use of END_REGNO Richard Sandiford
@ 2015-05-18 19:06   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 19:06 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:11 PM, Richard Sandiford wrote:
> This patch just handles some obvious cases where END_REGNO could be used.
>
>
> gcc/
> 	* cfgcleanup.c (mentions_nonequal_regs): Use END_REGNO.
> 	* dse.c (note_add_store): Likewise.
> 	* ira-lives.c (mark_hard_reg_dead): Likewise.
> 	* loop-invariant.c (mark_reg_store): Likewise.
> 	(mark_reg_death): Likewise.
> 	* postreload.c (reload_combine): Likewise.
> 	(reload_combine_note_store): Likewise.
> 	(reload_combine_note_use): Likewise.
> 	* recog.c (peep2_reg_dead_p): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [2/9] Add a REG_NREGS macro
  2015-05-18 18:15 ` [2/9] Add a REG_NREGS macro Richard Sandiford
@ 2015-05-18 20:27   ` Jeff Law
  2015-05-19  7:00     ` Richard Sandiford
  0 siblings, 1 reply; 27+ messages in thread
From: Jeff Law @ 2015-05-18 20:27 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

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


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [3/9] Clean up df_ref_change_reg_with_loc
  2015-05-18 18:19 ` [3/9] Clean up df_ref_change_reg_with_loc Richard Sandiford
@ 2015-05-18 20:33   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 20:33 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:15 PM, Richard Sandiford wrote:
> This patch cleans up the interface to df_ref_change_reg_with_loc.
> The function is used only by SET_REGNO_RAW, so the old regno is
> always REGNO (x) and the caller always goes on to set REGNO.
> (And the fuction doesn't make much sense otherwise.)
>
> The patch therefore gets df_ref_change_reg_with_loc to work out the old
> regno itself and to install the new register number once it's done.
>
> The check for the old register being -1 was redundant.  Only expr.c
> and postreload.c create -1 registers ("fixed" in a later patch).
> Both sites are just creating temporary registers in order to query
> backend hooks and neither site needs the check.  expr.c does use
> SET_REGNO and so does go through this function, but only at a time
> when there's no df information.  (And it wouldn't work if the df
> machinery were set up, since any change after the first would
> look like a "normal" change.)  postreload.c uses SET_REGNO_RAW
> and so bypasses the code altogether.
>
> expr.c bypasses the code too by the end of the series.
>
>
> gcc/
> 	* df.h (df_ref_change_reg_with_loc): Remove old_regno parameter.
> 	Change type of new_regno to unsigned int.
> 	* df-scan.c (df_ref_change_reg_with_loc_1): Change type of
> 	new_regno to unsigned int.
> 	(df_ref_change_reg_with_loc): Remove old_regno parameter.
> 	Change type of new_regno to unsigned int.  Use SET_REGNO_RAW.
> 	* rtl.h (SET_REGNO): Update call to df_ref_change_reg_with_loc.
> 	(SET_REGNO_RAW): Add space after ",".
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [4/9] Add a dedicated rtx union member for REGs
  2015-05-18 18:22 ` [4/9] Add a dedicated rtx union member for REGs Richard Sandiford
@ 2015-05-18 20:41   ` Jeff Law
  2015-05-19  7:04     ` Richard Sandiford
  0 siblings, 1 reply; 27+ messages in thread
From: Jeff Law @ 2015-05-18 20:41 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:19 PM, Richard Sandiford wrote:
> This patch replaces the current REG "i0" format with a dedicated structure,
> so that we can make use of the extra 32 bits in the "i" field.
>
> Of the places that iterate on formats and do something for 'i's,
> most already handled REGs specially before the format walk and
> so don't need to check for 'r'.  Otherwise it's mostly just a case
> of adding dummy 'r' cases in order avoid the default gcc_unreachable ()
> (in cases where we do the same for 'i').  The main exceptions are the
> cselib.c and lra-constraints.c changes.
>
> final.c:leaf_renumber_regs_insn handled REGs specially but then
> went on to do a no-op walk of the format.  I just added an early
> exit instead of an empty 'r' case.
>
>
> gcc/
> 	* rtl.def (REG): Change format to "r".
> 	* rtl.h (rtunion): Remove rt_reg.
> 	(reg_info): New structure.
> 	(rtx_def): Add reg field to main union.
> 	(X0REGATTR): Delete.
> 	(REG_CHECK): New macro.
> 	(SET_REGNO_RAW, rhs_regno, REG_ATTRS): Use it.
> 	* rtl.c (rtx_format): Document "r".
> 	(rtx_code_size): Handle REG specially.
> 	* gengenrtl.c (special_format): Return true for formats
> 	that include 'r'.
> 	* gengtype.c (adjust_field_rtx_def): Handle 'r' fields.
> 	Deal with REG_ATTRS after the field loop.
> 	* emit-rtl.c (gen_raw_REG): Call rtx_alloc_stat directly.
> 	* expmed.c (init_expmed): Call gen_raw_REG instead of
> 	gen_rtx_raw_REG.
> 	* expr.c (init_expr_target): Likewise.
> 	* regcprop.c (maybe_mode_change): Likewise.
> 	* varasm.c (make_decl_rtl): Likewise.
> 	* final.c (leaf_renumber_regs_insn): Return early after
> 	handling REGs.
> 	* genemit.c (gen_exp): Handle 'r' fields.
> 	* genpeep.c (match_rtx): Likewise.
> 	* gensupport.c (subst_pattern_match): Likewise.
> 	(get_alternatives_number, collect_insn_data, alter_predicate_for_insn)
> 	(alter_constraints, subst_dup): Likewise.
> 	* read-rtl.c (read_rtx_code): Likewise.
> 	* print-rtl.c (print_rtx): Likewise.
> 	* genrecog.c (find_operand, find_matching_operand): Likewise.
> 	(validate_pattern, match_pattern_2): Likewise.
> 	(parameter::UINT, rtx_test::REGNO_FIELD): New enum values.
> 	(rtx_test::regno_field): New function.
> 	(operator ==, safe_to_hoist_p, transition_parameter_type)
> 	(parameter_type_string, print_parameter_value)
> 	(print_nonbool_test, print_test): Handle new enum values.
> 	* cselib.c (rtx_equal_for_cselib_1): Handle REG specially.
> 	* lra-constraints.c (operands_match_p): Likewise.
Just to confirm, this doesn't change the size of a REG object, right? 
If it doesn't change the size, then it's OK.

If we make REG objects larger, we potentially increase the amount of 
memory used by GCC.

If we make REG objects smaller, then we run the risk of memory 
overwrites when reload changes REG objects into MEM objects.

The former is bad, the latter is a disaster waiting to happen.

Jeff




^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [5/9] Create sensible dummy registers
  2015-05-18 18:23 ` [5/9] Create sensible dummy registers Richard Sandiford
@ 2015-05-18 21:29   ` Jeff Law
  2015-05-19  9:02   ` Eric Botcazou
  1 sibling, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 21:29 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:21 PM, Richard Sandiford wrote:
> Some pieces of code create a temporary REG or MEM and only fill it
> in later when they're testing the cost of a particular rtx.  This patch
> makes sure that even the dummy REG or MEM is valid, rather than force
> the gen_* code to handle garbage values.
>
>
> gcc/
> 	* caller-save.c (init_caller_save): Use word_mode and
> 	FIRST_PSEUDO_REGISTER when creating temporary rtxes.
> 	* expr.c (init_expr_target): Likewise.
> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
> 	* postreload.c (reload_cse_regs_1): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [6/9] Pass REG changes through a new function
  2015-05-18 18:24 ` [6/9] Pass REG changes through a new function Richard Sandiford
@ 2015-05-18 21:32   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 21:32 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:23 PM, Richard Sandiford wrote:
> This patch adds a new function to set both the mode and regno
> of a REG.  It makes sure that all REG PUT_MODE and SET_REGNO changes
> go through this function.  There's a new PUT_MODE_RAW (analogous
> to SET_REGNO_RAW) for the cases where the caller doesn't want that.
>
> There's a small consistency fix: gen_rtx_REG was declared with
> "unsigned" and defined with "unsigned int".  The latter is usual
> GCC style.
>
>
> gcc/
> 	* rtl.h (PUT_MODE_RAW): New macro.
> 	(PUT_REG_NOTE_KIND): Use it.
> 	(set_mode_and_regno): Declare.
> 	(gen_raw_REG): Change regno to "unsigned int".
> 	(gen_rtx_REG): Change "unsigned" to "unsigned int".
> 	(PUT_MODE): Forward to PUT_MODE_RAW for generators, otherwise
> 	use set_mode_and_regno to change the mode of registers.
> 	* gengenrtl.c (gendef): Use PUT_MODE_RAW.
> 	* emit-rtl.c (set_mode_and_regno): New function.
> 	(gen_raw_REG): Change regno to unsigned int.  Use set_mode_and_regno.
> 	* caller-save.c (reg_save_code): Use set_mode_and_regno.
> 	* expr.c (init_expr_target): Likewise.
> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
> 	* postreload.c (reload_cse_simplify_operands): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [7/9] Record the number of registers in a REG
  2015-05-18 18:24 ` [7/9] Record the number of registers in a REG Richard Sandiford
@ 2015-05-18 21:33   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 21:33 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:24 PM, Richard Sandiford wrote:
> This is the main patch, to record REG_NREGS in the REG itself.
> The END_REGNO/END_HARD_REGNO distinction goes away in the next patch.
>
>
> gcc/
> 	* rtl.h (reg_info): Add an nregs field.
> 	(REG_NREGS): Use it.
> 	(SET_REGNO_RAW): Delete.
> 	(set_regno_raw): New function.
> 	* regs.h (END_HARD_REGNO): Make equivalent to END_REGNO.
> 	(END_REGNO): Redefine in terms of REG_NREGS.
> 	* read-rtl.c (read_rtx_code): Call set_regno_raw instead of
> 	SET_REGNO_RAW.
> 	* emit-rtl.c (set_mode_and_regno): Likewise.
> 	* df-scan.c (df_ref_change_reg_with_loc): Use set_mode_and_regno
> 	instead of SET_REGNO_RAW.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [8/9] Remove END_HARD_REGNO
  2015-05-18 18:26 ` [8/9] Remove END_HARD_REGNO Richard Sandiford
@ 2015-05-18 21:34   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 21:34 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:25 PM, Richard Sandiford wrote:
> This patch replaces calls to END_HARD_REGNO with calls to END_REGNO and
> moves END_REGNO to rtl.h (since it's now just a REG access).
>
>
> gcc/
> 	* regs.h (END_HARD_REGNO): Delete.
> 	(END_REGNO): Move to...
> 	* rtl.h: ...here.
> 	* bt-load.c (note_btr_set): Use END_REGNO instead of END_HARD_REGNO.
> 	* caller-save.c (mark_set_regs): Likewise.
> 	* combine.c (move_deaths, distribute_notes): Likewise.
> 	* cse.c (invalidate, invalidate_for_call): Likewise.
> 	* df-scan.c (df_ref_record): Likewise.
> 	* postreload-gcse.c (reg_changed_after_insn_p): Likewise.
> 	(record_last_reg_set_info): Likewise.
> 	* reg-stack.c (convert_regs_exit): Likewise.
> 	* reload.c (reg_overlap_mentioned_for_reload_p): Likewise.
> 	* resource.c (update_live_status): Likewise.
> 	* rtlanal.c (find_reg_fusage, find_regno_fusage): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [9/9] Simplify register bitmap operations
  2015-05-18 18:31 ` [9/9] Simplify register bitmap operations Richard Sandiford
@ 2015-05-18 21:39   ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-18 21:39 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/18/2015 12:27 PM, Richard Sandiford wrote:
> After the previous changes, several callers are left with code like:
>
>    if (HARD_REGISTER_P (x))
>      bitmap_foo_range (x, REGNO (x), REG_NREGS (x));
>    else
>      bitmap_foo (x, REGNO (x));
>
> These might as well now be:
>
>    if (REG_NREGS (x) > 1)
>      bitmap_foo_range (x, REGNO (x), REG_NREGS (x));
>    else
>      bitmap_foo (x, REGNO (x));
>
> since REG_NREGS is as cheap to test, and since single-register hard REGs
> are the common case.  But if separating out the cases is a win -- and it
> seems to be, very slightly -- then it would be better to add the shortcut
> to the range functions themselves.
>
>
> gcc/
> 	* bitmap.c (bitmap_set_range): Handle count==1 specially.
> 	(bitmap_clear_range): Likewise.
> 	* cfgcleanup.c (mark_effect): Use bitmap_clear_range and
> 	bitmap_set_range unconditionally.
> 	* df-problems.c (df_simulate_one_insn_forwards): Likewise.
> 	* df-scan.c (df_mark_reg): Likewise.
> 	* haifa-sched.c (setup_ref_regs): Likewise.
> 	* sched-rgn.c (update_live_1): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [2/9] Add a REG_NREGS macro
  2015-05-18 20:27   ` Jeff Law
@ 2015-05-19  7:00     ` Richard Sandiford
  0 siblings, 0 replies; 27+ messages in thread
From: Richard Sandiford @ 2015-05-19  7:00 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [4/9] Add a dedicated rtx union member for REGs
  2015-05-18 20:41   ` Jeff Law
@ 2015-05-19  7:04     ` Richard Sandiford
  2015-05-19  7:17       ` Jeff Law
  0 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-19  7:04 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

Jeff Law <law@redhat.com> writes:
> On 05/18/2015 12:19 PM, Richard Sandiford wrote:
>> This patch replaces the current REG "i0" format with a dedicated structure,
>> so that we can make use of the extra 32 bits in the "i" field.
>>
>> Of the places that iterate on formats and do something for 'i's,
>> most already handled REGs specially before the format walk and
>> so don't need to check for 'r'.  Otherwise it's mostly just a case
>> of adding dummy 'r' cases in order avoid the default gcc_unreachable ()
>> (in cases where we do the same for 'i').  The main exceptions are the
>> cselib.c and lra-constraints.c changes.
>>
>> final.c:leaf_renumber_regs_insn handled REGs specially but then
>> went on to do a no-op walk of the format.  I just added an early
>> exit instead of an empty 'r' case.
>>
>>
>> gcc/
>> 	* rtl.def (REG): Change format to "r".
>> 	* rtl.h (rtunion): Remove rt_reg.
>> 	(reg_info): New structure.
>> 	(rtx_def): Add reg field to main union.
>> 	(X0REGATTR): Delete.
>> 	(REG_CHECK): New macro.
>> 	(SET_REGNO_RAW, rhs_regno, REG_ATTRS): Use it.
>> 	* rtl.c (rtx_format): Document "r".
>> 	(rtx_code_size): Handle REG specially.
>> 	* gengenrtl.c (special_format): Return true for formats
>> 	that include 'r'.
>> 	* gengtype.c (adjust_field_rtx_def): Handle 'r' fields.
>> 	Deal with REG_ATTRS after the field loop.
>> 	* emit-rtl.c (gen_raw_REG): Call rtx_alloc_stat directly.
>> 	* expmed.c (init_expmed): Call gen_raw_REG instead of
>> 	gen_rtx_raw_REG.
>> 	* expr.c (init_expr_target): Likewise.
>> 	* regcprop.c (maybe_mode_change): Likewise.
>> 	* varasm.c (make_decl_rtl): Likewise.
>> 	* final.c (leaf_renumber_regs_insn): Return early after
>> 	handling REGs.
>> 	* genemit.c (gen_exp): Handle 'r' fields.
>> 	* genpeep.c (match_rtx): Likewise.
>> 	* gensupport.c (subst_pattern_match): Likewise.
>> 	(get_alternatives_number, collect_insn_data, alter_predicate_for_insn)
>> 	(alter_constraints, subst_dup): Likewise.
>> 	* read-rtl.c (read_rtx_code): Likewise.
>> 	* print-rtl.c (print_rtx): Likewise.
>> 	* genrecog.c (find_operand, find_matching_operand): Likewise.
>> 	(validate_pattern, match_pattern_2): Likewise.
>> 	(parameter::UINT, rtx_test::REGNO_FIELD): New enum values.
>> 	(rtx_test::regno_field): New function.
>> 	(operator ==, safe_to_hoist_p, transition_parameter_type)
>> 	(parameter_type_string, print_parameter_value)
>> 	(print_nonbool_test, print_test): Handle new enum values.
>> 	* cselib.c (rtx_equal_for_cselib_1): Handle REG specially.
>> 	* lra-constraints.c (operands_match_p): Likewise.
> Just to confirm, this doesn't change the size of a REG object, right? 
> If it doesn't change the size, then it's OK.

It doesn't change the size for LP64 hosts.  It makes it 32 bits bigger
for ILP32 hosts.  See https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01598.html
for discussion about that.

If we make the opposite call this time and say that it's better to have
two alternative rtx layouts rather than grow an rtx for ILP32 hosts,
then there are things we could do.  E.g. I doubt an ILP32 host has
enough addressable memory to cope with 1<<24 registers (and associated
instructions), so for ILP32 we could split original_regno into an 8/24
bitfield, using the :8 for the number of registers and the :24 for the
original_regno.  original_regno is so rarely used that an extra shift
or mask shouldn't matter.

Or we could simply leave ILP32 hosts accessing hard_regno_nregs each
time.  The problem then would be that an incorrectly-cached number
of registers would only show up on one type of host.  It would also mean
that REG_NREGS would need to be defined in regs.h for ILP32 at least,
since hard_regno_nregs isn't visible inside rtl.h.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [4/9] Add a dedicated rtx union member for REGs
  2015-05-19  7:04     ` Richard Sandiford
@ 2015-05-19  7:17       ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-19  7:17 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/19/2015 01:00 AM, Richard Sandiford wrote:
>> Just to confirm, this doesn't change the size of a REG object, right?
>> If it doesn't change the size, then it's OK.
>
> It doesn't change the size for LP64 hosts.  It makes it 32 bits bigger
> for ILP32 hosts.  See https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01598.html
> for discussion about that.
>
> If we make the opposite call this time and say that it's better to have
> two alternative rtx layouts rather than grow an rtx for ILP32 hosts,
> then there are things we could do.  E.g. I doubt an ILP32 host has
> enough addressable memory to cope with 1<<24 registers (and associated
> instructions), so for ILP32 we could split original_regno into an 8/24
> bitfield, using the :8 for the number of registers and the :24 for the
> original_regno.  original_regno is so rarely used that an extra shift
> or mask shouldn't matter.
>
> Or we could simply leave ILP32 hosts accessing hard_regno_nregs each
> time.  The problem then would be that an incorrectly-cached number
> of registers would only show up on one type of host.  It would also mean
> that REG_NREGS would need to be defined in regs.h for ILP32 at least,
> since hard_regno_nregs isn't visible inside rtl.h.
I can live with increasing on ilp32 hosts with lp64 staying the same -- 
ilp32 hosts are less and less important every day.

jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [5/9] Create sensible dummy registers
  2015-05-18 18:23 ` [5/9] Create sensible dummy registers Richard Sandiford
  2015-05-18 21:29   ` Jeff Law
@ 2015-05-19  9:02   ` Eric Botcazou
  2015-05-22 15:44     ` Richard Sandiford
  1 sibling, 1 reply; 27+ messages in thread
From: Eric Botcazou @ 2015-05-19  9:02 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> Some pieces of code create a temporary REG or MEM and only fill it
> in later when they're testing the cost of a particular rtx.  This patch
> makes sure that even the dummy REG or MEM is valid, rather than force
> the gen_* code to handle garbage values.
> 
> 
> gcc/
> 	* caller-save.c (init_caller_save): Use word_mode and
> 	FIRST_PSEUDO_REGISTER when creating temporary rtxes.
> 	* expr.c (init_expr_target): Likewise.
> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
> 	* postreload.c (reload_cse_regs_1): Likewise.

Isn't LAST_VIRTUAL_REGISTER + 1 the canonical regno to be used in this case?

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 27+ messages in thread

* breakage with series "[0/9] Record number of hard registers in a REG"
  2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
                   ` (8 preceding siblings ...)
  2015-05-18 18:31 ` [9/9] Simplify register bitmap operations Richard Sandiford
@ 2015-05-19 15:21 ` Hans-Peter Nilsson
  2015-05-19 15:54   ` Richard Sandiford
  9 siblings, 1 reply; 27+ messages in thread
From: Hans-Peter Nilsson @ 2015-05-19 15:21 UTC (permalink / raw)
  To: richard.sandiford; +Cc: gcc-patches

> From: Richard Sandiford <richard.sandiford@arm.com>
> Date: Mon, 18 May 2015 20:09:19 +0200

> While looking at a profile of gcc, I noticed one thing fairly high
> up the list was a loop iterating over all the registers in a REG,
> apparently due to the delay in computing the index for hard_regno_nregs
> and then loading the value (which would often be an L1 cache miss).

> Each patch in the series was individually bootstrapped & regression-tested
> on x86_64-linux-gnu.
> 
> Thanks,
> Richard
> 

Please also make use of config-list.mk or a subset affecting
targets.  Build succeded for cris-elf last at r223334.  Build
failed at r223355, r223364, r223366, it seems from a commit in
this patch series:

...
g++ -c   -g -O2 -DIN_GCC  -DCROSS_DIRECTORY_STRUCTURE  -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common  -DHAVE_CONFIG_H -I. -I. -I/tmp/hpautotest-gcc1/gcc/gcc -I/tmp/hpautotest-gcc1/gcc/gcc/. -I/tmp/hpautotest-gcc1/gcc/gcc/../include -I/tmp/hpautotest-gcc1/gcc/gcc/../libcpp/include -I/tmp/hpautotest-gcc1/cris-elf/gccobj/./gmp -I/tmp/hpautotest-gcc1/gcc/gmp -I/tmp/hpautotest-gcc1/cris-elf/gccobj/./mpfr -I/tmp/hpautotest-gcc1/gcc/mpfr -I/tmp/hpautotest-gcc1/gcc/mpc/src  -I/tmp/hpautotest-gcc1/gcc/gcc/../libdecnumber -I/tmp/hpautotest-gcc1/gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I/tmp/hpautotest-gcc1/gcc/gcc/../libbacktrace   -o cris.o -MT cris.o -MMD -MP -MF ./.deps/cris.TPo /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c
In file included from /tmp/hpautotest-gcc1/gcc/gcc/rtl.h:25,
                 from /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:25:
/tmp/hpautotest-gcc1/gcc/gcc/input.h:37: warning: comparison between signed and unsigned integer expressions
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c: In function 'void cris_expand_prologue()':
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3141: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3165: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3263: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c: In function 'void cris_expand_epilogue()':
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3429: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3515: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3548: error: 'gen_rtx_raw_REG' was not declared in this scope
/tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3573: error: 'gen_rtx_raw_REG' was not declared in this scope
make[2]: *** [cris.o] Error 1

brgds, H-P

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: breakage with series "[0/9] Record number of hard registers in a REG"
  2015-05-19 15:21 ` breakage with series "[0/9] Record number of hard registers in a REG" Hans-Peter Nilsson
@ 2015-05-19 15:54   ` Richard Sandiford
  0 siblings, 0 replies; 27+ messages in thread
From: Richard Sandiford @ 2015-05-19 15:54 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: gcc-patches

Hans-Peter Nilsson <hans-peter.nilsson@axis.com> writes:
> g++ -c -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions
> -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wwrite-strings
> -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic
> -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common
> -DHAVE_CONFIG_H -I. -I. -I/tmp/hpautotest-gcc1/gcc/gcc
> -I/tmp/hpautotest-gcc1/gcc/gcc/. -I/tmp/hpautotest-gcc1/gcc/gcc/../include
> -I/tmp/hpautotest-gcc1/gcc/gcc/../libcpp/include
> -I/tmp/hpautotest-gcc1/cris-elf/gccobj/./gmp
> -I/tmp/hpautotest-gcc1/gcc/gmp
> -I/tmp/hpautotest-gcc1/cris-elf/gccobj/./mpfr
> -I/tmp/hpautotest-gcc1/gcc/mpfr -I/tmp/hpautotest-gcc1/gcc/mpc/src
> -I/tmp/hpautotest-gcc1/gcc/gcc/../libdecnumber
> -I/tmp/hpautotest-gcc1/gcc/gcc/../libdecnumber/dpd -I../libdecnumber
> -I/tmp/hpautotest-gcc1/gcc/gcc/../libbacktrace -o cris.o -MT cris.o -MMD
> -MP -MF ./.deps/cris.TPo /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c
> In file included from /tmp/hpautotest-gcc1/gcc/gcc/rtl.h:25,
>                  from /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:25:
> /tmp/hpautotest-gcc1/gcc/gcc/input.h:37: warning: comparison between
> signed and unsigned integer expressions
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c: In function 'void
> cris_expand_prologue()':
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3141: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3165: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3263: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c: In function 'void
> cris_expand_epilogue()':
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3429: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3515: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3548: error:
> gen_rtx_raw_REG' was not declared in this scope
> /tmp/hpautotest-gcc1/gcc/gcc/config/cris/cris.c:3573: error:
> gen_rtx_raw_REG' was not declared in this scope
> make[2]: *** [cris.o] Error 1

Installed as obvious after testing that cris-elf, microblaze-elf
and sparc-linux-gnu now build.  Obviously I mustn't have used
the usual recursive grep.

Thanks,
Richard


gcc/
	* config/cris/cris.c (cris_expand_prologue): Use gen_raw_REG
	instead of gen_rtx_raw_REG.
	(cris_expand_epilogue): Likewise.
	* config/microblaze/microblaze.c (microblaze_classify_address):
	Likewise.
	* config/sparc/sparc.md: Likewise.

Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	2015-05-19 16:40:34.734003511 +0100
+++ gcc/config/cris/cris.c	2015-05-19 16:40:34.890001679 +0100
@@ -3138,7 +3138,7 @@ cris_expand_prologue (void)
 
 	  mem = gen_rtx_MEM (SImode, stack_pointer_rtx);
 	  set_mem_alias_set (mem, get_varargs_alias_set ());
-	  insn = emit_move_insn (mem, gen_rtx_raw_REG (SImode, regno));
+	  insn = emit_move_insn (mem, gen_raw_REG (SImode, regno));
 
 	  /* Note the absence of RTX_FRAME_RELATED_P on the above insn:
 	     the value isn't restored, so we don't want to tell dwarf2
@@ -3162,7 +3162,7 @@ cris_expand_prologue (void)
 
       mem = gen_rtx_MEM (SImode, stack_pointer_rtx);
       set_mem_alias_set (mem, get_frame_alias_set ());
-      insn = emit_move_insn (mem, gen_rtx_raw_REG (SImode, CRIS_SRP_REGNUM));
+      insn = emit_move_insn (mem, gen_raw_REG (SImode, CRIS_SRP_REGNUM));
       RTX_FRAME_RELATED_P (insn) = 1;
       framesize += 4;
     }
@@ -3260,7 +3260,7 @@ cris_expand_prologue (void)
 
 	      mem = gen_rtx_MEM (SImode, stack_pointer_rtx);
 	      set_mem_alias_set (mem, get_frame_alias_set ());
-	      insn = emit_move_insn (mem, gen_rtx_raw_REG (SImode, regno));
+	      insn = emit_move_insn (mem, gen_raw_REG (SImode, regno));
 	      RTX_FRAME_RELATED_P (insn) = 1;
 
 	      framesize += 4 + size;
@@ -3426,7 +3426,7 @@ cris_expand_epilogue (void)
 	mem = gen_rtx_MEM (SImode, gen_rtx_POST_INC (SImode,
 						     stack_pointer_rtx));
 	set_mem_alias_set (mem, get_frame_alias_set ());
-	insn = emit_move_insn (gen_rtx_raw_REG (SImode, regno), mem);
+	insn = emit_move_insn (gen_raw_REG (SImode, regno), mem);
 
 	/* Whenever we emit insns with post-incremented addresses
 	   ourselves, we must add a post-inc note manually.  */
@@ -3512,7 +3512,7 @@ cris_expand_epilogue (void)
 	{
 	  rtx mem;
 	  rtx insn;
-	  rtx srpreg = gen_rtx_raw_REG (SImode, CRIS_SRP_REGNUM);
+	  rtx srpreg = gen_raw_REG (SImode, CRIS_SRP_REGNUM);
 	  mem = gen_rtx_MEM (SImode,
 			     gen_rtx_POST_INC (SImode,
 					       stack_pointer_rtx));
@@ -3527,8 +3527,7 @@ cris_expand_epilogue (void)
 	  if (crtl->calls_eh_return)
 	    emit_insn (gen_addsi3 (stack_pointer_rtx,
 				   stack_pointer_rtx,
-				   gen_rtx_raw_REG (SImode,
-						    CRIS_STACKADJ_REG)));
+				   gen_raw_REG (SImode, CRIS_STACKADJ_REG)));
 	  cris_expand_return (false);
 	}
       else
@@ -3545,7 +3544,7 @@ cris_expand_epilogue (void)
       if (return_address_on_stack)
 	{
 	  rtx mem;
-	  rtx srpreg = gen_rtx_raw_REG (SImode, CRIS_SRP_REGNUM);
+	  rtx srpreg = gen_raw_REG (SImode, CRIS_SRP_REGNUM);
 	  rtx insn;
 
 	  mem = gen_rtx_MEM (SImode,
@@ -3569,8 +3568,7 @@ cris_expand_epilogue (void)
   if (crtl->calls_eh_return)
     emit_insn (gen_addsi3 (stack_pointer_rtx,
 			   stack_pointer_rtx,
-			   gen_rtx_raw_REG (SImode,
-					    CRIS_STACKADJ_REG)));
+			   gen_raw_REG (SImode, CRIS_STACKADJ_REG)));
   cris_expand_return (false);
 }
 
Index: gcc/config/microblaze/microblaze.c
===================================================================
--- gcc/config/microblaze/microblaze.c	2015-05-19 16:40:34.738003464 +0100
+++ gcc/config/microblaze/microblaze.c	2015-05-19 16:40:34.890001679 +0100
@@ -866,7 +866,7 @@ microblaze_classify_address (struct micr
       }
     case CONST_INT:
       {
-	info->regA = gen_rtx_raw_REG (mode, 0);
+	info->regA = gen_raw_REG (mode, 0);
 	info->type = ADDRESS_CONST_INT;
 	info->offset = x;
 	return true;
@@ -878,13 +878,13 @@ microblaze_classify_address (struct micr
 	info->type = ADDRESS_SYMBOLIC;
 	info->symbol_type = SYMBOL_TYPE_GENERAL;
 	info->symbol = x;
-	info->regA = gen_rtx_raw_REG (mode, get_base_reg (x));
+	info->regA = gen_raw_REG (mode, get_base_reg (x));
 
 	if (GET_CODE (x) == CONST)
 	  {
 	    if (GET_CODE (XEXP (x, 0)) == UNSPEC)
 	     {
-		info->regA = gen_rtx_raw_REG (mode,
+		info->regA = gen_raw_REG (mode,
 				  get_base_reg (XVECEXP (XEXP (x,0), 0, 0)));
 		return microblaze_classify_unspec (info, XEXP (x, 0));
 	     }
Index: gcc/config/sparc/sparc.md
===================================================================
--- gcc/config/sparc/sparc.md	2015-05-19 16:40:34.738003464 +0100
+++ gcc/config/sparc/sparc.md	2015-05-19 16:40:34.894001632 +0100
@@ -2364,7 +2364,7 @@ (define_split
    && reload_completed"
   [(clobber (const_int 0))]
 {
-  operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
+  operands[0] = gen_raw_REG (DImode, REGNO (operands[0]));
 
   if (TARGET_ARCH64)
     {

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [5/9] Create sensible dummy registers
  2015-05-19  9:02   ` Eric Botcazou
@ 2015-05-22 15:44     ` Richard Sandiford
  2015-05-22 20:05       ` Jeff Law
  0 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2015-05-22 15:44 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@adacore.com> writes:
>> Some pieces of code create a temporary REG or MEM and only fill it
>> in later when they're testing the cost of a particular rtx.  This patch
>> makes sure that even the dummy REG or MEM is valid, rather than force
>> the gen_* code to handle garbage values.
>> 
>> 
>> gcc/
>> 	* caller-save.c (init_caller_save): Use word_mode and
>> 	FIRST_PSEUDO_REGISTER when creating temporary rtxes.
>> 	* expr.c (init_expr_target): Likewise.
>> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
>> 	* postreload.c (reload_cse_regs_1): Likewise.
>
> Isn't LAST_VIRTUAL_REGISTER + 1 the canonical regno to be used in this case?

Ah, yeah.  Here's patch to fix all instances of that (I hope).

Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
	* caller-save.c (init_caller_save): Base temporary register numbers
	on LAST_VIRTUAL_REGISTER + 1 rather than FIRST_PSEUDO_REGISTER.
	* cfgloopanal.c (init_set_costs): Likewise.
	* dojump.c (prefer_and_bit_test): Likewise.
	* expr.c (init_expr_target): Likewise.
	* ira.c (setup_prohibited_mode_move_regs): Likewise.
	* lower-subreg.c (init_lower_subreg): Likewise.
	* postreload.c (reload_cse_regs_1): Likewise.

Index: gcc/caller-save.c
===================================================================
--- gcc/caller-save.c	2015-05-21 08:31:02.045801973 +0100
+++ gcc/caller-save.c	2015-05-21 08:31:02.257799438 +0100
@@ -286,7 +286,7 @@ init_caller_save (void)
      To avoid lots of unnecessary RTL allocation, we construct all the RTL
      once, then modify the memory and register operands in-place.  */
 
-  test_reg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
   test_mem = gen_rtx_MEM (word_mode, address);
   savepat = gen_rtx_SET (test_mem, test_reg);
   restpat = gen_rtx_SET (test_reg, test_mem);
Index: gcc/cfgloopanal.c
===================================================================
--- gcc/cfgloopanal.c	2015-05-21 08:31:02.045801973 +0100
+++ gcc/cfgloopanal.c	2015-05-21 08:31:02.257799438 +0100
@@ -336,9 +336,9 @@ init_set_costs (void)
 {
   int speed;
   rtx_insn *seq;
-  rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER);
-  rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1);
-  rtx addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 2);
+  rtx reg1 = gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 1);
+  rtx reg2 = gen_raw_REG (SImode, LAST_VIRTUAL_REGISTER + 2);
+  rtx addr = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 3);
   rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
   unsigned i;
 
Index: gcc/dojump.c
===================================================================
--- gcc/dojump.c	2015-05-21 08:31:02.045801973 +0100
+++ gcc/dojump.c	2015-05-21 08:31:02.257799438 +0100
@@ -196,7 +196,7 @@ prefer_and_bit_test (machine_mode mode,
     {
       /* Set up rtxes for the two variations.  Use NULL as a placeholder
 	 for the BITNUM-based constants.  */
-      and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER);
+      and_reg = gen_rtx_REG (mode, LAST_VIRTUAL_REGISTER + 1);
       and_test = gen_rtx_AND (mode, and_reg, NULL);
       shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL),
 				const1_rtx);
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2015-05-21 08:31:02.049801925 +0100
+++ gcc/expr.c	2015-05-21 08:31:02.257799438 +0100
@@ -207,7 +207,7 @@ init_expr_target (void)
 
   /* A scratch register we can modify in-place below to avoid
      useless RTL allocations.  */
-  reg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
 
   insn = rtx_alloc (INSN);
   pat = gen_rtx_SET (NULL_RTX, NULL_RTX);
@@ -257,7 +257,7 @@ init_expr_target (void)
 	  }
     }
 
-  mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER));
+  mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1));
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2015-05-21 08:31:02.049801925 +0100
+++ gcc/ira.c	2015-05-21 08:31:02.261799391 +0100
@@ -1767,8 +1767,8 @@ setup_prohibited_mode_move_regs (void)
   if (ira_prohibited_mode_move_regs_initialized_p)
     return;
   ira_prohibited_mode_move_regs_initialized_p = true;
-  test_reg1 = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
-  test_reg2 = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  test_reg1 = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
+  test_reg2 = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
   move_pat = gen_rtx_SET (test_reg1, test_reg2);
   move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, move_pat, 0, -1, 0);
   for (i = 0; i < NUM_MACHINE_MODES; i++)
Index: gcc/lower-subreg.c
===================================================================
--- gcc/lower-subreg.c	2015-05-21 08:31:02.049801925 +0100
+++ gcc/lower-subreg.c	2015-05-21 08:31:02.261799391 +0100
@@ -302,8 +302,8 @@ init_lower_subreg (void)
 
   twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode);
 
-  rtxes.target = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
-  rtxes.source = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER + 1);
+  rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
+  rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
   rtxes.set = gen_rtx_SET (rtxes.target, rtxes.source);
   rtxes.zext = gen_rtx_ZERO_EXTEND (twice_word_mode, rtxes.source);
   rtxes.shift = gen_rtx_ASHIFT (twice_word_mode, rtxes.source, const0_rtx);
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2015-05-21 08:31:02.049801925 +0100
+++ gcc/postreload.c	2015-05-21 08:31:02.261799391 +0100
@@ -234,7 +234,7 @@ reload_cse_regs_1 (void)
   bool cfg_changed = false;
   basic_block bb;
   rtx_insn *insn;
-  rtx testreg = gen_rtx_REG (word_mode, FIRST_PSEUDO_REGISTER);
+  rtx testreg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
 
   cselib_init (CSELIB_RECORD_MEMORY);
   init_alias_analysis ();

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [5/9] Create sensible dummy registers
  2015-05-22 15:44     ` Richard Sandiford
@ 2015-05-22 20:05       ` Jeff Law
  0 siblings, 0 replies; 27+ messages in thread
From: Jeff Law @ 2015-05-22 20:05 UTC (permalink / raw)
  To: Eric Botcazou, gcc-patches, richard.sandiford

On 05/22/2015 09:39 AM, Richard Sandiford wrote:
> Eric Botcazou <ebotcazou@adacore.com> writes:
>>> Some pieces of code create a temporary REG or MEM and only fill it
>>> in later when they're testing the cost of a particular rtx.  This patch
>>> makes sure that even the dummy REG or MEM is valid, rather than force
>>> the gen_* code to handle garbage values.
>>>
>>>
>>> gcc/
>>> 	* caller-save.c (init_caller_save): Use word_mode and
>>> 	FIRST_PSEUDO_REGISTER when creating temporary rtxes.
>>> 	* expr.c (init_expr_target): Likewise.
>>> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
>>> 	* postreload.c (reload_cse_regs_1): Likewise.
>>
>> Isn't LAST_VIRTUAL_REGISTER + 1 the canonical regno to be used in this case?
>
> Ah, yeah.  Here's patch to fix all instances of that (I hope).
>
> Bootstrapped & regression-tested on x86_64-linux-gnu.  OK to install?
>
> Thanks,
> Richard
>
>
> gcc/
> 	* caller-save.c (init_caller_save): Base temporary register numbers
> 	on LAST_VIRTUAL_REGISTER + 1 rather than FIRST_PSEUDO_REGISTER.
> 	* cfgloopanal.c (init_set_costs): Likewise.
> 	* dojump.c (prefer_and_bit_test): Likewise.
> 	* expr.c (init_expr_target): Likewise.
> 	* ira.c (setup_prohibited_mode_move_regs): Likewise.
> 	* lower-subreg.c (init_lower_subreg): Likewise.
> 	* postreload.c (reload_cse_regs_1): Likewise.
OK.
jeff

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2015-05-22 19:49 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-18 18:11 [0/9] Record number of hard registers in a REG Richard Sandiford
2015-05-18 18:13 ` [1/9] Make more use of END_REGNO Richard Sandiford
2015-05-18 19:06   ` Jeff Law
2015-05-18 18:15 ` [2/9] Add a REG_NREGS macro Richard Sandiford
2015-05-18 20:27   ` Jeff Law
2015-05-19  7:00     ` Richard Sandiford
2015-05-18 18:19 ` [3/9] Clean up df_ref_change_reg_with_loc Richard Sandiford
2015-05-18 20:33   ` Jeff Law
2015-05-18 18:22 ` [4/9] Add a dedicated rtx union member for REGs Richard Sandiford
2015-05-18 20:41   ` Jeff Law
2015-05-19  7:04     ` Richard Sandiford
2015-05-19  7:17       ` Jeff Law
2015-05-18 18:23 ` [5/9] Create sensible dummy registers Richard Sandiford
2015-05-18 21:29   ` Jeff Law
2015-05-19  9:02   ` Eric Botcazou
2015-05-22 15:44     ` Richard Sandiford
2015-05-22 20:05       ` Jeff Law
2015-05-18 18:24 ` [7/9] Record the number of registers in a REG Richard Sandiford
2015-05-18 21:33   ` Jeff Law
2015-05-18 18:24 ` [6/9] Pass REG changes through a new function Richard Sandiford
2015-05-18 21:32   ` Jeff Law
2015-05-18 18:26 ` [8/9] Remove END_HARD_REGNO Richard Sandiford
2015-05-18 21:34   ` Jeff Law
2015-05-18 18:31 ` [9/9] Simplify register bitmap operations Richard Sandiford
2015-05-18 21:39   ` Jeff Law
2015-05-19 15:21 ` breakage with series "[0/9] Record number of hard registers in a REG" Hans-Peter Nilsson
2015-05-19 15:54   ` Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).