md.texi (define_enum_attr): Document.

gcc/
	* doc/md.texi (define_enum_attr): Document.
	* rtl.def (DEFINE_ENUM_ATTR): New rtx.
	* read-md.h (lookup_enum_type): Declare.
	* read-md.c (lookup_enum_type): New function.
	* genattr.c (gen_attr, main): Handle DEFINE_ENUM_ATTR.
	* genattrtab.c (attr_desc): Add an enum_name field.
	(evaluate_eq_attr): Take the associated attribute as argument.
	Get the enum prefix from the enum_name field, if defined.
	Use ACONCAT rather than a fixed-length buffer.  Update recursive calls.
	(simplify_test_exp): Pass attr to evaluate_eq_attr.
	(add_attr_value): New function, split out from...
	(gen_attr): ...here.  Handle DEFINE_ENUM_ATTR.
	(write_test_expr): Pass attr to evaluate_eq_attr.
	(write_attr_get): Use the enum_name as the enum tag, if defined.
	(write_attr_valueq): Use the enum_name as a prefix, if defined.
	(find_attr): Initialize enum_name.
	(main): Handle DEFINE_ENUM_ATTR.
	* gensupport.c (process_rtx): Likewise.
	* config/mips/mips.h (mips_tune_attr): Delete.
	* config/mips/mips.md (cpu): Use define_attr_enum.

From-SVN: r160581
This commit is contained in:
Richard Sandiford 2010-06-10 20:24:17 +00:00 committed by Richard Sandiford
parent 24609606bd
commit 8f4fe86cd1
10 changed files with 163 additions and 58 deletions

View File

@ -1,3 +1,26 @@
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
* doc/md.texi (define_enum_attr): Document.
* rtl.def (DEFINE_ENUM_ATTR): New rtx.
* read-md.h (lookup_enum_type): Declare.
* read-md.c (lookup_enum_type): New function.
* genattr.c (gen_attr, main): Handle DEFINE_ENUM_ATTR.
* genattrtab.c (attr_desc): Add an enum_name field.
(evaluate_eq_attr): Take the associated attribute as argument.
Get the enum prefix from the enum_name field, if defined.
Use ACONCAT rather than a fixed-length buffer. Update recursive calls.
(simplify_test_exp): Pass attr to evaluate_eq_attr.
(add_attr_value): New function, split out from...
(gen_attr): ...here. Handle DEFINE_ENUM_ATTR.
(write_test_expr): Pass attr to evaluate_eq_attr.
(write_attr_get): Use the enum_name as the enum tag, if defined.
(write_attr_valueq): Use the enum_name as a prefix, if defined.
(find_attr): Initialize enum_name.
(main): Handle DEFINE_ENUM_ATTR.
* gensupport.c (process_rtx): Likewise.
* config/mips/mips.h (mips_tune_attr): Delete.
* config/mips/mips.md (cpu): Use define_attr_enum.
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
* doc/md.texi (define_c_enum, define_enum): Document.

View File

