*** empty log message ***
From-SVN: r888
This commit is contained in:
parent
8241a41f2a
commit
7339c88dc5
460
gcc/genattrtab.c
460
gcc/genattrtab.c
@ -90,8 +90,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "obstack.h"
|
||||
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */
|
||||
|
||||
static struct obstack obstack;
|
||||
static struct obstack obstack, obstack1;
|
||||
struct obstack *rtl_obstack = &obstack;
|
||||
struct obstack *hash_obstack = &obstack1;
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
@ -256,6 +257,7 @@ static void check_defs ();
|
||||
static rtx convert_const_symbol_ref ();
|
||||
static rtx make_canonical ();
|
||||
static struct attr_value *get_attr_value ();
|
||||
static rtx copy_rtx_unchanging ();
|
||||
static void expand_delays ();
|
||||
static rtx operate_exp ();
|
||||
static void expand_units ();
|
||||
@ -348,7 +350,8 @@ attr_hash_add_rtx (hashcode, rtl)
|
||||
{
|
||||
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->u.rtl = rtl;
|
||||
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
|
||||
@ -364,7 +367,8 @@ attr_hash_add_string (hashcode, str)
|
||||
{
|
||||
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->u.str = str;
|
||||
h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
|
||||
@ -388,6 +392,7 @@ attr_rtx (va_alist)
|
||||
register rtx rt_val; /* RTX to return to caller... */
|
||||
int hashcode;
|
||||
register struct attr_hash *h;
|
||||
struct obstack *old_obstack = rtl_obstack;
|
||||
|
||||
va_start (p);
|
||||
code = va_arg (p, enum rtx_code);
|
||||
@ -409,6 +414,7 @@ attr_rtx (va_alist)
|
||||
|
||||
if (h == 0)
|
||||
{
|
||||
rtl_obstack = hash_obstack;
|
||||
rt_val = rtx_alloc (code);
|
||||
XEXP (rt_val, 0) = arg0;
|
||||
}
|
||||
@ -430,6 +436,7 @@ attr_rtx (va_alist)
|
||||
|
||||
if (h == 0)
|
||||
{
|
||||
rtl_obstack = hash_obstack;
|
||||
rt_val = rtx_alloc (code);
|
||||
XEXP (rt_val, 0) = arg0;
|
||||
XEXP (rt_val, 1) = arg1;
|
||||
@ -449,6 +456,7 @@ attr_rtx (va_alist)
|
||||
|
||||
if (h == 0)
|
||||
{
|
||||
rtl_obstack = hash_obstack;
|
||||
rt_val = rtx_alloc (code);
|
||||
XSTR (rt_val, 0) = arg0;
|
||||
}
|
||||
@ -470,6 +478,7 @@ attr_rtx (va_alist)
|
||||
|
||||
if (h == 0)
|
||||
{
|
||||
rtl_obstack = hash_obstack;
|
||||
rt_val = rtx_alloc (code);
|
||||
XSTR (rt_val, 0) = arg0;
|
||||
XSTR (rt_val, 1) = arg1;
|
||||
@ -512,6 +521,7 @@ attr_rtx (va_alist)
|
||||
return rt_val;
|
||||
}
|
||||
|
||||
rtl_obstack = old_obstack;
|
||||
va_end (p);
|
||||
attr_hash_add_rtx (hashcode, rt_val);
|
||||
return rt_val;
|
||||
@ -649,7 +659,7 @@ check_attr_test (exp, is_const)
|
||||
RTX_UNCHANGING_P (exp) = 1;
|
||||
return exp;
|
||||
}
|
||||
else
|
||||
else
|
||||
fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0));
|
||||
}
|
||||
|
||||
@ -1053,16 +1063,26 @@ make_canonical (attr, exp)
|
||||
|
||||
case COND:
|
||||
cond:
|
||||
/* First, check for degenerate COND. */
|
||||
if (XVECLEN (exp, 0) == 0)
|
||||
return make_canonical (attr, XEXP (exp, 1));
|
||||
{
|
||||
int allsame = 1;
|
||||
rtx defval;
|
||||
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
XVECEXP (exp, 0, i + 1)
|
||||
= make_canonical (attr, XVECEXP (exp, 0, i + 1));
|
||||
/* First, check for degenerate COND. */
|
||||
if (XVECLEN (exp, 0) == 0)
|
||||
return make_canonical (attr, XEXP (exp, 1));
|
||||
defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
|
||||
|
||||
XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
|
||||
break;
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
{
|
||||
XVECEXP (exp, 0, i + 1)
|
||||
= make_canonical (attr, XVECEXP (exp, 0, i + 1));
|
||||
if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
|
||||
allsame = 0;
|
||||
}
|
||||
if (allsame)
|
||||
return defval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return exp;
|
||||
@ -1261,22 +1281,46 @@ operate_exp (op, left, right)
|
||||
else if (GET_CODE (right) == IF_THEN_ELSE)
|
||||
{
|
||||
/* Apply recursively to all values within. */
|
||||
return attr_rtx (IF_THEN_ELSE, XEXP (right, 0),
|
||||
operate_exp (op, left, XEXP (right, 1)),
|
||||
operate_exp (op, left, XEXP (right, 2)));
|
||||
rtx newleft = operate_exp (op, left, XEXP (right, 1));
|
||||
rtx newright = 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)
|
||||
{
|
||||
int allsame = 1;
|
||||
rtx defval;
|
||||
|
||||
newexp = rtx_alloc (COND);
|
||||
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)
|
||||
{
|
||||
XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
|
||||
XVECEXP (newexp, 0, i + 1)
|
||||
= operate_exp (op, left, XVECEXP (right, 0, i + 1));
|
||||
if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
|
||||
defval))
|
||||
allsame = 0;
|
||||
}
|
||||
|
||||
XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@ -1287,23 +1331,46 @@ operate_exp (op, left, right)
|
||||
/* Otherwise, do recursion the other way. */
|
||||
else if (GET_CODE (left) == IF_THEN_ELSE)
|
||||
{
|
||||
return attr_rtx (IF_THEN_ELSE, XEXP (left, 0),
|
||||
operate_exp (op, XEXP (left, 1), right),
|
||||
operate_exp (op, XEXP (left, 2), right));
|
||||
rtx newleft = operate_exp (op, XEXP (left, 1), right);
|
||||
rtx newright = 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)
|
||||
{
|
||||
int allsame = 1;
|
||||
rtx defval;
|
||||
|
||||
newexp = rtx_alloc (COND);
|
||||
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)
|
||||
{
|
||||
XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
|
||||
XVECEXP (newexp, 0, i + 1)
|
||||
= operate_exp (op, XVECEXP (left, 0, i + 1), right);
|
||||
if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
|
||||
defval))
|
||||
allsame = 0;
|
||||
}
|
||||
|
||||
XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@ -1618,8 +1685,7 @@ max_fn (exp)
|
||||
|
||||
Also call ourselves on any COND operations that are values of this COND.
|
||||
|
||||
We only do the first replacement found directly and call ourselves
|
||||
recursively for subsequent replacements. */
|
||||
We do not modify EXP; rather, we make and return a new rtx. */
|
||||
|
||||
static rtx
|
||||
simplify_cond (exp, insn_code, insn_index)
|
||||
@ -1627,129 +1693,128 @@ simplify_cond (exp, insn_code, insn_index)
|
||||
int insn_code, insn_index;
|
||||
{
|
||||
int i, j;
|
||||
rtx newtest;
|
||||
rtx value;
|
||||
rtx newexp = exp;
|
||||
/* We store the desired contents here,
|
||||
then build a new expression if they don't match EXP. */
|
||||
rtx defval = XEXP (exp, 1);
|
||||
int len = XVECLEN (exp, 0);
|
||||
rtx *tests = (rtx *) alloca (len * sizeof (rtx));
|
||||
int allsame = 1;
|
||||
char *spacer, *first_spacer;
|
||||
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
/* This lets us free all storage allocated below, if appropriate. */
|
||||
first_spacer = (char *) obstack_next_free (rtl_obstack);
|
||||
|
||||
bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx));
|
||||
|
||||
/* See if default value needs simplification. */
|
||||
if (GET_CODE (defval) == COND)
|
||||
defval = simplify_cond (defval, insn_code, insn_index);
|
||||
|
||||
/* Simplify now, just to see what tests we can get rid of. */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
newtest = SIMPLIFY_TEST_EXP (XVECEXP (exp, 0, i), insn_code, insn_index);
|
||||
rtx newtest, newval;
|
||||
|
||||
/* Simplify this test. */
|
||||
newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
|
||||
|
||||
newval = tests[i + 1];
|
||||
/* See if this value may need simplification. */
|
||||
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)
|
||||
{
|
||||
/* 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);
|
||||
break;
|
||||
/* If test is true, make this value the default
|
||||
and discard this + any following tests. */
|
||||
len = i;
|
||||
defval = tests[i];
|
||||
}
|
||||
|
||||
else if (newtest == false_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);
|
||||
/* If test is false, discard it and its value. */
|
||||
for (j = i; j < len - 2; j++)
|
||||
tests[j] = tests[j + 2];
|
||||
|
||||
for (j = i; j < XVECLEN (newexp, 0); j++)
|
||||
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2);
|
||||
|
||||
XEXP (newexp, 1) = XEXP (exp, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (newtest != XVECEXP (exp, 0, i))
|
||||
{
|
||||
newexp = rtx_alloc (COND);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
/* See if this value may need simplification. */
|
||||
if (GET_CODE (XVECEXP (exp, 0, i + 1)) == COND)
|
||||
{
|
||||
value = simplify_cond (XVECEXP (exp, 0, i + 1),
|
||||
insn_code, insn_index);
|
||||
if (value != XVECEXP (exp, 0, i + 1))
|
||||
{
|
||||
newexp = rtx_alloc (COND);
|
||||
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 + 1) = value;
|
||||
break;
|
||||
}
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* If this is the last condition in a COND and our value is the same
|
||||
as the default value, our test isn't needed. */
|
||||
if (i == XVECLEN (exp, 0) - 2
|
||||
&& rtx_equal_p (XVECEXP (exp, 0, i + 1), XEXP (exp, 1)))
|
||||
{
|
||||
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);
|
||||
XEXP (newexp, 1) = XEXP (exp, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this value and the value for the next test are the same, merge the
|
||||
tests. */
|
||||
else if (i != XVECLEN (exp, 0) - 2
|
||||
&& rtx_equal_p (XVECEXP (exp, 0, i + 1),
|
||||
XVECEXP (exp, 0, i + 3)))
|
||||
{
|
||||
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);
|
||||
|
||||
XVECEXP (newexp, 0, j)
|
||||
= insert_right_side (IOR, XVECEXP (exp, 0, i),
|
||||
XVECEXP (exp, 0, i + 2),
|
||||
insn_code, insn_index);
|
||||
XVECEXP (newexp, 0, j + 1) = XVECEXP (exp, 0, i + 1);
|
||||
|
||||
for (j = i + 2; j < XVECLEN (newexp, 0); j++)
|
||||
XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2);
|
||||
|
||||
XEXP (newexp, 1) = XEXP (exp, 1);
|
||||
break;
|
||||
}
|
||||
else if (i == len - 2 && rtx_equal_p (newval, defval))
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* See if default value needs simplification. */
|
||||
if (GET_CODE (XEXP (exp, 1)) == COND)
|
||||
obstack_free (rtl_obstack, first_spacer);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
value = simplify_cond (XEXP (exp, 1), insn_code, insn_index);
|
||||
if (value != XEXP (exp, 1))
|
||||
{
|
||||
newexp = rtx_alloc (COND);
|
||||
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) = value;
|
||||
}
|
||||
defval = XEXP (exp, 1);
|
||||
if (GET_CODE (defval) == COND)
|
||||
return simplify_cond (defval, insn_code, insn_index);
|
||||
return defval;
|
||||
}
|
||||
|
||||
if (exp == newexp)
|
||||
return exp;
|
||||
else if (XVECLEN (newexp, 0) == 1)
|
||||
return XVECEXP (newexp, 0, 0);
|
||||
else
|
||||
return simplify_cond (newexp, insn_code, insn_index);
|
||||
{
|
||||
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
|
||||
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);
|
||||
bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx));
|
||||
XEXP (newexp, 1) = defval;
|
||||
return newexp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove an insn entry from an attribute value. */
|
||||
@ -1807,6 +1872,26 @@ insert_right_side (code, exp, term, insn_code, insn_index)
|
||||
{
|
||||
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)
|
||||
{
|
||||
exp = insert_right_side (code, exp, XEXP (term, 0),
|
||||
@ -1819,16 +1904,19 @@ insert_right_side (code, exp, term, insn_code, insn_index)
|
||||
|
||||
if (GET_CODE (exp) == code)
|
||||
{
|
||||
/* Make a copy of this expression and call recursively. */
|
||||
newexp = attr_rtx (code, XEXP (exp, 0),
|
||||
insert_right_side (code, XEXP (exp, 1),
|
||||
term, insn_code, insn_index));
|
||||
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. */
|
||||
newexp = attr_rtx (code, XEXP (exp, 0), new);
|
||||
else
|
||||
newexp = exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert the new term. */
|
||||
newexp = attr_rtx (code, exp, term);
|
||||
}
|
||||
}
|
||||
|
||||
return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
|
||||
}
|
||||
@ -1892,6 +1980,8 @@ make_alternative_compare (mask)
|
||||
computation. If a test condition involves an address, we leave the EQ_ATTR
|
||||
intact because addresses are only valid for the `length' attribute. */
|
||||
|
||||
/* ??? Kenner, document the meanings of the arguments!!! */
|
||||
|
||||
static rtx
|
||||
evaluate_eq_attr (exp, value, insn_code, insn_index)
|
||||
rtx exp;
|
||||
@ -1929,8 +2019,10 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
|
||||
|
||||
for (i = 0; i < XVECLEN (value, 0); i += 2)
|
||||
{
|
||||
right = insert_right_side (AND, andexp,
|
||||
XVECEXP (value, 0, i),
|
||||
rtx this = SIMPLIFY_TEST_EXP (XVECEXP (value, 0, i),
|
||||
insn_code, insn_index);
|
||||
|
||||
right = insert_right_side (AND, andexp, this,
|
||||
insn_code, insn_index);
|
||||
right = insert_right_side (AND, right,
|
||||
evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1),
|
||||
@ -1940,7 +2032,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
|
||||
insn_code, insn_index);
|
||||
|
||||
/* 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,
|
||||
insn_code, insn_index);
|
||||
}
|
||||
@ -1964,9 +2056,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
|
||||
if (address_used)
|
||||
{
|
||||
if (! RTX_UNCHANGING_P (exp))
|
||||
exp = copy_rtx (exp);
|
||||
|
||||
RTX_UNCHANGING_P (exp) = 1;
|
||||
return copy_rtx_unchanging (exp);
|
||||
return exp;
|
||||
}
|
||||
else
|
||||
@ -2194,6 +2284,21 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
struct insn_ent *ie;
|
||||
int i;
|
||||
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))
|
||||
{
|
||||
@ -2228,11 +2333,20 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
left = simplify_and_tree (left, &right, insn_code, insn_index);
|
||||
|
||||
if (left == false_rtx || right == false_rtx)
|
||||
return false_rtx;
|
||||
{
|
||||
obstack_free (rtl_obstack, spacer);
|
||||
return false_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)
|
||||
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
|
||||
in this tree. Optimize if so. */
|
||||
@ -2286,11 +2400,20 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
left = simplify_or_tree (left, &right, insn_code, insn_index);
|
||||
|
||||
if (right == true_rtx || left == true_rtx)
|
||||
return true_rtx;
|
||||
{
|
||||
obstack_free (rtl_obstack, spacer);
|
||||
return true_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)
|
||||
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.,
|
||||
convert (ior (and (x) (y))
|
||||
@ -2352,14 +2475,23 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
break;
|
||||
|
||||
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);
|
||||
if (GET_CODE (left) == NOT)
|
||||
return XEXP (left, 0);
|
||||
|
||||
if (left == false_rtx)
|
||||
return true_rtx;
|
||||
{
|
||||
obstack_free (rtl_obstack, spacer);
|
||||
return true_rtx;
|
||||
}
|
||||
else if (left == true_rtx)
|
||||
return false_rtx;
|
||||
{
|
||||
obstack_free (rtl_obstack, spacer);
|
||||
return false_rtx;
|
||||
}
|
||||
|
||||
/* Try to apply De`Morgan's laws. */
|
||||
else if (GET_CODE (left) == IOR)
|
||||
@ -2401,12 +2533,14 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
to process (i.e., we are canonicalizing something.). */
|
||||
if (insn_code != -2 && ! RTX_UNCHANGING_P (newexp))
|
||||
{
|
||||
newexp = copy_rtx (newexp);
|
||||
RTX_UNCHANGING_P (newexp) = 1;
|
||||
return copy_rtx_unchanging (newexp);
|
||||
}
|
||||
|
||||
return newexp;
|
||||
}
|
||||
|
||||
do_nothing ()
|
||||
{}
|
||||
|
||||
/* Optimize the attribute lists by seeing if we can determine conditional
|
||||
values from the known values of other attributes. This will save subroutine
|
||||
@ -3819,6 +3953,33 @@ xmalloc (size)
|
||||
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
|
||||
fatal (s, a1, a2)
|
||||
char *s;
|
||||
@ -3852,6 +4013,7 @@ main (argc, argv)
|
||||
rtx tem;
|
||||
|
||||
obstack_init (rtl_obstack);
|
||||
obstack_init (hash_obstack);
|
||||
|
||||
if (argc <= 1)
|
||||
fatal ("No input file name.");
|
||||
|
Loading…
Reference in New Issue
Block a user