Commit 7339c88d by Richard Stallman

*** empty log message ***

From-SVN: r888
parent 8241a41f
...@@ -90,8 +90,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -90,8 +90,9 @@ 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; static struct obstack obstack, obstack1;
struct obstack *rtl_obstack = &obstack; struct obstack *rtl_obstack = &obstack;
struct obstack *hash_obstack = &obstack1;
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free #define obstack_chunk_free free
...@@ -256,6 +257,7 @@ static void check_defs (); ...@@ -256,6 +257,7 @@ static void check_defs ();
static rtx convert_const_symbol_ref (); 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 void expand_delays (); static void expand_delays ();
static rtx operate_exp (); static rtx operate_exp ();
static void expand_units (); static void expand_units ();
...@@ -348,7 +350,8 @@ attr_hash_add_rtx (hashcode, rtl) ...@@ -348,7 +350,8 @@ attr_hash_add_rtx (hashcode, rtl)
{ {
register struct attr_hash *h; register struct attr_hash *h;
h = (struct attr_hash *) xmalloc (sizeof (struct attr_hash)); h = (struct attr_hash *) obstack_alloc (hash_obstack,
sizeof (struct attr_hash));
h->hashcode = hashcode; h->hashcode = hashcode;
h->u.rtl = rtl; h->u.rtl = rtl;
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE]; h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
...@@ -364,7 +367,8 @@ attr_hash_add_string (hashcode, str) ...@@ -364,7 +367,8 @@ attr_hash_add_string (hashcode, str)
{ {
register struct attr_hash *h; register struct attr_hash *h;
h = (struct attr_hash *) xmalloc (sizeof (struct attr_hash)); h = (struct attr_hash *) obstack_alloc (hash_obstack,
sizeof (struct attr_hash));
h->hashcode = -hashcode; h->hashcode = -hashcode;
h->u.str = str; h->u.str = str;
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE]; h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
...@@ -388,6 +392,7 @@ attr_rtx (va_alist) ...@@ -388,6 +392,7 @@ attr_rtx (va_alist)
register rtx rt_val; /* RTX to return to caller... */ register rtx rt_val; /* RTX to return to caller... */
int hashcode; int hashcode;
register struct attr_hash *h; register struct attr_hash *h;
struct obstack *old_obstack = rtl_obstack;
va_start (p); va_start (p);
code = va_arg (p, enum rtx_code); code = va_arg (p, enum rtx_code);
...@@ -409,6 +414,7 @@ attr_rtx (va_alist) ...@@ -409,6 +414,7 @@ attr_rtx (va_alist)
if (h == 0) if (h == 0)
{ {
rtl_obstack = hash_obstack;
rt_val = rtx_alloc (code); rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0; XEXP (rt_val, 0) = arg0;
} }
...@@ -430,6 +436,7 @@ attr_rtx (va_alist) ...@@ -430,6 +436,7 @@ attr_rtx (va_alist)
if (h == 0) if (h == 0)
{ {
rtl_obstack = hash_obstack;
rt_val = rtx_alloc (code); rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0; XEXP (rt_val, 0) = arg0;
XEXP (rt_val, 1) = arg1; XEXP (rt_val, 1) = arg1;
...@@ -449,6 +456,7 @@ attr_rtx (va_alist) ...@@ -449,6 +456,7 @@ attr_rtx (va_alist)
if (h == 0) if (h == 0)
{ {
rtl_obstack = hash_obstack;
rt_val = rtx_alloc (code); rt_val = rtx_alloc (code);
XSTR (rt_val, 0) = arg0; XSTR (rt_val, 0) = arg0;
} }
...@@ -470,6 +478,7 @@ attr_rtx (va_alist) ...@@ -470,6 +478,7 @@ attr_rtx (va_alist)
if (h == 0) if (h == 0)
{ {
rtl_obstack = hash_obstack;
rt_val = rtx_alloc (code); rt_val = rtx_alloc (code);
XSTR (rt_val, 0) = arg0; XSTR (rt_val, 0) = arg0;
XSTR (rt_val, 1) = arg1; XSTR (rt_val, 1) = arg1;
...@@ -512,6 +521,7 @@ attr_rtx (va_alist) ...@@ -512,6 +521,7 @@ attr_rtx (va_alist)
return rt_val; return rt_val;
} }
rtl_obstack = old_obstack;
va_end (p); va_end (p);
attr_hash_add_rtx (hashcode, rt_val); attr_hash_add_rtx (hashcode, rt_val);
return rt_val; return rt_val;
...@@ -1053,17 +1063,27 @@ make_canonical (attr, exp) ...@@ -1053,17 +1063,27 @@ make_canonical (attr, exp)
case COND: case COND:
cond: cond:
{
int allsame = 1;
rtx defval;
/* First, check for degenerate COND. */ /* First, check for degenerate COND. */
if (XVECLEN (exp, 0) == 0) if (XVECLEN (exp, 0) == 0)
return make_canonical (attr, XEXP (exp, 1)); return make_canonical (attr, XEXP (exp, 1));
defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
for (i = 0; i < XVECLEN (exp, 0); i += 2) for (i = 0; i < XVECLEN (exp, 0); i += 2)
{
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))
XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1)); allsame = 0;
}
if (allsame)
return defval;
break; break;
} }
}
return exp; return exp;
} }
...@@ -1261,22 +1281,46 @@ operate_exp (op, left, right) ...@@ -1261,22 +1281,46 @@ operate_exp (op, left, right)
else if (GET_CODE (right) == IF_THEN_ELSE) else if (GET_CODE (right) == IF_THEN_ELSE)
{ {
/* Apply recursively to all values within. */ /* Apply recursively to all values within. */
return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), rtx newleft = operate_exp (op, left, XEXP (right, 1));
operate_exp (op, left, XEXP (right, 1)), rtx newright = operate_exp (op, left, XEXP (right, 2));
operate_exp (op, left, XEXP (right, 2))); if (rtx_equal_p (newleft, newright))
return newleft;
return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);
} }
else if (GET_CODE (right) == COND) else if (GET_CODE (right) == COND)
{ {
int allsame = 1;
rtx defval;
newexp = rtx_alloc (COND); newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0)); XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
for (i = 0; i < XVECLEN (right, 0); i += 2) for (i = 0; i < XVECLEN (right, 0); i += 2)
{ {
XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i); XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
XVECEXP (newexp, 0, i + 1) XVECEXP (newexp, 0, i + 1)
= operate_exp (op, left, XVECEXP (right, 0, i + 1)); = operate_exp (op, left, XVECEXP (right, 0, i + 1));
if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
defval))
allsame = 0;
}
/* If the resulting cond is trivial (all alternatives
give the same value), optimize it away. */
if (allsame)
{
obstack_free (rtl_obstack, newexp);
return operate_exp (op, left, XEXP (right, 1));
} }
XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); /* If the result is the same as the RIGHT operand,
just use that. */
if (rtx_equal_p (newexp, right))
{
obstack_free (rtl_obstack, newexp);
return right;
}
return newexp; return newexp;
} }
...@@ -1287,23 +1331,46 @@ operate_exp (op, left, right) ...@@ -1287,23 +1331,46 @@ operate_exp (op, left, right)
/* Otherwise, do recursion the other way. */ /* Otherwise, do recursion the other way. */
else if (GET_CODE (left) == IF_THEN_ELSE) else if (GET_CODE (left) == IF_THEN_ELSE)
{ {
return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), rtx newleft = operate_exp (op, XEXP (left, 1), right);
operate_exp (op, XEXP (left, 1), right), rtx newright = operate_exp (op, XEXP (left, 2), right);
operate_exp (op, XEXP (left, 2), right)); if (rtx_equal_p (newleft, newright))
return newleft;
return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);
} }
else if (GET_CODE (left) == COND) else if (GET_CODE (left) == COND)
{ {
int allsame = 1;
rtx defval;
newexp = rtx_alloc (COND); newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0)); XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
for (i = 0; i < XVECLEN (left, 0); i += 2) for (i = 0; i < XVECLEN (left, 0); i += 2)
{ {
XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i); XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
XVECEXP (newexp, 0, i + 1) XVECEXP (newexp, 0, i + 1)
= operate_exp (op, XVECEXP (left, 0, i + 1), right); = operate_exp (op, XVECEXP (left, 0, i + 1), right);
if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
defval))
allsame = 0;
}
/* If the cond is trivial (all alternatives give the same value),
optimize it away. */
if (allsame)
{
obstack_free (rtl_obstack, newexp);
return operate_exp (op, XEXP (left, 1), right);
} }
XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right); /* If the result is the same as the LEFT operand,
just use that. */
if (rtx_equal_p (newexp, left))
{
obstack_free (rtl_obstack, newexp);
return left;
}
return newexp; return newexp;
} }
...@@ -1618,8 +1685,7 @@ max_fn (exp) ...@@ -1618,8 +1685,7 @@ max_fn (exp)
Also call ourselves on any COND operations that are values of this COND. Also call ourselves on any COND operations that are values of this COND.
We only do the first replacement found directly and call ourselves We do not modify EXP; rather, we make and return a new rtx. */
recursively for subsequent replacements. */
static rtx static rtx
simplify_cond (exp, insn_code, insn_index) simplify_cond (exp, insn_code, insn_index)
...@@ -1627,129 +1693,128 @@ simplify_cond (exp, insn_code, insn_index) ...@@ -1627,129 +1693,128 @@ simplify_cond (exp, insn_code, insn_index)
int insn_code, insn_index; int insn_code, insn_index;
{ {
int i, j; int i, j;
rtx newtest; /* We store the desired contents here,
rtx value; then build a new expression if they don't match EXP. */
rtx newexp = exp; rtx defval = XEXP (exp, 1);
int len = XVECLEN (exp, 0);
for (i = 0; i < XVECLEN (exp, 0); i += 2) rtx *tests = (rtx *) alloca (len * sizeof (rtx));
{ int allsame = 1;
newtest = SIMPLIFY_TEST_EXP (XVECEXP (exp, 0, i), insn_code, insn_index); char *spacer, *first_spacer;
if (newtest == true_rtx)
{
/* Make a new COND with any previous conditions and the value for
this pair as the default value. */
newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (i);
for (j = 0; j < i; j++)
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
XEXP (newexp, 1) = XVECEXP (exp, 0, i + 1); /* This lets us free all storage allocated below, if appropriate. */
break; first_spacer = (char *) obstack_next_free (rtl_obstack);
}
else if (newtest == false_rtx) bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx));
{
/* Build a new COND without this test. */
newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2);
for (j = 0; j < i; j++)
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
for (j = i; j < XVECLEN (newexp, 0); j++) /* See if default value needs simplification. */
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); if (GET_CODE (defval) == COND)
defval = simplify_cond (defval, insn_code, insn_index);
XEXP (newexp, 1) = XEXP (exp, 1); /* Simplify now, just to see what tests we can get rid of. */
break;
}
else if (newtest != XVECEXP (exp, 0, i)) /* Work from back to front, so if all values match the default,
we get rid of all of them. */
for (i = len - 2; i >= 0; i -= 2)
{ {
newexp = rtx_alloc (COND); rtx newtest, newval;
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
for (j = 0; j < XVECLEN (exp, 0); j++)
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
XEXP (newexp, 1) = XEXP (exp, 1);
XVECEXP (newexp, 0, i) = newtest; /* Simplify this test. */
break; newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
}
newval = tests[i + 1];
/* See if this value may need simplification. */ /* See if this value may need simplification. */
if (GET_CODE (XVECEXP (exp, 0, i + 1)) == COND) if (GET_CODE (newval) == COND)
newval = simplify_cond (newval, insn_code, insn_index);
/* Look for ways to delete or combine this test. */
if (newtest == true_rtx)
{ {
value = simplify_cond (XVECEXP (exp, 0, i + 1), /* If test is true, make this value the default
insn_code, insn_index); and discard this + any following tests. */
if (value != XVECEXP (exp, 0, i + 1)) len = i;
defval = tests[i];
}
else if (newtest == false_rtx)
{ {
newexp = rtx_alloc (COND); /* If test is false, discard it and its value. */
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); for (j = i; j < len - 2; j++)
for (j = 0; j < XVECLEN (exp, 0); j++) tests[j] = tests[j + 2];
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
XEXP (newexp, 1) = XEXP (exp, 1);
XVECEXP (newexp, 0, i + 1) = value; len -= 2;
break;
}
} }
/* If this is the last condition in a COND and our value is the same /* If this is the last condition in a COND and our value is the same
as the default value, our test isn't needed. */ as the default value, our test isn't needed. */
if (i == XVECLEN (exp, 0) - 2 else if (i == len - 2 && rtx_equal_p (newval, defval))
&& rtx_equal_p (XVECEXP (exp, 0, i + 1), XEXP (exp, 1))) len -= 2;
}
obstack_free (rtl_obstack, first_spacer);
if (len == 0)
{ {
newexp = rtx_alloc (COND); defval = XEXP (exp, 1);
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2); if (GET_CODE (defval) == COND)
for (j = 0; j < i; j++) return simplify_cond (defval, insn_code, insn_index);
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); return defval;
XEXP (newexp, 1) = XEXP (exp, 1);
break;
} }
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)
{
/* 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 /* If this value and the value for the next test are the same, merge the
tests. */ tests. */
else if (i != XVECLEN (exp, 0) - 2 if (i != len - 2
&& rtx_equal_p (XVECEXP (exp, 0, i + 1), && rtx_equal_p (tests[i + 1], tests[i + 3]))
XVECEXP (exp, 0, i + 3)))
{ {
newexp = rtx_alloc (COND); /* Merge following test into this one. */
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2); tests[i]
for (j = 0; j < i; j++) = insert_right_side (IOR, tests[i], tests[i + 2],
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
XVECEXP (newexp, 0, j)
= insert_right_side (IOR, XVECEXP (exp, 0, i),
XVECEXP (exp, 0, i + 2),
insn_code, insn_index); insn_code, insn_index);
XVECEXP (newexp, 0, j + 1) = XVECEXP (exp, 0, i + 1);
for (j = i + 2; j < XVECLEN (newexp, 0); j++) /* Delete the following test/value. */
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); for (j = i + 2; j < len - 2; j++)
tests[j] = tests[j + 2];
XEXP (newexp, 1) = XEXP (exp, 1); len -= 2;
break;
} }
} }
/* See if default value needs simplification. */ /* See if we changed anything. */
if (GET_CODE (XEXP (exp, 1)) == COND) if (len != XVECLEN (exp, 0) || defval != XEXP (exp, 1))
{ allsame = 0;
value = simplify_cond (XEXP (exp, 1), insn_code, insn_index); else
if (value != XEXP (exp, 1)) for (i = 0; i < len; i++)
if (! rtx_equal_p (tests[i], XVECEXP (exp, 0, i)))
{ {
newexp = rtx_alloc (COND); allsame = 0;
XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); break;
for (j = 0; j < XVECLEN (exp, 0); j++)
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j);
XEXP (newexp, 1) = value;
}
} }
if (exp == newexp) if (allsame)
return exp; return exp;
else if (XVECLEN (newexp, 0) == 1)
return XVECEXP (newexp, 0, 0); newexp = rtx_alloc (COND);
else
return simplify_cond (newexp, insn_code, insn_index); XVEC (newexp, 0) = rtvec_alloc (len);
bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx));
XEXP (newexp, 1) = defval;
return newexp;
}
} }
/* Remove an insn entry from an attribute value. */ /* Remove an insn entry from an attribute value. */
...@@ -1807,6 +1872,26 @@ insert_right_side (code, exp, term, insn_code, insn_index) ...@@ -1807,6 +1872,26 @@ insert_right_side (code, exp, term, insn_code, insn_index)
{ {
rtx newexp; rtx newexp;
/* Avoid consing in some special cases. */
if (code == AND && term == true_rtx)
return exp;
if (code == AND && term == false_rtx)
return false_rtx;
if (code == AND && exp == true_rtx)
return term;
if (code == AND && exp == false_rtx)
return false_rtx;
if (code == IOR && term == true_rtx)
return true_rtx;
if (code == IOR && term == false_rtx)
return exp;
if (code == IOR && exp == true_rtx)
return true_rtx;
if (code == IOR && exp == false_rtx)
return term;
if (rtx_equal_p (exp, term))
return exp;
if (GET_CODE (term) == code) if (GET_CODE (term) == code)
{ {
exp = insert_right_side (code, exp, XEXP (term, 0), exp = insert_right_side (code, exp, XEXP (term, 0),
...@@ -1819,10 +1904,13 @@ insert_right_side (code, exp, term, insn_code, insn_index) ...@@ -1819,10 +1904,13 @@ insert_right_side (code, exp, term, insn_code, insn_index)
if (GET_CODE (exp) == code) if (GET_CODE (exp) == code)
{ {
rtx new = insert_right_side (code, XEXP (exp, 1),
term, insn_code, insn_index);
if (new != XEXP (exp, 1))
/* Make a copy of this expression and call recursively. */ /* Make a copy of this expression and call recursively. */
newexp = attr_rtx (code, XEXP (exp, 0), newexp = attr_rtx (code, XEXP (exp, 0), new);
insert_right_side (code, XEXP (exp, 1), else
term, insn_code, insn_index)); newexp = exp;
} }
else else
{ {
...@@ -1892,6 +1980,8 @@ make_alternative_compare (mask) ...@@ -1892,6 +1980,8 @@ make_alternative_compare (mask)
computation. If a test condition involves an address, we leave the EQ_ATTR computation. If a test condition involves an address, we leave the EQ_ATTR
intact because addresses are only valid for the `length' attribute. */ intact because addresses are only valid for the `length' attribute. */
/* ??? Kenner, document the meanings of the arguments!!! */
static rtx static rtx
evaluate_eq_attr (exp, value, insn_code, insn_index) evaluate_eq_attr (exp, value, insn_code, insn_index)
rtx exp; rtx exp;
...@@ -1929,8 +2019,10 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) ...@@ -1929,8 +2019,10 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
for (i = 0; i < XVECLEN (value, 0); i += 2) for (i = 0; i < XVECLEN (value, 0); i += 2)
{ {
right = insert_right_side (AND, andexp, rtx this = SIMPLIFY_TEST_EXP (XVECEXP (value, 0, i),
XVECEXP (value, 0, i), insn_code, insn_index);
right = insert_right_side (AND, andexp, this,
insn_code, insn_index); insn_code, insn_index);
right = insert_right_side (AND, right, right = insert_right_side (AND, right,
evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1), evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1),
...@@ -1940,7 +2032,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) ...@@ -1940,7 +2032,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
insn_code, insn_index); insn_code, insn_index);
/* Add this condition into the AND expression. */ /* Add this condition into the AND expression. */
newexp = attr_rtx (NOT, XVECEXP (value, 0, i)); newexp = attr_rtx (NOT, this);
andexp = insert_right_side (AND, andexp, newexp, andexp = insert_right_side (AND, andexp, newexp,
insn_code, insn_index); insn_code, insn_index);
} }
...@@ -1964,9 +2056,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) ...@@ -1964,9 +2056,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
if (address_used) if (address_used)
{ {
if (! RTX_UNCHANGING_P (exp)) if (! RTX_UNCHANGING_P (exp))
exp = copy_rtx (exp); return copy_rtx_unchanging (exp);
RTX_UNCHANGING_P (exp) = 1;
return exp; return exp;
} }
else else
...@@ -2194,6 +2284,21 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2194,6 +2284,21 @@ 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);
static rtx loser = 0;
static int count = 0;
static stopcount = 0;
if (exp == loser)
do_nothing ();
count++;
if (count == stopcount)
do_nothing ();
/* Don't re-simplify something we already simplified. */
if (RTX_UNCHANGING_P (exp))
return exp;
switch (GET_CODE (exp)) switch (GET_CODE (exp))
{ {
...@@ -2228,11 +2333,20 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2228,11 +2333,20 @@ simplify_test_exp (exp, insn_code, insn_index)
left = simplify_and_tree (left, &right, insn_code, insn_index); left = simplify_and_tree (left, &right, insn_code, insn_index);
if (left == false_rtx || right == false_rtx) if (left == false_rtx || right == false_rtx)
{
obstack_free (rtl_obstack, spacer);
return false_rtx; return false_rtx;
}
else if (left == true_rtx) else if (left == true_rtx)
return right; {
obstack_free (rtl_obstack, spacer);
return SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
}
else if (right == true_rtx) else if (right == true_rtx)
return left; {
obstack_free (rtl_obstack, spacer);
return SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
}
/* See if all or all but one of the insn's alternatives are specified /* See if all or all but one of the insn's alternatives are specified
in this tree. Optimize if so. */ in this tree. Optimize if so. */
...@@ -2286,11 +2400,20 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2286,11 +2400,20 @@ simplify_test_exp (exp, insn_code, insn_index)
left = simplify_or_tree (left, &right, insn_code, insn_index); left = simplify_or_tree (left, &right, insn_code, insn_index);
if (right == true_rtx || left == true_rtx) if (right == true_rtx || left == true_rtx)
{
obstack_free (rtl_obstack, spacer);
return true_rtx; return true_rtx;
}
else if (left == false_rtx) else if (left == false_rtx)
return right; {
obstack_free (rtl_obstack, spacer);
return SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
}
else if (right == false_rtx) else if (right == false_rtx)
return left; {
obstack_free (rtl_obstack, spacer);
return SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
}
/* Test for simple cases where the distributive law is useful. I.e., /* Test for simple cases where the distributive law is useful. I.e.,
convert (ior (and (x) (y)) convert (ior (and (x) (y))
...@@ -2352,14 +2475,23 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2352,14 +2475,23 @@ simplify_test_exp (exp, insn_code, insn_index)
break; break;
case NOT: case NOT:
if (GET_CODE (XEXP (exp, 0)) == NOT)
return SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
insn_code, insn_index);
left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
if (GET_CODE (left) == NOT) if (GET_CODE (left) == NOT)
return XEXP (left, 0); return XEXP (left, 0);
if (left == false_rtx) if (left == false_rtx)
{
obstack_free (rtl_obstack, spacer);
return true_rtx; return true_rtx;
}
else if (left == true_rtx) else if (left == true_rtx)
{
obstack_free (rtl_obstack, spacer);
return false_rtx; return false_rtx;
}
/* Try to apply De`Morgan's laws. */ /* Try to apply De`Morgan's laws. */
else if (GET_CODE (left) == IOR) else if (GET_CODE (left) == IOR)
...@@ -2401,13 +2533,15 @@ simplify_test_exp (exp, insn_code, insn_index) ...@@ -2401,13 +2533,15 @@ simplify_test_exp (exp, insn_code, insn_index)
to process (i.e., we are canonicalizing something.). */ to process (i.e., we are canonicalizing something.). */
if (insn_code != -2 && ! RTX_UNCHANGING_P (newexp)) if (insn_code != -2 && ! RTX_UNCHANGING_P (newexp))
{ {
newexp = copy_rtx (newexp); return copy_rtx_unchanging (newexp);
RTX_UNCHANGING_P (newexp) = 1;
} }
return newexp; return newexp;
} }
do_nothing ()
{}
/* Optimize the attribute lists by seeing if we can determine conditional /* Optimize the attribute lists by seeing if we can determine conditional
values from the known values of other attributes. This will save subroutine values from the known values of other attributes. This will save subroutine
calls during the compilation. */ calls during the compilation. */
...@@ -3819,6 +3953,33 @@ xmalloc (size) ...@@ -3819,6 +3953,33 @@ xmalloc (size)
return val; return val;
} }
static rtx
copy_rtx_unchanging (orig)
register rtx orig;
{
register rtx copy;
register RTX_CODE code;
code = GET_CODE (orig);
switch (code)
{
case CONST_INT:
case CONST_DOUBLE:
case SYMBOL_REF:
case CODE_LABEL:
return orig;
}
copy = rtx_alloc (code);
PUT_MODE (copy, GET_MODE (orig));
RTX_UNCHANGING_P (copy) = 1;
bcopy (&XEXP (orig, 0), &XEXP (copy, 0),
GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx));
return copy;
}
static void static void
fatal (s, a1, a2) fatal (s, a1, a2)
char *s; char *s;
...@@ -3852,6 +4013,7 @@ main (argc, argv) ...@@ -3852,6 +4013,7 @@ main (argc, argv)
rtx tem; rtx tem;
obstack_init (rtl_obstack); obstack_init (rtl_obstack);
obstack_init (hash_obstack);
if (argc <= 1) if (argc <= 1)
fatal ("No input file name."); fatal ("No input file name.");
......
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