@ -3035,10 +3035,6 @@ extern enum mips_code_readable_setting mips_code_readable;
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
mips_final_prescan_insn (INSN, OPVEC, NOPERANDS)
/* This is necessary to avoid a warning about comparing different enum
types. */
#define mips_tune_attr ((enum attr_cpu) mips_tune)
/* As on most targets, we want the .eh_frame section to be read-only where
possible. And as on most targets, this means two things:

View File

@ -508,11 +508,9 @@
(symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
] (const_int 4)))
;; Attribute describing the processor. This attribute must match exactly
;; with the processor enumeration above.
(define_attr "cpu"
"r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr"
(const (symbol_ref "mips_tune_attr")))
;; Attribute describing the processor.
(define_enum_attr "cpu" "processor"
(const (symbol_ref "mips_tune")))
;; The type of hardware hazard associated with this instruction.
;; DELAY means that the next instruction cannot read the result

View File

@ -6700,9 +6700,46 @@ distances. @xref{Insn Lengths}.
The @code{enabled} attribute can be defined to prevent certain
alternatives of an insn definition from being used during code
generation. @xref{Disable Insn Alternatives}.
@end table
@findex define_enum_attr
@anchor{define_enum_attr}
Another way of defining an attribute is to use:
@smallexample
(define_enum_attr "@var{attr}" "@var{enum}" @var{default})
@end smallexample
This works in just the same way as @code{define_attr}, except that
the list of values is taken from a separate enumeration called
@var{enum} (@pxref{define_enum}). This form allows you to use
the same list of values for several attributes without having to
repeat the list each time. For example:
@smallexample
(define_enum "processor" [
model_a
model_b
@dots{}
])
(define_enum_attr "arch" "processor"
(const (symbol_ref "target_arch")))
(define_enum_attr "tune" "processor"
(const (symbol_ref "target_tune")))
@end smallexample
defines the same attributes as:
@smallexample
(define_attr "arch" "model_a,model_b,@dots{}"
(const (symbol_ref "target_arch")))
(define_attr "tune" "model_a,model_b,@dots{}"
(const (symbol_ref "target_tune")))
@end smallexample
but without duplicating the processor list. The second example defines two
separate C enums (@code{attr_arch} and @code{attr_tune}) whereas the first
defines a single C enum (@code{processor}).
@end ifset
@ifset INTERNALS
@node Expressions
@ -7961,6 +7998,7 @@ it is convenient to define all synchronization-specific enumeration
values in @file{sync.md} rather than in the main @file{.md} file.
@findex define_enum
@anchor{define_enum}
Another way of defining an enumeration is to use @code{define_enum}:
@smallexample
@ -7983,7 +8021,11 @@ This directive implies:
])
@end smallexample
@findex define_enum_attr
where @var{cvaluei} is the capitalized form of @var{valuei}.
However, unlike @code{define_c_enum}, the enumerations defined
by @code{define_enum} can be used in attribute specifications
(@pxref{define_enum_attr}).
@end ifset
@ifset INTERNALS
@node Iterators

View File

@ -49,27 +49,33 @@ gen_attr (rtx attr)
printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
/* If numeric attribute, don't need to write an enum. */
p = XSTR (attr, 1);
if (*p == '\0')
printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
(is_const ? "void" : "rtx"));
if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
printf ("extern enum %s get_attr_%s (%s);\n\n",
XSTR (attr, 1), XSTR (attr, 0), (is_const ? "void" : "rtx"));
else
{
printf ("enum attr_%s {", XSTR (attr, 0));
while ((tag = scan_comma_elt (&p)) != 0)
p = XSTR (attr, 1);
if (*p == '\0')
printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
(is_const ? "void" : "rtx"));
else
{
write_upcase (XSTR (attr, 0));
putchar ('_');
while (tag != p)
putchar (TOUPPER (*tag++));
if (*p == ',')
fputs (", ", stdout);
}
printf ("enum attr_%s {", XSTR (attr, 0));
fputs ("};\n", stdout);
printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
while ((tag = scan_comma_elt (&p)) != 0)
{
write_upcase (XSTR (attr, 0));
putchar ('_');
while (tag != p)
putchar (TOUPPER (*tag++));
if (*p == ',')
fputs (", ", stdout);
}
fputs ("};\n", stdout);
printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
}
}
/* If `length' attribute, write additional function definitions and define
@ -122,7 +128,8 @@ main (int argc, char **argv)
if (desc == NULL)
break;
if (GET_CODE (desc) == DEFINE_ATTR)
if (GET_CODE (desc) == DEFINE_ATTR
|| GET_CODE (desc) == DEFINE_ENUM_ATTR)
gen_attr (desc);
else if (GET_CODE (desc) == DEFINE_DELAY)

View File

@ -171,6 +171,7 @@ struct attr_value
struct attr_desc
{
char *name; /* Name of attribute. */
const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */
struct attr_desc *next; /* Next attribute. */
struct attr_value *first_value; /* First value of this attribute. */
struct attr_value *default_val; /* Default value for this attribute. */
@ -1901,11 +1902,13 @@ make_alternative_compare (int mask)
computation. If a test condition involves an address, we leave the EQ_ATTR
intact because addresses are only valid for the `length' attribute.
EXP is the EQ_ATTR expression and VALUE is the value of that attribute
for the insn corresponding to INSN_CODE and INSN_INDEX. */
EXP is the EQ_ATTR expression and ATTR is the attribute to which
it refers. VALUE is the value of that attribute for the insn
corresponding to INSN_CODE and INSN_INDEX. */
static rtx
evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
evaluate_eq_attr (rtx exp, struct attr_desc *attr, rtx value,
int insn_code, int insn_index)
{
rtx orexp, andexp;
rtx right;
@ -1923,16 +1926,12 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
case SYMBOL_REF:
{
char *p;
char string[256];
const char *prefix;
char *string, *p;
gcc_assert (GET_CODE (exp) == EQ_ATTR);
gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2
<= 256);
strcpy (string, XSTR (exp, 0));
strcat (string, "_");
strcat (string, XSTR (exp, 1));
prefix = attr->enum_name ? attr->enum_name : attr->name;
string = ACONCAT ((prefix, "_", XSTR (exp, 1), NULL));
for (p = string; *p; p++)
*p = TOUPPER (*p);
@ -1966,7 +1965,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
right = insert_right_side (AND, andexp, this_cond,
insn_code, insn_index);
right = insert_right_side (AND, right,
evaluate_eq_attr (exp,
evaluate_eq_attr (exp, attr,
XVECEXP (value, 0,
i + 1),
insn_code, insn_index),
@ -1982,7 +1981,7 @@ evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
/* Handle the default case. */
right = insert_right_side (AND, andexp,
evaluate_eq_attr (exp, XEXP (value, 1),
evaluate_eq_attr (exp, attr, XEXP (value, 1),
insn_code, insn_index),
insn_code, insn_index);
newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
@ -2732,7 +2731,8 @@ simplify_test_exp (rtx exp, int insn_code, int insn_index)
if (av)
{
got_av:
x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
x = evaluate_eq_attr (exp, attr, av->value,
insn_code, insn_index);
x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
if (attr_rtx_cost(x) < 20)
return x;
@ -2900,13 +2900,30 @@ clear_struct_flag (rtx x)
}
}
/* Create table entries for DEFINE_ATTR. */
/* Add attribute value NAME to the beginning of ATTR's list. */
static void
add_attr_value (struct attr_desc *attr, const char *name)
{
struct attr_value *av;
av = oballoc (struct attr_value);
av->value = attr_rtx (CONST_STRING, name);
av->next = attr->first_value;
attr->first_value = av;
av->first_insn = NULL;
av->num_insns = 0;
av->has_asm_insn = 0;
}
/* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR. */
static void
gen_attr (rtx exp, int lineno)
{
struct enum_type *et;
struct enum_value *ev;
struct attr_desc *attr;
struct attr_value *av;
const char *name_ptr;
char *p;
@ -2922,21 +2939,23 @@ gen_attr (rtx exp, int lineno)
}
attr->lineno = lineno;
if (*XSTR (exp, 1) == '\0')
if (GET_CODE (exp) == DEFINE_ENUM_ATTR)
{
attr->enum_name = XSTR (exp, 1);
et = lookup_enum_type (XSTR (exp, 1));
if (!et || !et->md_p)
error_with_line (lineno, "No define_enum called `%s' defined",
attr->name);
for (ev = et->values; ev; ev = ev->next)
add_attr_value (attr, ev->name);
}
else if (*XSTR (exp, 1) == '\0')
attr->is_numeric = 1;
else
{
name_ptr = XSTR (exp, 1);
while ((p = next_comma_elt (&name_ptr)) != NULL)
{
av = oballoc (struct attr_value);
av->value = attr_rtx (CONST_STRING, p);
av->next = attr->first_value;
attr->first_value = av;
av->first_insn = NULL;
av->num_insns = 0;
av->has_asm_insn = 0;
}
add_attr_value (attr, p);
}
if (GET_CODE (XEXP (exp, 2)) == CONST)
@ -3319,8 +3338,8 @@ write_test_expr (rtx exp, int flags)
/* Now is the time to expand the value of a constant attribute. */
if (attr->is_const)
{
write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
-2, -2),
write_test_expr (evaluate_eq_attr (exp, attr,
attr->default_val->value, -2, -2),
flags);
}
else
@ -3612,7 +3631,9 @@ write_attr_get (struct attr_desc *attr)
/* Write out start of function, then all values with explicit `case' lines,
then a `default', then the value with the most uses. */
if (!attr->is_numeric)
if (attr->enum_name)
printf ("enum %s\n", attr->enum_name);
else if (!attr->is_numeric)
printf ("enum attr_%s\n", attr->name);
else
printf ("int\n");
@ -3869,7 +3890,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s)
}
else
{
write_upcase (attr->name);
write_upcase (attr->enum_name ? attr->enum_name : attr->name);
printf ("_");
write_upcase (s);
}
@ -4133,6 +4154,7 @@ find_attr (const char **name_p, int create)
attr = oballoc (struct attr_desc);
attr->name = DEF_ATTR_STRING (name);
attr->enum_name = 0;
attr->first_value = attr->default_val = NULL;
attr->is_numeric = attr->is_const = attr->is_special = 0;
attr->next = attrs[index];
@ -4459,6 +4481,7 @@ from the machine description file `md'. */\n\n");
break;
case DEFINE_ATTR:
case DEFINE_ENUM_ATTR:
gen_attr (desc, lineno);
break;

View File

@ -173,6 +173,7 @@ process_rtx (rtx desc, int lineno)
break;
case DEFINE_ATTR:
case DEFINE_ENUM_ATTR:
queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
break;

View File

@ -847,6 +847,14 @@ handle_enum (int lineno, bool md_p)
}
}
/* Try to find the definition of the given enum. Return null on failure. */
struct enum_type *
lookup_enum_type (const char *name)
{
return (struct enum_type *) htab_find (enum_types, &name);
}
/* For every enum definition, call CALLBACK with two arguments:
a pointer to the constant definition and INFO. Stop when CALLBACK
returns zero. */

View File

@ -135,5 +135,6 @@ extern const char *scan_comma_elt (const char **);
extern void upcase_string (char *);
extern void traverse_md_constants (htab_trav, void *);
extern void traverse_enum_types (htab_trav, void *);
extern struct enum_type *lookup_enum_type (const char *);
extern bool read_md_files (int, char **, bool (*) (const char *),
directive_handler_t);

View File

@ -1198,6 +1198,12 @@ DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", RTX_EXT
3rd operand: expression for the default value of the attribute. */
DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", RTX_EXTRA)
/* Definition of an insn attribute that uses an existing enumerated type.
1st operand: name of the attribute
2nd operand: the name of the enumerated type
3rd operand: expression for the default value of the attribute. */
DEF_RTL_EXPR(DEFINE_ENUM_ATTR, "define_enum_attr", "sse", RTX_EXTRA)
/* Marker for the name of an attribute. */
DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)