diff mbox

[4/9] Add a dedicated rtx union member for REGs

Message ID 87617pu4sr.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford May 18, 2015, 6:19 p.m. UTC
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.

Comments

Jeff Law May 18, 2015, 8:40 p.m. UTC | #1
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
Richard Sandiford May 19, 2015, 7 a.m. UTC | #2
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
Jeff Law May 19, 2015, 7:04 a.m. UTC | #3
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
diff mbox

Patch

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;