This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
genattrtab enhancement
- To: egcs-patches at egcs dot cygnus dot com
- Subject: genattrtab enhancement
- From: Richard Henderson <rth at cygnus dot com>
- Date: Sun, 21 Feb 1999 18:41:32 -0800
The following patch allows a target to use more interesting
expressions in numeric attributes, and in particular, make
calls from one attribute to another.
r~
+ * genattrtab.c (check_attr_value): Allow negative const_int if
+ negative_ok. Accept integral arithmetic operators. Accept
+ direct references to other attributes. Accept symbol_ref in
+ non-constant attributes.
+ (max_attr_value): Add new argument `unknownp'. Update all callers.
+ (or_attr_value): Likewise.
+ (simplify_knowing): Don't optimize if max_attr_value unknown.
+ (write_length_unit_log): Likewise with or_attr_value.
+ (find_and_mark_used_attributes): Don't fallthru case.
+ (write_attr_set): Pass thru all non-cond expressions.
+ (write_attr_value): Handle symbol_ref, attr, and arithmetic.
Index: genattrtab.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/genattrtab.c,v
retrieving revision 1.45
diff -c -p -d -r1.45 genattrtab.c
*** genattrtab.c 1999/01/22 11:51:53 1.45
--- genattrtab.c 1999/02/22 01:38:23
*************** static void gen_insn PROTO((rtx));
*** 426,433 ****
static void gen_delay PROTO((rtx));
static void gen_unit PROTO((rtx));
static void write_test_expr PROTO((rtx, int));
! static int max_attr_value PROTO((rtx));
! static int or_attr_value PROTO((rtx));
static void walk_attr_value PROTO((rtx));
static void write_attr_get PROTO((struct attr_desc *));
static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
--- 426,433 ----
static void gen_delay PROTO((rtx));
static void gen_unit PROTO((rtx));
static void write_test_expr PROTO((rtx, int));
! static int max_attr_value PROTO((rtx, int*));
! static int or_attr_value PROTO((rtx, int*));
static void walk_attr_value PROTO((rtx));
static void write_attr_get PROTO((struct attr_desc *));
static rtx eliminate_known_true PROTO((rtx, rtx, int, int));
*************** check_attr_value (exp, attr)
*** 1083,1089 ****
fatal ("CONST_INT not valid for non-numeric `%s' attribute",
attr->name);
! if (INTVAL (exp) < 0)
fatal ("Negative numeric value specified for `%s' attribute",
attr->name);
--- 1083,1089 ----
fatal ("CONST_INT not valid for non-numeric `%s' attribute",
attr->name);
! if (INTVAL (exp) < 0 && ! attr->negative_ok)
fatal ("Negative numeric value specified for `%s' attribute",
attr->name);
*************** check_attr_value (exp, attr)
*** 1123,1128 ****
--- 1123,1138 ----
XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
break;
+ case PLUS:
+ case MINUS:
+ case MULT:
+ case DIV:
+ case MOD:
+ if (attr && !attr->is_numeric)
+ fatal ("Invalid operation `%s' for non-numeric attribute value",
+ GET_RTX_NAME (GET_CODE (exp)));
+ /* FALLTHRU */
+
case IOR:
case AND:
XEXP (exp, 0) = check_attr_value (XEXP (exp, 0), attr);
*************** check_attr_value (exp, attr)
*** 1148,1159 ****
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
break;
case SYMBOL_REF:
! if (attr && attr->is_const)
! /* A constant SYMBOL_REF is valid as a constant attribute test and
! is expanded later by make_canonical into a COND. */
! return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
! /* Otherwise, fall through... */
default:
fatal ("Invalid operation `%s' for attribute value",
--- 1158,1184 ----
XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
break;
+ case ATTR:
+ {
+ struct attr_desc *attr2 = find_attr (XSTR (exp, 0), 0);
+ if (attr2 == NULL)
+ fatal ("Unknown attribute `%s' in ATTR", XSTR (exp, 0));
+ else if ((attr && attr->is_const) && ! attr2->is_const)
+ fatal ("Non-constant attribute `%s' referenced from `%s'",
+ XSTR (exp, 0), attr->name);
+ else if (attr
+ && (attr->is_numeric != attr2->is_numeric
+ || (! attr->negative_ok && attr2->negative_ok)))
+ fatal ("Numeric attribute mismatch calling `%s' from `%s'",
+ XSTR (exp, 0), attr->name);
+ }
+ break;
+
case SYMBOL_REF:
! /* A constant SYMBOL_REF is valid as a constant attribute test and
! is expanded later by make_canonical into a COND. In a non-constant
! attribute test, it is left be. */
! return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
default:
fatal ("Invalid operation `%s' for attribute value",
*************** expand_units ()
*** 2101,2107 ****
}
/* Record MAX (BLOCKAGE (*,*)). */
! unit->max_blockage = max_attr_value (max_blockage);
/* See if the upper and lower bounds of BLOCKAGE (E,*) are the
same. If so, the blockage function carries no additional
--- 2126,2135 ----
}
/* Record MAX (BLOCKAGE (*,*)). */
! {
! int unknown;
! unit->max_blockage = max_attr_value (max_blockage, &unknown);
! }
/* See if the upper and lower bounds of BLOCKAGE (E,*) are the
same. If so, the blockage function carries no additional
*************** simplify_knowing (exp, known_true)
*** 2186,2194 ****
{
if (GET_CODE (exp) != CONST_STRING)
{
! exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
! make_numeric_value (max_attr_value (exp)));
! exp = simplify_by_exploding (exp);
}
return exp;
}
--- 2214,2227 ----
{
if (GET_CODE (exp) != CONST_STRING)
{
! int unknown, max;
! max = max_attr_value (exp, &unknown);
! if (! unknown)
! {
! exp = attr_rtx (IF_THEN_ELSE, known_true, exp,
! make_numeric_value (max));
! exp = simplify_by_exploding (exp);
! }
}
return exp;
}
*************** static rtx
*** 2458,2464 ****
max_fn (exp)
rtx exp;
{
! return make_numeric_value (max_attr_value (exp));
}
static void
--- 2491,2498 ----
max_fn (exp)
rtx exp;
{
! int unknown;
! return make_numeric_value (max_attr_value (exp, &unknown));
}
static void
*************** write_length_unit_log ()
*** 2468,2483 ****
struct attr_value *av;
struct insn_ent *ie;
unsigned int length_unit_log, length_or;
if (length_attr == 0)
return;
! length_or = or_attr_value (length_attr->default_val->value);
! for (av = length_attr->first_value; av; av = av->next)
! for (ie = av->first_insn; ie; ie = ie->next)
! length_or |= or_attr_value (av->value);
! length_or = ~length_or;
! for (length_unit_log = 0; length_or & 1; length_or >>= 1)
! length_unit_log++;
printf ("int length_unit_log = %u;\n", length_unit_log);
}
--- 2502,2524 ----
struct attr_value *av;
struct insn_ent *ie;
unsigned int length_unit_log, length_or;
+ int unknown = 0;
if (length_attr == 0)
return;
! length_or = or_attr_value (length_attr->default_val->value, &unknown);
! for (av = length_attr->first_value; av; av = av->next)
! for (ie = av->first_insn; ie; ie = ie->next)
! length_or |= or_attr_value (av->value, &unknown);
!
! if (unknown)
! length_unit_log = 0;
! else
! {
! length_or = ~length_or;
! for (length_unit_log = 0; length_or & 1; length_or >>= 1)
! length_unit_log++;
! }
printf ("int length_unit_log = %u;\n", length_unit_log);
}
*************** find_and_mark_used_attributes (exp, term
*** 3703,3708 ****
--- 3744,3751 ----
*nterms += 1;
MEM_VOLATILE_P (exp) = 1;
}
+ return 1;
+
case CONST_STRING:
case CONST_INT:
return 1;
*************** gen_attr (exp)
*** 4106,4112 ****
fatal ("Duplicate definition for `%s' attribute", attr->name);
if (*XSTR (exp, 1) == '\0')
! attr->is_numeric = 1;
else
{
name_ptr = XSTR (exp, 1);
--- 4149,4155 ----
fatal ("Duplicate definition for `%s' attribute", attr->name);
if (*XSTR (exp, 1) == '\0')
! attr->is_numeric = 1;
else
{
name_ptr = XSTR (exp, 1);
*************** write_test_expr (exp, flags)
*** 4652,4731 ****
}
/* Given an attribute value, return the maximum CONST_STRING argument
! encountered. It is assumed that they are all numeric. */
static int
! max_attr_value (exp)
rtx exp;
{
! int current_max = 0;
! int n;
! int i;
!
! if (GET_CODE (exp) == CONST_STRING)
! return atoi (XSTR (exp, 0));
! else if (GET_CODE (exp) == COND)
{
for (i = 0; i < XVECLEN (exp, 0); i += 2)
{
! n = max_attr_value (XVECEXP (exp, 0, i + 1));
if (n > current_max)
current_max = n;
}
! n = max_attr_value (XEXP (exp, 1));
if (n > current_max)
current_max = n;
! }
! else if (GET_CODE (exp) == IF_THEN_ELSE)
! {
! current_max = max_attr_value (XEXP (exp, 1));
! n = max_attr_value (XEXP (exp, 2));
! if (n > current_max)
! current_max = n;
}
- else
- abort ();
-
return current_max;
}
/* Given an attribute value, return the result of ORing together all
! CONST_STRING arguments encountered. It is assumed that they are
! all numeric. */
static int
! or_attr_value (exp)
rtx exp;
{
! int current_or = 0;
int i;
! if (GET_CODE (exp) == CONST_STRING)
! return atoi (XSTR (exp, 0));
!
! else if (GET_CODE (exp) == COND)
{
for (i = 0; i < XVECLEN (exp, 0); i += 2)
! {
! current_or |= or_attr_value (XVECEXP (exp, 0, i + 1));
! }
! current_or |= or_attr_value (XEXP (exp, 1));
! }
! else if (GET_CODE (exp) == IF_THEN_ELSE)
! {
! current_or = or_attr_value (XEXP (exp, 1));
! current_or |= or_attr_value (XEXP (exp, 2));
}
- else
- abort ();
-
return current_or;
}
--- 4695,4777 ----
}
/* Given an attribute value, return the maximum CONST_STRING argument
! encountered. Set *UNKNOWNP and return INT_MAX if the value is unknown. */
static int
! max_attr_value (exp, unknownp)
rtx exp;
+ int *unknownp;
{
! int current_max;
! int i, n;
! switch (GET_CODE (exp))
{
+ case CONST_STRING:
+ current_max = atoi (XSTR (exp, 0));
+ break;
+
+ case COND:
+ current_max = max_attr_value (XEXP (exp, 1), unknownp);
for (i = 0; i < XVECLEN (exp, 0); i += 2)
{
! n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
if (n > current_max)
current_max = n;
}
+ break;
! case IF_THEN_ELSE:
! current_max = max_attr_value (XEXP (exp, 1), unknownp);
! n = max_attr_value (XEXP (exp, 2), unknownp);
if (n > current_max)
current_max = n;
! break;
! default:
! *unknownp = 1;
! current_max = INT_MAX;
! break;
}
return current_max;
}
/* Given an attribute value, return the result of ORing together all
! CONST_STRING arguments encountered. Set *UNKNOWNP and return -1
! if the numeric value is not known. */
static int
! or_attr_value (exp, unknownp)
rtx exp;
+ int *unknownp;
{
! int current_or;
int i;
! switch (GET_CODE (exp))
{
+ case CONST_STRING:
+ current_or = atoi (XSTR (exp, 0));
+ break;
+
+ case COND:
+ current_or = or_attr_value (XEXP (exp, 1), unknownp);
for (i = 0; i < XVECLEN (exp, 0); i += 2)
! current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
! break;
! case IF_THEN_ELSE:
! current_or = or_attr_value (XEXP (exp, 1), unknownp);
! current_or |= or_attr_value (XEXP (exp, 2), unknownp);
! break;
! default:
! *unknownp = 1;
! current_or = -1;
! break;
}
return current_or;
}
*************** write_attr_set (attr, indent, value, pre
*** 4928,4941 ****
rtx known_true;
int insn_code, insn_index;
{
! if (GET_CODE (value) == CONST_STRING)
! {
! write_indent (indent);
! printf ("%s ", prefix);
! write_attr_value (attr, value);
! printf ("%s\n", suffix);
! }
! else if (GET_CODE (value) == COND)
{
/* Assume the default value will be the default of the COND unless we
find an always true expression. */
--- 4974,4980 ----
rtx known_true;
int insn_code, insn_index;
{
! if (GET_CODE (value) == COND)
{
/* Assume the default value will be the default of the COND unless we
find an always true expression. */
*************** write_attr_set (attr, indent, value, pre
*** 5009,5015 ****
}
}
else
! abort ();
}
/* Write out the computation for one attribute value. */
--- 5048,5059 ----
}
}
else
! {
! write_indent (indent);
! printf ("%s ", prefix);
! write_attr_value (attr, value);
! printf ("%s\n", suffix);
! }
}
/* Write out the computation for one attribute value. */
*************** write_attr_value (attr, value)
*** 5244,5253 ****
struct attr_desc *attr;
rtx value;
{
! if (GET_CODE (value) != CONST_STRING)
! abort ();
! write_attr_valueq (attr, XSTR (value, 0));
}
static void
--- 5288,5340 ----
struct attr_desc *attr;
rtx value;
{
! int op;
! switch (GET_CODE (value))
! {
! case CONST_STRING:
! write_attr_valueq (attr, XSTR (value, 0));
! break;
!
! case SYMBOL_REF:
! fputs (XSTR (value, 0), stdout);
! break;
!
! case ATTR:
! {
! struct attr_desc *attr2 = find_attr (XSTR (value, 0), 0);
! printf ("get_attr_%s (%s)", attr2->name,
! (attr2->is_const ? "" : "insn"));
! }
! break;
!
! case PLUS:
! op = '+';
! goto do_operator;
! case MINUS:
! op = '-';
! goto do_operator;
! case MULT:
! op = '*';
! goto do_operator;
! case DIV:
! op = '/';
! goto do_operator;
! case MOD:
! op = '%';
! goto do_operator;
!
! do_operator:
! write_attr_value (attr, XEXP (value, 0));
! putchar (' ');
! putchar (op);
! putchar (' ');
! write_attr_value (attr, XEXP (value, 1));
! break;
!
! default:
! abort ();
! }
}
static void
Index: md.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/md.texi,v
retrieving revision 1.22
diff -c -p -d -r1.22 md.texi
*** md.texi 1998/12/16 20:57:22 1.22
--- md.texi 1999/02/22 02:39:12
*************** The integer @var{i} specifies the value
*** 3555,3563 ****
must be non-negative.
The value of a numeric attribute can be specified either with a
! @code{const_int} or as an integer represented as a string in
! @code{const_string}, @code{eq_attr} (see below), and @code{set_attr}
! (@pxref{Tagging Insns}) expressions.
@cindex @code{const_string} and attributes
@item (const_string @var{value})
--- 3555,3564 ----
must be non-negative.
The value of a numeric attribute can be specified either with a
! @code{const_int}, or as an integer represented as a string in
! @code{const_string}, @code{eq_attr} (see below), @code{attr},
! @code{symbol_ref}, simple arithmetic expressions, and @code{set_attr}
! overrides on specific instructions (@pxref{Tagging Insns}).
@cindex @code{const_string} and attributes
@item (const_string @var{value})
*************** The @code{very_unlikely} and @code{unlik
*** 3740,3745 ****
--- 3741,3752 ----
@code{attr_flag} is only used during delay slot scheduling and has no
meaning to other passes of the compiler.
+
+ @findex attr
+ @item (attr @var{name})
+ The value of another attribute is returned. This is most useful
+ for numeric attributes, as @code{eq_attr} and @code{attr_flag}
+ produce more efficient code for non-numeric attributes.
@end table
@node Tagging Insns