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;