+2015-05-19 Richard Sandiford <richard.sandiford@arm.com>
+
+ * 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.
+
2015-05-19 Richard Sandiford <richard.sandiford@arm.com>
* df.h (df_ref_change_reg_with_loc): Remove old_regno parameter.
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. */
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;
}
}
/* 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);
}
}
- 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))
df_set_regs_ever_live (newreg, true);
SET_REGNO (in_rtx, newreg);
in_rtx->used = 1;
+ return;
}
if (INSN_P (in_rtx))
printf ("%u", XINT (x, i));
break;
+ case 'r':
+ printf ("%u", REGNO (x));
+ break;
+
case 's':
printf ("\"%s\"", XSTR (x, i));
break;
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. */
case 'i':
case 'n':
case 'w':
+ case 'r':
t = scalar_tp;
subname = "rt_int";
break;
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)
"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
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. */
return r;
break;
- case 'i': case 'w': case '0': case 's':
+ case 'i': case 'r': case 'w': case '0': case 's':
break;
default:
return r;
break;
- case 'i': case 'w': case '0': case 's':
+ case 'i': case 'r': case 'w': case '0': case 's':
break;
default:
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:
/* An int parameter. */
INT,
+ /* An unsigned int parameter. */
+ UINT,
+
/* A HOST_WIDE_INT parameter. */
WIDE_INT
};
/* Check GET_MODE (X) == LABEL. */
MODE,
+ /* Check REGNO (X) == LABEL. */
+ REGNO_FIELD,
+
/* Check XINT (X, u.opno) == LABEL. */
INT_FIELD,
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 *);
return rtx_test (pos, rtx_test::MODE);
}
+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)
{
{
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;
}
gcc_unreachable ();
+ case rtx_test::REGNO_FIELD:
case rtx_test::INT_FIELD:
case rtx_test::WIDE_INT_FIELD:
case rtx_test::VECLEN:
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:
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),
case parameter::INT:
return "int";
+ case parameter::UINT:
+ return "unsigned int";
+
case parameter::WIDE_INT:
return "HOST_WIDE_INT";
}
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;
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);
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:
switch (fmt[i])
{
- case 'i': case 'w': case 's':
+ case 'i': case 'r': case 'w': case 's':
continue;
case 'e': case 'u':
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:
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:
}
break;
- case 'i': case 'w': case '0': case 's':
+ case 'i': case 'r': case 'w': case '0': case 's':
break;
default:
}
break;
- case 'i': case 'w': case '0': case 's':
+ case 'i': case 'r': case 'w': case '0': case 's':
break;
default:
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:
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;
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)
}
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':
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 ();
}
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];
+ (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;
}
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 */
(((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"
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
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. */
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;
__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); \
#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)
#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. */
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
static inline unsigned int
rhs_regno (const_rtx x)
{
- return XCUINT (x, 0, REG);
+ return REG_CHECK (x)->regno;
}
/* 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
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;