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. */
...@@ -611,6 +666,88 @@ attr_string (str, len) ...@@ -611,6 +666,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
...@@ -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,16 +1141,12 @@ convert_const_symbol_ref (exp, attr) ...@@ -987,16 +1141,12 @@ 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; + strlen (attr->name)
XEXP (XVECEXP (condexp, 0, 2 * i), 1) = value = rtx_alloc (SYMBOL_REF); + strlen (XSTR (av->value, 0)));
RTX_UNCHANGING_P (value) = 1;
XSTR (value, 0) = p = (char *) xmalloc (2
+ strlen (attr->name)
+ strlen (XSTR (av->value, 0)));
strcpy (p, attr->name); strcpy (p, attr->name);
strcat (p, "_"); strcat (p, "_");
strcat (p, XSTR (av->value, 0)); strcat (p, XSTR (av->value, 0));
...@@ -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))
...@@ -1087,6 +1243,16 @@ make_canonical (attr, exp) ...@@ -1087,6 +1243,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
...@@ -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;
}
else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
{
/* If this value and the value for the prev test are the same,
merge the tests. */
tests[i - 2]
= insert_right_side (IOR, tests[i - 2], newtest,
insn_code, insn_index);
/* Delete this test/value. */
for (j = i; j < len - 2; j++)
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
as the default value, our test isn't needed. */ tests[i + 1] = newval;
else if (i == len - 2 && rtx_equal_p (newval, new_defval))
len -= 2;
} }
obstack_free (rtl_obstack, first_spacer); /* 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. */
if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
allsame = 0;
else
for (i = 0; i < len; i++)
if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
{
allsame = 0;
break;
}
if (len == 0) if (len == 0)
{ {
obstack_free (rtl_obstack, first_spacer);
if (GET_CODE (defval) == COND) if (GET_CODE (defval) == COND)
return simplify_cond (defval, insn_code, insn_index); return simplify_cond (defval, insn_code, insn_index);
return defval; return defval;
} }
else if (allsame)
{
obstack_free (rtl_obstack, first_spacer);
return exp;
}
else else
{ {
rtx newexp; rtx newexp = rtx_alloc (COND);
/* 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)
{
/* 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);
/* Delete the following test/value. */
for (j = i + 2; j < len - 2; j++)
tests[j] = tests[j + 2];
len -= 2;
}
}
/* See if we changed anything. */
if (len != XVECLEN (exp, 0) || defval != XEXP (exp, 1))
allsame = 0;
else
for (i = 0; i < len; i++)
if (! rtx_equal_p (tests[i], XVECEXP (exp, 0, i)))
{
allsame = 0;
break;
}
if (allsame)
return exp;
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