diff options
author | rms <rms@138bc75d-0d04-0410-961f-82ee72b054a4> | 1992-05-05 03:06:39 +0000 |
---|---|---|
committer | rms <rms@138bc75d-0d04-0410-961f-82ee72b054a4> | 1992-05-05 03:06:39 +0000 |
commit | fa737ee85fa03a38a11741b03f7061ee2f23682a (patch) | |
tree | c55358c9062c68bef71a83b0bb7319c867a63423 /gcc/genattrtab.c | |
parent | 98e6062f4dad87478666d0e1a6bc3f2e1c8b3106 (diff) | |
download | ppe42-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.c | 494 |
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."); |