Commit 81fd4c6e by Richard Stallman

*** empty log message ***

From-SVN: r910
parent 4be1e768
...@@ -90,9 +90,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -90,9 +90,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "obstack.h" #include "obstack.h"
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */ #include "insn-config.h" /* For REGISTER_CONSTRAINTS */
static struct obstack obstack, obstack1; static struct obstack obstack, obstack1, obstack2;
struct obstack *rtl_obstack = &obstack; struct obstack *rtl_obstack = &obstack;
struct obstack *hash_obstack = &obstack1; struct obstack *hash_obstack = &obstack1;
struct obstack *temp_obstack = &obstack2;
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free #define obstack_chunk_free free
...@@ -233,7 +234,7 @@ static rtx true_rtx, false_rtx; ...@@ -233,7 +234,7 @@ static rtx true_rtx, false_rtx;
/* Used to reduce calls to `strcmp' */ /* Used to reduce calls to `strcmp' */
static char *alternative_name = "alternative"; static char *alternative_name;
/* Simplify an expression. Only call the routine if there is something to /* Simplify an expression. Only call the routine if there is something to
simplify. */ simplify. */
...@@ -250,7 +251,7 @@ static rtx attr_rtx (); ...@@ -250,7 +251,7 @@ static rtx attr_rtx ();
static char *attr_printf (); static char *attr_printf ();
static char *attr_string (); static char *attr_string ();
static rtx check_attr_test (); static rtx check_attr_test ();
static void check_attr_value (); static rtx check_attr_value ();
static rtx convert_set_attr_alternative (); static rtx convert_set_attr_alternative ();
static rtx convert_set_attr (); static rtx convert_set_attr ();
static void check_defs (); static void check_defs ();
...@@ -258,6 +259,7 @@ static rtx convert_const_symbol_ref (); ...@@ -258,6 +259,7 @@ static rtx convert_const_symbol_ref ();
static rtx make_canonical (); static rtx make_canonical ();
static struct attr_value *get_attr_value (); static struct attr_value *get_attr_value ();
static rtx copy_rtx_unchanging (); static rtx copy_rtx_unchanging ();
static rtx copy_boolean ();
static void expand_delays (); static void expand_delays ();
static rtx operate_exp (); static rtx operate_exp ();
static void expand_units (); static void expand_units ();
...@@ -375,8 +377,13 @@ attr_hash_add_string (hashcode, str) ...@@ -375,8 +377,13 @@ attr_hash_add_string (hashcode, str)
attr_hash_table[hashcode % RTL_HASH_SIZE] = h; attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
} }
/* Generate an RTL expression, but allow sharing. Like gen_rtx, but the /* Generate an RTL expression, but avoid duplicates.
mode is not used: Set the RTX_INTEGRATED_P flag for these permanent objects.
In some cases we cannot uniquify; then we return an ordinary
impermanent rtx with RTX_INTEGRATED_P clear.
Args are like gen_rtx, but without the mode:
rtx attr_rtx (code, [element1, ..., elementn]) */ rtx attr_rtx (code, [element1, ..., elementn]) */
...@@ -405,6 +412,15 @@ attr_rtx (va_alist) ...@@ -405,6 +412,15 @@ attr_rtx (va_alist)
{ {
rtx arg0 = va_arg (p, rtx); rtx arg0 = va_arg (p, rtx);
/* A permanent object cannot point to impermanent ones. */
if (! RTX_INTEGRATED_P (arg0))
{
rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0;
va_end (p);
return rt_val;
}
hashcode = ((int) code + RTL_HASH (arg0)); hashcode = ((int) code + RTL_HASH (arg0));
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode if (h->hashcode == hashcode
...@@ -426,6 +442,16 @@ attr_rtx (va_alist) ...@@ -426,6 +442,16 @@ attr_rtx (va_alist)
rtx arg0 = va_arg (p, rtx); rtx arg0 = va_arg (p, rtx);
rtx arg1 = va_arg (p, rtx); rtx arg1 = va_arg (p, rtx);
/* A permanent object cannot point to impermanent ones. */
if (! RTX_INTEGRATED_P (arg0) || ! RTX_INTEGRATED_P (arg1))
{
rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0;
XEXP (rt_val, 1) = arg1;
va_end (p);
return rt_val;
}
hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1)); hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1));
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode if (h->hashcode == hashcode
...@@ -447,6 +473,9 @@ attr_rtx (va_alist) ...@@ -447,6 +473,9 @@ attr_rtx (va_alist)
{ {
char * arg0 = va_arg (p, char *); char * arg0 = va_arg (p, char *);
if (code == SYMBOL_REF)
arg0 = attr_string (arg0, strlen (arg0));
hashcode = ((int) code + RTL_HASH (arg0)); hashcode = ((int) code + RTL_HASH (arg0));
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode if (h->hashcode == hashcode
...@@ -465,8 +494,8 @@ attr_rtx (va_alist) ...@@ -465,8 +494,8 @@ attr_rtx (va_alist)
&& GET_RTX_FORMAT (code)[0] == 's' && GET_RTX_FORMAT (code)[0] == 's'
&& GET_RTX_FORMAT (code)[1] == 's') && GET_RTX_FORMAT (code)[1] == 's')
{ {
char * arg0 = va_arg (p, char *); char *arg0 = va_arg (p, char *);
char * arg1 = va_arg (p, char *); char *arg1 = va_arg (p, char *);
hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1)); hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1));
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
...@@ -484,8 +513,18 @@ attr_rtx (va_alist) ...@@ -484,8 +513,18 @@ attr_rtx (va_alist)
XSTR (rt_val, 1) = arg1; XSTR (rt_val, 1) = arg1;
} }
} }
else if (code == CONST_INT)
{
int arg0 = va_arg (p, int);
if (arg0 == 0)
return false_rtx;
if (arg0 == 1)
return true_rtx;
goto nohash;
}
else else
{ {
nohash:
rt_val = rtx_alloc (code); /* Allocate the storage space. */ rt_val = rtx_alloc (code); /* Allocate the storage space. */
fmt = GET_RTX_FORMAT (code); /* Find the right format... */ fmt = GET_RTX_FORMAT (code); /* Find the right format... */
...@@ -524,6 +563,7 @@ attr_rtx (va_alist) ...@@ -524,6 +563,7 @@ attr_rtx (va_alist)
rtl_obstack = old_obstack; rtl_obstack = old_obstack;
va_end (p); va_end (p);
attr_hash_add_rtx (hashcode, rt_val); attr_hash_add_rtx (hashcode, rt_val);
RTX_INTEGRATED_P (rt_val) = 1;
return rt_val; return rt_val;
found: found:
...@@ -577,6 +617,21 @@ attr_printf (len, fmt, arg1, arg2, arg3) ...@@ -577,6 +617,21 @@ attr_printf (len, fmt, arg1, arg2, arg3)
} }
#endif /* not HAVE_VPRINTF */ #endif /* not HAVE_VPRINTF */
rtx
attr_eq (name, value)
char *name, *value;
{
return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
attr_string (value, strlen (value)));
}
char *
attr_numeral (n)
int n;
{
return XSTR (make_numeric_value (n), 0);
}
/* Return a permanent (possibly shared) copy of a string STR (not assumed /* Return a permanent (possibly shared) copy of a string STR (not assumed
to be null terminated) with LEN bytes. */ to be null terminated) with LEN bytes. */
...@@ -599,7 +654,7 @@ attr_string (str, len) ...@@ -599,7 +654,7 @@ attr_string (str, len)
/* Search the table for the string. */ /* Search the table for the string. */
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
if (h->hashcode == -hashcode if (h->hashcode == -hashcode && h->u.str[0] == str[0]
&& !strncmp (h->u.str, str, len)) && !strncmp (h->u.str, str, len))
return h->u.str; /* <-- return if found. */ return h->u.str; /* <-- return if found. */
...@@ -612,6 +667,88 @@ attr_string (str, len) ...@@ -612,6 +667,88 @@ attr_string (str, len)
return new_str; /* Return the new string. */ return new_str; /* Return the new string. */
} }
/* Check two rtx's for equality of contents,
taking advantage of the fact that if both are hashed
then they can't be equal unless they are the same object. */
int
attr_equal_p (x, y)
rtx x, y;
{
return (x == y || (! (RTX_INTEGRATED_P (x) && RTX_INTEGRATED_P (y))
&& rtx_equal_p (x, y)));
}
/* Copy an attribute value expression,
descending to all depths, but not copying any
permanent hashed subexpressions. */
rtx
attr_copy_rtx (orig)
register rtx orig;
{
register rtx copy;
register int i, j;
register RTX_CODE code;
register char *format_ptr;
/* No need to copy a permanent object. */
if (RTX_INTEGRATED_P (orig))
return orig;
code = GET_CODE (orig);
switch (code)
{
case REG:
case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
return orig;
}
copy = rtx_alloc (code);
PUT_MODE (copy, GET_MODE (orig));
copy->in_struct = orig->in_struct;
copy->volatil = orig->volatil;
copy->unchanging = orig->unchanging;
copy->integrated = orig->integrated;
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
{
switch (*format_ptr++)
{
case 'e':
XEXP (copy, i) = XEXP (orig, i);
if (XEXP (orig, i) != NULL)
XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i));
break;
case 'E':
case 'V':
XVEC (copy, i) = XVEC (orig, i);
if (XVEC (orig, i) != NULL)
{
XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
for (j = 0; j < XVECLEN (copy, i); j++)
XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j));
}
break;
default:
XINT (copy, i) = XINT (orig, i);
break;
}
}
return copy;
}
/* Given a test expression for an attribute, ensure it is validly formed. /* Given a test expression for an attribute, ensure it is validly formed.
IS_CONST indicates whether the expression is constant for each compiler IS_CONST indicates whether the expression is constant for each compiler
run (a constant expression may not test any particular insn). run (a constant expression may not test any particular insn).
...@@ -642,9 +779,8 @@ check_attr_test (exp, is_const) ...@@ -642,9 +779,8 @@ check_attr_test (exp, is_const)
/* Handle negation test. */ /* Handle negation test. */
if (XSTR (exp, 1)[0] == '!') if (XSTR (exp, 1)[0] == '!')
return check_attr_test (attr_rtx (NOT, return check_attr_test (attr_rtx (NOT,
attr_rtx (EQ_ATTR, attr_eq (XSTR (exp, 0),
XSTR (exp, 0), &XSTR (exp, 1)[1])),
&XSTR(exp, 1)[1])),
is_const); is_const);
else if (n_comma_elts (XSTR (exp, 1)) == 1) else if (n_comma_elts (XSTR (exp, 1)) == 1)
...@@ -667,7 +803,9 @@ check_attr_test (exp, is_const) ...@@ -667,7 +803,9 @@ check_attr_test (exp, is_const)
fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR", fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR",
XEXP (exp, 0)); XEXP (exp, 0));
XSTR (exp, 0) = attr->name; /* Copy this just to make it permanent,
so expressions using it can be permanent too. */
exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
if (attr->is_numeric) if (attr->is_numeric)
{ {
...@@ -695,7 +833,7 @@ check_attr_test (exp, is_const) ...@@ -695,7 +833,7 @@ check_attr_test (exp, is_const)
name_ptr = XSTR (exp, 1); name_ptr = XSTR (exp, 1);
while ((p = next_comma_elt (&name_ptr)) != NULL) while ((p = next_comma_elt (&name_ptr)) != NULL)
{ {
newexp = attr_rtx (EQ_ATTR, XSTR (exp, 0), p); newexp = attr_eq (XSTR (exp, 0), p);
orexp = insert_right_side (IOR, orexp, newexp, -2); orexp = insert_right_side (IOR, orexp, newexp, -2);
} }
...@@ -724,10 +862,18 @@ check_attr_test (exp, is_const) ...@@ -724,10 +862,18 @@ check_attr_test (exp, is_const)
if (is_const) if (is_const)
fatal ("RTL operator \"%s\" not valid in constant attribute test", fatal ("RTL operator \"%s\" not valid in constant attribute test",
GET_RTX_NAME (MATCH_OPERAND)); GET_RTX_NAME (MATCH_OPERAND));
/* These cases can't be simplified. */
RTX_UNCHANGING_P (exp) = 1;
break;
case LE: case LT: case GT: case GE: case LE: case LT: case GT: case GE:
case LEU: case LTU: case GTU: case GEU: case LEU: case LTU: case GTU: case GEU:
case NE: case EQ: case NE: case EQ:
if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
&& GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
exp = attr_rtx (GET_CODE (exp),
attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
/* These cases can't be simplified. */ /* These cases can't be simplified. */
RTX_UNCHANGING_P (exp) = 1; RTX_UNCHANGING_P (exp) = 1;
break; break;
...@@ -737,7 +883,7 @@ check_attr_test (exp, is_const) ...@@ -737,7 +883,7 @@ check_attr_test (exp, is_const)
{ {
/* These cases are valid for constant attributes, but can't be /* These cases are valid for constant attributes, but can't be
simplified. */ simplified. */
exp = copy_rtx (exp); exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
RTX_UNCHANGING_P (exp) = 1; RTX_UNCHANGING_P (exp) = 1;
break; break;
} }
...@@ -751,9 +897,11 @@ check_attr_test (exp, is_const) ...@@ -751,9 +897,11 @@ check_attr_test (exp, is_const)
/* Given an expression, ensure that it is validly formed and that all named /* Given an expression, ensure that it is validly formed and that all named
attribute values are valid for the given attribute. Issue a fatal error attribute values are valid for the given attribute. Issue a fatal error
if not. If no attribute is specified, assume a numeric attribute. */ if not. If no attribute is specified, assume a numeric attribute.
static void Return a perhaps modified replacement expression for the value. */
static rtx
check_attr_value (exp, attr) check_attr_value (exp, attr)
rtx exp; rtx exp;
struct attr_desc *attr; struct attr_desc *attr;
...@@ -797,14 +945,14 @@ check_attr_value (exp, attr) ...@@ -797,14 +945,14 @@ check_attr_value (exp, attr)
fatal ("Unknown value `%s' for `%s' attribute", fatal ("Unknown value `%s' for `%s' attribute",
XSTR (exp, 0), attr ? attr->name : "internal"); XSTR (exp, 0), attr ? attr->name : "internal");
return; break;
case IF_THEN_ELSE: case IF_THEN_ELSE:
XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
attr ? attr->is_const : 0); attr ? attr->is_const : 0);
check_attr_value (XEXP (exp, 1), attr); XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
check_attr_value (XEXP (exp, 2), attr); XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
return; break;
case COND: case COND:
if (XVECLEN (exp, 0) % 2 != 0) if (XVECLEN (exp, 0) % 2 != 0)
...@@ -814,23 +962,26 @@ check_attr_value (exp, attr) ...@@ -814,23 +962,26 @@ check_attr_value (exp, attr)
{ {
XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i), XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
attr ? attr->is_const : 0); attr ? attr->is_const : 0);
check_attr_value (XVECEXP (exp, 0, i + 1), attr); XVECEXP (exp, 0, i + 1)
= check_attr_value (XVECEXP (exp, 0, i + 1), attr);
} }
check_attr_value (XEXP (exp, 1), attr); XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
return; break;
case SYMBOL_REF: case SYMBOL_REF:
if (attr && attr->is_const) if (attr && attr->is_const)
/* A constant SYMBOL_REF is valid as a constant attribute test and /* A constant SYMBOL_REF is valid as a constant attribute test and
is expanded later by make_canonical into a COND. */ is expanded later by make_canonical into a COND. */
return; return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
/* Otherwise, fall through... */ /* Otherwise, fall through... */
default: default:
fatal ("Illegal operation `%s' for attribute value", fatal ("Illegal operation `%s' for attribute value",
GET_RTX_NAME (GET_CODE (exp))); GET_RTX_NAME (GET_CODE (exp)));
} }
return exp;
} }
/* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET. /* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
...@@ -858,12 +1009,15 @@ convert_set_attr_alternative (exp, num_alt, insn_code, insn_index) ...@@ -858,12 +1009,15 @@ convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
for (i = 0; i < num_alt - 1; i++) for (i = 0; i < num_alt - 1; i++)
{ {
char *p; char *p;
p = attr_printf (3, "%d", i); p = attr_numeral (i);
XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);
#if 0
/* Sharing this EQ_ATTR rtl causes trouble. */ /* Sharing this EQ_ATTR rtl causes trouble. */
XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR); XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR);
XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name; XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name;
XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p; XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p;
#endif
XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i); XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
} }
...@@ -955,7 +1109,7 @@ check_defs () ...@@ -955,7 +1109,7 @@ check_defs ()
XSTR (XEXP (value, 0), 0), id->insn_index); XSTR (XEXP (value, 0), 0), id->insn_index);
XVECEXP (id->def, id->vec_idx, i) = value; XVECEXP (id->def, id->vec_idx, i) = value;
check_attr_value (XEXP (value, 1), attr); XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
} }
} }
} }
...@@ -987,14 +1141,10 @@ convert_const_symbol_ref (exp, attr) ...@@ -987,14 +1141,10 @@ convert_const_symbol_ref (exp, attr)
for (i = num_alt - 2; av = av->next, i >= 0; i--) for (i = num_alt - 2; av = av->next, i >= 0; i--)
{ {
char * p; char *p, *string;
rtx value; rtx value;
XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ); string = p = (char *) xmalloc (2
XEXP (XVECEXP (condexp, 0, 2 * i), 0) = exp;
XEXP (XVECEXP (condexp, 0, 2 * i), 1) = value = rtx_alloc (SYMBOL_REF);
RTX_UNCHANGING_P (value) = 1;
XSTR (value, 0) = p = (char *) xmalloc (2
+ strlen (attr->name) + strlen (attr->name)
+ strlen (XSTR (av->value, 0))); + strlen (XSTR (av->value, 0)));
strcpy (p, attr->name); strcpy (p, attr->name);
...@@ -1004,6 +1154,11 @@ convert_const_symbol_ref (exp, attr) ...@@ -1004,6 +1154,11 @@ convert_const_symbol_ref (exp, attr)
if (*p >= 'a' && *p <= 'z') if (*p >= 'a' && *p <= 'z')
*p -= 'a' - 'A'; *p -= 'a' - 'A';
value = attr_rtx (SYMBOL_REF, string);
RTX_UNCHANGING_P (value) = 1;
XVECEXP (condexp, 0, 2 * i) = attr_eq (exp, value);
XVECEXP (condexp, 0, 2 * i + 1) = av->value; XVECEXP (condexp, 0, 2 * i + 1) = av->value;
} }
...@@ -1044,7 +1199,7 @@ make_canonical (attr, exp) ...@@ -1044,7 +1199,7 @@ make_canonical (attr, exp)
break; break;
exp = convert_const_symbol_ref (exp, attr); exp = convert_const_symbol_ref (exp, attr);
RTX_UNCHANGING_P (exp) = 1; RTX_UNCHANGING_P (exp) = 1;
check_attr_value (exp, attr); exp = check_attr_value (exp, attr);
/* Goto COND case since this is now a COND. Note that while the /* Goto COND case since this is now a COND. Note that while the
new expression is rescanned, all symbol_ref notes are mared as new expression is rescanned, all symbol_ref notes are mared as
unchanging. */ unchanging. */
...@@ -1074,6 +1229,7 @@ make_canonical (attr, exp) ...@@ -1074,6 +1229,7 @@ make_canonical (attr, exp)
for (i = 0; i < XVECLEN (exp, 0); i += 2) for (i = 0; i < XVECLEN (exp, 0); i += 2)
{ {
XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
XVECEXP (exp, 0, i + 1) XVECEXP (exp, 0, i + 1)
= make_canonical (attr, XVECEXP (exp, 0, i + 1)); = make_canonical (attr, XVECEXP (exp, 0, i + 1));
if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval)) if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
...@@ -1088,6 +1244,16 @@ make_canonical (attr, exp) ...@@ -1088,6 +1244,16 @@ make_canonical (attr, exp)
return exp; return exp;
} }
static rtx
copy_boolean (exp)
rtx exp;
{
if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
copy_boolean (XEXP (exp, 1)));
return exp;
}
/* Given a value and an attribute description, return a `struct attr_value *' /* Given a value and an attribute description, return a `struct attr_value *'
that represents that value. This is either an existing structure, if the that represents that value. This is either an existing structure, if the
value has been previously encountered, or a newly-created structure. value has been previously encountered, or a newly-created structure.
...@@ -1437,7 +1603,7 @@ expand_units () ...@@ -1437,7 +1603,7 @@ expand_units ()
and busy cost. Then make an attribute for use in the conflict and busy cost. Then make an attribute for use in the conflict
function. */ function. */
op->condexp = check_attr_test (op->condexp, 0); op->condexp = check_attr_test (op->condexp, 0);
check_attr_value (op->busyexp, 0); op->busyexp = check_attr_value (op->busyexp, 0);
str = attr_printf (strlen (unit->name) + 11, "*%s_case_%d", str = attr_printf (strlen (unit->name) + 11, "*%s_case_%d",
unit->name, op->num); unit->name, op->num);
make_internal_attr (str, make_canonical (0, op->busyexp)); make_internal_attr (str, make_canonical (0, op->busyexp));
...@@ -1704,7 +1870,7 @@ simplify_cond (exp, insn_code, insn_index) ...@@ -1704,7 +1870,7 @@ simplify_cond (exp, insn_code, insn_index)
char *spacer, *first_spacer; char *spacer, *first_spacer;
/* This lets us free all storage allocated below, if appropriate. */ /* This lets us free all storage allocated below, if appropriate. */
first_spacer = (char *) obstack_next_free (rtl_obstack); first_spacer = (char *) obstack_finish (rtl_obstack);
bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx)); bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx));
...@@ -1712,16 +1878,15 @@ simplify_cond (exp, insn_code, insn_index) ...@@ -1712,16 +1878,15 @@ simplify_cond (exp, insn_code, insn_index)
if (GET_CODE (defval) == COND) if (GET_CODE (defval) == COND)
new_defval = simplify_cond (defval, insn_code, insn_index); new_defval = simplify_cond (defval, insn_code, insn_index);
/* Simplify now, just to see what tests we can get rid of. */ /* Simplify the subexpressions, and see what tests we can get rid of. */
/* Work from back to front, so if all values match the default, for (i = 0; i < len; i += 2)
we get rid of all of them. */
for (i = len - 2; i >= 0; i -= 2)
{ {
rtx newtest, newval; rtx newtest, newval;
/* Simplify this test. */ /* Simplify this test. */
newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index); newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
tests[i] = newtest;
newval = tests[i + 1]; newval = tests[i + 1];
/* See if this value may need simplification. */ /* See if this value may need simplification. */
...@@ -1743,78 +1908,64 @@ simplify_cond (exp, insn_code, insn_index) ...@@ -1743,78 +1908,64 @@ simplify_cond (exp, insn_code, insn_index)
/* If test is false, discard it and its value. */ /* If test is false, discard it and its value. */
for (j = i; j < len - 2; j++) for (j = i; j < len - 2; j++)
tests[j] = tests[j + 2]; tests[j] = tests[j + 2];
len -= 2; len -= 2;
} }
/* If this is the last condition in a COND and our value is the same else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
as the default value, our test isn't needed. */
else if (i == len - 2 && rtx_equal_p (newval, new_defval))
len -= 2;
}
obstack_free (rtl_obstack, first_spacer);
if (len == 0)
{ {
if (GET_CODE (defval) == COND) /* If this value and the value for the prev test are the same,
return simplify_cond (defval, insn_code, insn_index); merge the tests. */
return defval;
}
else
{
rtx newexp;
/* Simplify again, for real this time. */
if (GET_CODE (defval) == COND)
defval = simplify_cond (defval, insn_code, insn_index);
for (i = len - 2; i >= 0; i -= 2) tests[i - 2]
{ = insert_right_side (IOR, tests[i - 2], newtest,
/* See if this value may need simplification. */
if (GET_CODE (tests[i + 1]) == COND)
tests[i + 1] = simplify_cond (tests[i + 1], insn_code, insn_index);
/* Simplify this test. */
tests[i] = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
/* If this value and the value for the next test are the same, merge the
tests. */
if (i != len - 2
&& rtx_equal_p (tests[i + 1], tests[i + 3]))
{
/* Merge following test into this one. */
tests[i]
= insert_right_side (IOR, tests[i], tests[i + 2],
insn_code, insn_index); insn_code, insn_index);
/* Delete the following test/value. */ /* Delete this test/value. */
for (j = i + 2; j < len - 2; j++) for (j = i; j < len - 2; j++)
tests[j] = tests[j + 2]; tests[j] = tests[j + 2];
len -= 2; len -= 2;
} }
else
tests[i + 1] = newval;
} }
/* If the last test in a COND has the same value
as the default value, that test isn't needed. */
while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
len -= 2;
/* See if we changed anything. */ /* See if we changed anything. */
if (len != XVECLEN (exp, 0) || defval != XEXP (exp, 1)) if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
allsame = 0; allsame = 0;
else else
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if (! rtx_equal_p (tests[i], XVECEXP (exp, 0, i))) if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
{ {
allsame = 0; allsame = 0;
break; break;
} }
if (allsame) if (len == 0)
{
obstack_free (rtl_obstack, first_spacer);
if (GET_CODE (defval) == COND)
return simplify_cond (defval, insn_code, insn_index);
return defval;
}
else if (allsame)
{
obstack_free (rtl_obstack, first_spacer);
return exp; return exp;
}
newexp = rtx_alloc (COND); else
{
rtx newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (len); XVEC (newexp, 0) = rtvec_alloc (len);
bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx)); bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx));
XEXP (newexp, 1) = defval; XEXP (newexp, 1) = new_defval;
return newexp; return newexp;
} }
} }
...@@ -1891,7 +2042,7 @@ insert_right_side (code, exp, term, insn_code, insn_index) ...@@ -1891,7 +2042,7 @@ insert_right_side (code, exp, term, insn_code, insn_index)
return true_rtx; return true_rtx;
if (code == IOR && exp == false_rtx) if (code == IOR && exp == false_rtx)
return term; return term;
if (rtx_equal_p (exp, term)) if (attr_equal_p (exp, term))
return exp; return exp;
if (GET_CODE (term) == code) if (GET_CODE (term) == code)
...@@ -1968,9 +2119,7 @@ make_alternative_compare (mask) ...@@ -1968,9 +2119,7 @@ make_alternative_compare (mask)
for (i = 0; (mask & (1 << i)) == 0; i++) for (i = 0; (mask & (1 << i)) == 0; i++)
; ;
alternative = attr_printf (3, "%d", i); newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
newexp = attr_rtx (EQ_ATTR, alternative_name, alternative);
RTX_UNCHANGING_P (newexp) = 1; RTX_UNCHANGING_P (newexp) = 1;
return newexp; return newexp;
...@@ -2174,23 +2323,23 @@ simplify_and_tree (exp, pterm, insn_code, insn_index) ...@@ -2174,23 +2323,23 @@ simplify_and_tree (exp, pterm, insn_code, insn_index)
else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT) else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
{ {
if (rtx_equal_p (XEXP (exp, 0), XEXP (*pterm, 0))) if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
return true_rtx; return true_rtx;
} }
else if (GET_CODE (exp) == NOT) else if (GET_CODE (exp) == NOT)
{ {
if (rtx_equal_p (XEXP (exp, 0), *pterm)) if (attr_equal_p (XEXP (exp, 0), *pterm))
return false_rtx; return false_rtx;
} }
else if (GET_CODE (*pterm) == NOT) else if (GET_CODE (*pterm) == NOT)
{ {
if (rtx_equal_p (XEXP (*pterm, 0), exp)) if (attr_equal_p (XEXP (*pterm, 0), exp))
return false_rtx; return false_rtx;
} }
else if (rtx_equal_p (exp, *pterm)) else if (attr_equal_p (exp, *pterm))
return true_rtx; return true_rtx;
return exp; return exp;
...@@ -2244,13 +2393,13 @@ simplify_or_tree (exp, pterm, insn_code, insn_index) ...@@ -2244,13 +2393,13 @@ simplify_or_tree (exp, pterm, insn_code, insn_index)
} }
} }
if (rtx_equal_p (exp, *pterm)) if (attr_equal_p (exp, *pterm))
return false_rtx; return false_rtx;
else if (GET_CODE (exp) == NOT && rtx_equal_p (XEXP (exp, 0), *pterm)) else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
return true_rtx; return true_rtx;
else if (GET_CODE (*pterm) == NOT && rtx_equal_p (XEXP (*pterm, 0), exp)) else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
return true_rtx; return true_rtx;
else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
...@@ -2286,7 +2435,7 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2286,7 +2435,7 @@ simplify_test_exp (exp, insn_code, insn_index)
struct insn_ent *ie; struct insn_ent *ie;
int i; int i;
rtx newexp = exp; rtx newexp = exp;
char *spacer = (char *) obstack_next_free (rtl_obstack); char *spacer = (char *) obstack_finish (rtl_obstack);
static rtx loser = 0; static rtx loser = 0;
static int count = 0; static int count = 0;
...@@ -2425,7 +2574,7 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2425,7 +2574,7 @@ simplify_test_exp (exp, insn_code, insn_index)
*/ */
else if (GET_CODE (left) == AND && GET_CODE (right) == AND else if (GET_CODE (left) == AND && GET_CODE (right) == AND
&& rtx_equal_p (XEXP (left, 0), XEXP (right, 0))) && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
{ {
newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1)); newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
...@@ -2565,19 +2714,26 @@ optimize_attrs () ...@@ -2565,19 +2714,26 @@ optimize_attrs ()
for (av = attr->first_value; av; av = av->next) for (av = attr->first_value; av; av = av->next)
for (ie = av->first_insn; ie; ie = nextie) for (ie = av->first_insn; ie; ie = nextie)
{ {
struct obstack *old = rtl_obstack;
char *spacer = (char *) obstack_finish (temp_obstack);
nextie = ie->next; nextie = ie->next;
if (GET_CODE (av->value) != COND) if (GET_CODE (av->value) != COND)
continue; continue;
rtl_obstack = temp_obstack;
newexp = simplify_cond (av->value, ie->insn_code, newexp = simplify_cond (av->value, ie->insn_code,
ie->insn_index); ie->insn_index);
rtl_obstack = old;
if (newexp != av->value) if (newexp != av->value)
{ {
newexp = attr_copy_rtx (newexp);
remove_insn_ent (av, ie); remove_insn_ent (av, ie);
insert_insn_ent (get_attr_value (newexp, attr, insert_insn_ent (get_attr_value (newexp, attr,
ie->insn_code), ie); ie->insn_code), ie);
something_changed = 1; something_changed = 1;
} }
obstack_free (temp_obstack, spacer);
} }
} }
} }
...@@ -2629,7 +2785,7 @@ gen_attr (exp) ...@@ -2629,7 +2785,7 @@ gen_attr (exp)
fatal ("`length' attribute must take numeric values"); fatal ("`length' attribute must take numeric values");
/* Set up the default value. */ /* Set up the default value. */
check_attr_value (XEXP (exp, 2), attr); XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2); attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
} }
...@@ -3826,7 +3982,7 @@ find_attr (name, create) ...@@ -3826,7 +3982,7 @@ find_attr (name, create)
/* Otherwise, do it the slow way. */ /* Otherwise, do it the slow way. */
for (attr = attrs; attr; attr = attr->next) for (attr = attrs; attr; attr = attr->next)
if (! strcmp (name, attr->name)) if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
return attr; return attr;
if (! create) if (! create)
...@@ -3962,6 +4118,9 @@ copy_rtx_unchanging (orig) ...@@ -3962,6 +4118,9 @@ copy_rtx_unchanging (orig)
register rtx copy; register rtx copy;
register RTX_CODE code; register RTX_CODE code;
if (RTX_UNCHANGING_P (orig))
return orig;
code = GET_CODE (orig); code = GET_CODE (orig);
switch (code) switch (code)
...@@ -4016,6 +4175,7 @@ main (argc, argv) ...@@ -4016,6 +4175,7 @@ main (argc, argv)
obstack_init (rtl_obstack); obstack_init (rtl_obstack);
obstack_init (hash_obstack); obstack_init (hash_obstack);
obstack_init (temp_obstack);
if (argc <= 1) if (argc <= 1)
fatal ("No input file name."); fatal ("No input file name.");
...@@ -4030,9 +4190,14 @@ main (argc, argv) ...@@ -4030,9 +4190,14 @@ main (argc, argv)
init_rtl (); init_rtl ();
/* Set up true and false rtx's */ /* Set up true and false rtx's */
true_rtx = attr_rtx (CONST_INT, 1); true_rtx = rtx_alloc (CONST_INT);
false_rtx = attr_rtx (CONST_INT, 0); XINT (true_rtx, 0) = 1;
false_rtx = rtx_alloc (CONST_INT);
XINT (false_rtx, 0) = 0;
RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1; RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1;
RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1;
alternative_name = attr_string ("alternative", strlen ("alternative"));
printf ("/* Generated automatically by the program `genattrtab'\n\ printf ("/* Generated automatically by the program `genattrtab'\n\
from the machine description file `md'. */\n\n"); from the machine description file `md'. */\n\n");
...@@ -4116,7 +4281,8 @@ from the machine description file `md'. */\n\n"); ...@@ -4116,7 +4281,8 @@ from the machine description file `md'. */\n\n");
check_defs (); check_defs ();
for (attr = attrs; attr; attr = attr->next) for (attr = attrs; attr; attr = attr->next)
{ {
check_attr_value (attr->default_val->value, attr); attr->default_val->value
= check_attr_value (attr->default_val->value, attr);
fill_attr (attr); fill_attr (attr);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment