summaryrefslogtreecommitdiffstats
path: root/gcc/genattrtab.c
diff options
context:
space:
mode:
authorrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-05-05 03:06:39 +0000
committerrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-05-05 03:06:39 +0000
commitfa737ee85fa03a38a11741b03f7061ee2f23682a (patch)
treec55358c9062c68bef71a83b0bb7319c867a63423 /gcc/genattrtab.c
parent98e6062f4dad87478666d0e1a6bc3f2e1c8b3106 (diff)
downloadppe42-gcc-fa737ee85fa03a38a11741b03f7061ee2f23682a.tar.gz
ppe42-gcc-fa737ee85fa03a38a11741b03f7061ee2f23682a.zip
*** empty log message ***
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@895 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/genattrtab.c')
-rw-r--r--gcc/genattrtab.c494
1 files changed, 180 insertions, 314 deletions
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index b4e8c77c4a1..24d2d446316 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -90,10 +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, obstack1, obstack2;
+static struct obstack obstack, obstack1;
struct obstack *rtl_obstack = &obstack;
struct obstack *hash_obstack = &obstack1;
-struct obstack *accum_obstack = &obstack2;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -276,8 +275,8 @@ static rtx insert_right_side ();
static rtx make_alternative_compare ();
static int compute_alternative_mask ();
static rtx evaluate_eq_attr ();
-/* static rtx simplify_and_tree ();
-static rtx simplify_or_tree (); */
+static rtx simplify_and_tree ();
+static rtx simplify_or_tree ();
static rtx simplify_test_exp ();
static void optimize_attrs ();
static void gen_attr ();
@@ -2066,288 +2065,6 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
return newexp;
}
-/* These are used by simplify_boolean to accumulate and sort terms. */
-
-struct term
-{
- rtx exp;
- int hash;
- int ignore;
- struct term *next;
-};
-
-struct term *termlist;
-
-void
-extract_terms (code, exp, pnterms, insn_code, insn_index)
- enum rtx_code code;
- rtx exp;
- int *pnterms;
- int insn_code, insn_index;
-{
- if (GET_CODE (exp) == code)
- {
- extract_terms (code, XEXP (exp, 0), pnterms, insn_code, insn_index);
- extract_terms (code, XEXP (exp, 1), pnterms, insn_code, insn_index);
- }
- else
- {
- struct term *save = termlist;
- exp = SIMPLIFY_TEST_EXP (exp, insn_code, insn_index);
- termlist = save;
-
- if (GET_CODE (exp) == code)
- {
- extract_terms (code, XEXP (exp, 0), pnterms, insn_code, insn_index);
- extract_terms (code, XEXP (exp, 1), pnterms, insn_code, insn_index);
- }
- else
- {
- struct term t;
- t.exp = exp;
- t.hash = hash_term (exp);
- t.ignore = 0;
- t.next = termlist;
- termlist = (struct term *) obstack_copy (accum_obstack,
- &t, sizeof t);
-
- (*pnterms)++;
- }
- }
-}
-
-/* Compare two terms for sorting.
- This particular sort function treats any term and its negation as "equal"
- so that they sort together. */
-
-int
-compare_terms (pt1, pt2)
- struct term *pt1, *pt2;
-{
- return pt1->hash - pt2->hash;
-}
-
-int
-hash_term (term)
- rtx term;
-{
- while (GET_CODE (term) == NOT)
- term = XEXP (term, 0);
-
- if (RTX_UNCHANGING_P (term))
- return (int) term;
-
- switch (GET_CODE (term))
- {
- case AND:
- return (hash_term (XEXP (term, 0))
- + (hash_term (XEXP (term, 1)) << 3)
- + (int) AND);
-
- case IOR:
- return (hash_term (XEXP (term, 0))
- + (hash_term (XEXP (term, 1)) << 4)
- + (int) IOR);
-
- default:
- return (int) term;
- }
-}
-
-/* Simplify a boolean expression made from applying CODE (which is AND or IOR)
- to the two expressions EXP1 and EXP2.
-
- EXP3 is another expression we can assume is true (if CODE is AND)
- or assume is false (if CODE is IOR).
-
- STABLE is either true or false.
- It is the truth value which, when input to CODE, makes itself the output.
- UNSTABLE is the other truth value: the one which is CODE of no operands. */
-
-rtx
-simplify_boolean (code, exp1, exp2, exp3, stable, unstable,
- insn_code, insn_index)
- enum rtx_code code;
- rtx exp1, exp2, exp3;
- rtx stable, unstable;
- int insn_code, insn_index;
-{
- struct term *vector;
- int nterms = 0;
- int nignores = 0;
- int i, j;
- char *spacer = (char *) obstack_finish (accum_obstack);
- rtx combined;
- rtx common_term;
- enum rtx_code other_code = (code == AND ? IOR : AND);
- static struct term dummy = {0, 0, 0, 0};
-
- termlist = 0;
-
- nterms = 1; /* Count one dummy element. */
- extract_terms (code, exp1, &nterms, insn_code, insn_index);
- if (exp2)
- extract_terms (code, exp2, &nterms, insn_code, insn_index);
-
- if (exp3)
- extract_terms (code, exp3, &nignores, insn_code, insn_index);
- nterms += nignores;
-
- vector = (struct term *) alloca (nterms * sizeof (struct term));
-
- /* Copy the terms from the list into the vector.
- Set the ignore flag in those which came from EXP3.
- That way, we won't include them in the final result. */
-
- vector[0] = dummy;
- for (i = 1; i < nterms; i++)
- {
- vector[i] = *termlist;
- if (i < nignores)
- vector[i].ignore = 1;
- termlist = termlist->next;
- }
-
- /* Free what we used in the obstack. */
- obstack_free (accum_obstack, spacer);
-
- qsort (vector, nterms, sizeof (struct term), compare_terms);
-
- if (insn_code >= 0)
- {
- i = (compute_alternative_mask (exp1, code)
- & compute_alternative_mask (exp2, code));
- if (i & ~insn_alternatives[insn_code])
- fatal ("invalid alternative specified for pattern number %d",
- insn_index);
-
- /* If all alternatives are excluded for AND (included for IOR),
- this is false (true). */
- i ^= insn_alternatives[insn_code];
- if (i == 0)
- {
- return stable;
- }
- else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
- {
- /* If just one included for AND (excluded for IOR),
- add one term which tests for that alternative.
- We do not want to do this if the insn has one
- alternative and we have tested none of them! */
- vector[0].exp = make_alternative_compare (i);
- if (code == IOR)
- vector[0].exp = attr_rtx (NOT, vector[0].exp);
- }
- }
-
- /* Try distributive law in one simple way. */
- common_term = 0;
- for (i = 0; i < nterms; i++)
- if (vector[i].exp != 0)
- {
- if (GET_CODE (vector[i].exp) != other_code)
- break;
- if (common_term == 0)
- common_term = XEXP (vector[i].exp, 0);
- else if (!rtx_equal_p (XEXP (vector[i].exp, 0), common_term))
- break;
- }
- if (i != nterms)
- common_term = 0;
-
- /* If we found a subterm in common, remove it from each term. */
- if (common_term)
- for (i = 0; i < nterms; i++)
- if (vector[i].exp != 0)
- vector[i].exp = XEXP (vector[i].exp, 1);
-
- /* See if any two adjacent terms are equivalent or contrary.
- Equivalent or contrary terms should be adjacent because of sorting. */
- for (i = 0; i < nterms - 1; i++)
- {
- rtx base0 = vector[i].exp;
- rtx base1 = vector[i + 1].exp;
- if (base0 != 0 && base1 != 0)
- {
- if (GET_CODE (base0) == NOT)
- base0 = XEXP (base0, 0);
- if (GET_CODE (base1) == NOT)
- base1 = XEXP (base1, 0);
- if (rtx_equal_p (base0, base1))
- {
- if (! rtx_equal_p (vector[i].exp, vector[i + 1].exp))
- {
- /* There are two contrary terms:
- The value is true for IOR, false for AND. */
- return common_term ? common_term : stable;
- }
- /* Delete one of a pair of equivalent terms. */
- vector[i].exp = 0;
- vector[i].ignore |= vector[i + 1].ignore;
- }
- }
- }
-
- /* Take advantage of the fact that two different values for the same
- attribute are contradictory. */
- if (code == AND)
- {
- for (i = 0; i < nterms; i++)
- if (vector[i].exp != 0 && GET_CODE (vector[i].exp) == EQ_ATTR)
- {
- char *aname = XSTR (vector[i].exp, 0);
-
- for (j = i + 1; j < nterms; j++)
- {
- if (vector[j].exp != 0 && GET_CODE (vector[j].exp) == EQ_ATTR
- && XSTR (vector[i].exp, 0) == aname)
- {
- return common_term ? common_term : stable;
- }
-
- if (vector[i].exp != 0 && GET_CODE (vector[i].exp) == NOT
- && GET_CODE (XEXP (vector[i].exp, 0)) == EQ_ATTR
- && XSTR (XEXP (vector[i].exp, 0), 0) == aname)
- vector[i].exp = 0;
- }
- }
- }
-
- /* Now build up rtl from the terms we didn't get rid of. */
- combined = unstable;
- for (i = 0; i < nterms; i++)
- if (vector[i].exp != 0 && ! vector[i].ignore)
- {
- if (combined == unstable)
- combined = vector[i].exp;
- else
- combined = attr_rtx (code, vector[i].exp, combined);
- }
- if (common_term)
- return attr_rtx (other_code, common_term, combined);
- return combined;
-}
-
-rtx
-simplify_ands (exp1, exp2, exp3, insn_code, insn_index)
- rtx exp1, exp2, exp3;
- int insn_code, insn_index;
-{
- return simplify_boolean (AND, exp1, exp2, exp3, false_rtx, true_rtx,
- insn_code, insn_index);
-}
-
-rtx
-simplify_iors (exp1, exp2, exp3, insn_code, insn_index)
- rtx exp1, exp2, exp3;
- int insn_code, insn_index;
-{
- return simplify_boolean (IOR, exp1, exp2, exp3, true_rtx, false_rtx,
- insn_code, insn_index);
-}
-
-#if 0
-
/* This routine is called when an AND of a term with a tree of AND's is
encountered. If the term or its complement is present in the tree, it
can be replaced with TRUE or FALSE, respectively.
@@ -2548,8 +2265,6 @@ simplify_or_tree (exp, pterm, insn_code, insn_index)
return exp;
}
-
-#endif
/* Given an expression, see if it can be simplified for a particular insn
code based on the values of other attributes being tested. This can
@@ -2590,39 +2305,176 @@ simplify_test_exp (exp, insn_code, insn_index)
switch (GET_CODE (exp))
{
case AND:
- exp = simplify_ands (XEXP (exp, 0), XEXP (exp, 1), 0,
- insn_code, insn_index);
- if (GET_CODE (exp) == AND)
+ left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
+ right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
+
+ /* If either side is an IOR and we have (eq_attr "alternative" ..")
+ present on both sides, apply the distributive law since this will
+ yield simplifications. */
+ if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
+ && compute_alternative_mask (left, IOR)
+ && compute_alternative_mask (right, IOR))
{
- left = XEXP (exp, 0);
- right = XEXP (exp, 1);
-
- /* If either side is an IOR and we have (eq_attr "alternative" ..")
- present on both sides, apply the distributive law since this will
- yield simplifications. */
- if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
- && compute_alternative_mask (left, IOR)
- && compute_alternative_mask (right, IOR))
+ if (GET_CODE (left) == IOR)
{
- if (GET_CODE (left) == IOR)
- {
- rtx tem = left;
- left = right;
- right = tem;
- }
+ rtx tem = left;
+ left = right;
+ right = tem;
+ }
+
+ newexp = attr_rtx (IOR,
+ attr_rtx (AND, left, XEXP (right, 0)),
+ attr_rtx (AND, left, XEXP (right, 1)));
+
+ return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
+ }
+
+ /* Try with the term on both sides. */
+ right = simplify_and_tree (right, &left, insn_code, insn_index);
+ if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
+ left = simplify_and_tree (left, &right, insn_code, insn_index);
+
+ if (left == false_rtx || right == false_rtx)
+ {
+ obstack_free (rtl_obstack, spacer);
+ return false_rtx;
+ }
+ else if (left == true_rtx)
+ {
+ obstack_free (rtl_obstack, spacer);
+ return SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
+ }
+ else if (right == true_rtx)
+ {
+ obstack_free (rtl_obstack, spacer);
+ return SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
+ }
- newexp = attr_rtx (IOR,
- attr_rtx (AND, left, XEXP (right, 0)),
- attr_rtx (AND, left, XEXP (right, 1)));
+ /* See if all or all but one of the insn's alternatives are specified
+ in this tree. Optimize if so. */
+
+ else if (insn_code >= 0
+ && (GET_CODE (left) == AND
+ || (GET_CODE (left) == NOT
+ && GET_CODE (XEXP (left, 0)) == EQ_ATTR
+ && XSTR (XEXP (left, 0), 0) == alternative_name)
+ || GET_CODE (right) == AND
+ || (GET_CODE (right) == NOT
+ && GET_CODE (XEXP (right, 0)) == EQ_ATTR
+ && XSTR (XEXP (right, 0), 0) == alternative_name)))
+ {
+ i = compute_alternative_mask (exp, AND);
+ if (i & ~insn_alternatives[insn_code])
+ fatal ("Illegal alternative specified for pattern number %d",
+ insn_index);
+
+ /* If all alternatives are excluded, this is false. */
+ i ^= insn_alternatives[insn_code];
+ if (i == 0)
+ return false_rtx;
+ else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
+ {
+ /* If just one excluded, AND a comparison with that one to the
+ front of the tree. The others will be eliminated by
+ optimization. We do not want to do this if the insn has one
+ alternative and we have tested none of them! */
+ left = make_alternative_compare (i);
+ right = simplify_and_tree (exp, &left, insn_code, insn_index);
+ newexp = attr_rtx (AND, left, right);
return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
}
}
- return exp;
+
+ if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
+ {
+ newexp = attr_rtx (AND, left, right);
+ return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
+ }
+ break;
case IOR:
- return simplify_iors (XEXP (exp, 0), XEXP (exp, 1), 0,
- insn_code, insn_index);
+ left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
+ right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
+
+ right = simplify_or_tree (right, &left, insn_code, insn_index);
+ if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
+ left = simplify_or_tree (left, &right, insn_code, insn_index);
+
+ if (right == true_rtx || left == true_rtx)
+ {
+ obstack_free (rtl_obstack, spacer);
+ return true_rtx;
+ }
+ else if (left == false_rtx)
+ {
+ obstack_free (rtl_obstack, spacer);
+ return SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
+ }
+ else if (right == false_rtx)
+ {
+ 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))
+ (and (x) (z)))
+ to (and (x)
+ (ior (y) (z)))
+ */
+
+ else if (GET_CODE (left) == AND && GET_CODE (right) == AND
+ && rtx_equal_p (XEXP (left, 0), XEXP (right, 0)))
+ {
+ newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
+
+ left = XEXP (left, 0);
+ right = newexp;
+ newexp = attr_rtx (AND, left, right);
+ return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
+ }
+
+ /* See if all or all but one of the insn's alternatives are specified
+ in this tree. Optimize if so. */
+
+ else if (insn_code >= 0
+ && (GET_CODE (left) == IOR
+ || (GET_CODE (left) == EQ_ATTR
+ && XSTR (left, 0) == alternative_name)
+ || GET_CODE (right) == IOR
+ || (GET_CODE (right) == EQ_ATTR
+ && XSTR (right, 0) == alternative_name)))
+ {
+ i = compute_alternative_mask (exp, IOR);
+ if (i & ~insn_alternatives[insn_code])
+ fatal ("Illegal alternative specified for pattern number %d",
+ insn_index);
+
+ /* If all alternatives are included, this is true. */
+ i ^= insn_alternatives[insn_code];
+ if (i == 0)
+ return true_rtx;
+ else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
+ {
+ /* If just one excluded, IOR a comparison with that one to the
+ front of the tree. The others will be eliminated by
+ optimization. We do not want to do this if the insn has one
+ alternative and we have tested none of them! */
+ left = make_alternative_compare (i);
+ right = simplify_and_tree (exp, &left, insn_code, insn_index);
+ newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
+
+ return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
+ }
+ }
+
+ if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
+ {
+ newexp = attr_rtx (IOR, left, right);
+ return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
+ }
+ break;
case NOT:
if (GET_CODE (XEXP (exp, 0)) == NOT)
@@ -3394,7 +3246,22 @@ eliminate_known_true (known_true, exp, insn_code, insn_index)
{
rtx term;
- return simplify_ands (exp, 0, known_true, insn_code, insn_index);
+ known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
+
+ if (GET_CODE (known_true) == AND)
+ {
+ exp = eliminate_known_true (XEXP (known_true, 0), exp,
+ insn_code, insn_index);
+ exp = eliminate_known_true (XEXP (known_true, 1), exp,
+ insn_code, insn_index);
+ }
+ else
+ {
+ term = known_true;
+ exp = simplify_and_tree (exp, &term, insn_code, insn_index);
+ }
+
+ return exp;
}
/* Write out a series of tests and assignment statements to perform tests and
@@ -4149,7 +4016,6 @@ main (argc, argv)
obstack_init (rtl_obstack);
obstack_init (hash_obstack);
- obstack_init (accum_obstack);
if (argc <= 1)
fatal ("No input file name.");
OpenPOWER on IntegriCloud