From 7339c88dc58d3f64a28e8f08fe9ed4cf929be7a0 Mon Sep 17 00:00:00 2001 From: Richard Stallman Date: Mon, 4 May 1992 22:57:54 +0000 Subject: [PATCH] *** empty log message *** From-SVN: r888 --- gcc/genattrtab.c | 450 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 306 insertions(+), 144 deletions(-) diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 31579807229..73c09eb2f82 100644 --- a/gcc/genattrtab.c +++ b/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) - { - newtest = SIMPLIFY_TEST_EXP (XVECEXP (exp, 0, i), insn_code, insn_index); - 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); + /* This lets us free all storage allocated below, if appropriate. */ + first_spacer = (char *) obstack_next_free (rtl_obstack); - XEXP (newexp, 1) = XVECEXP (exp, 0, i + 1); - break; - } + bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx)); - 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); + /* See if default value needs simplification. */ + if (GET_CODE (defval) == COND) + defval = simplify_cond (defval, insn_code, insn_index); - for (j = i; j < XVECLEN (newexp, 0); j++) - XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); + /* Simplify now, just to see what tests we can get rid of. */ - XEXP (newexp, 1) = XEXP (exp, 1); - break; - } + /* 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) + { + rtx newtest, newval; - 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); + /* Simplify this test. */ + newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index); - XVECEXP (newexp, 0, i) = newtest; - break; + 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) + { + /* If test is true, make this value the default + and discard this + any following tests. */ + len = i; + defval = tests[i]; } - /* See if this value may need simplification. */ - if (GET_CODE (XVECEXP (exp, 0, i + 1)) == COND) + else if (newtest == false_rtx) { - 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); + /* If test is false, discard it and its value. */ + for (j = i; j < len - 2; j++) + tests[j] = tests[j + 2]; - 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; - } + else if (i == len - 2 && rtx_equal_p (newval, defval)) + len -= 2; + } - /* 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); + obstack_free (rtl_obstack, first_spacer); - 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); + if (len == 0) + { + defval = XEXP (exp, 1); + if (GET_CODE (defval) == COND) + return simplify_cond (defval, insn_code, insn_index); + return defval; + } + else + { + rtx newexp; - for (j = i + 2; j < XVECLEN (newexp, 0); j++) - XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); + /* Simplify again, for real this time. */ - XEXP (newexp, 1) = XEXP (exp, 1); - break; - } - } + if (GET_CODE (defval) == COND) + defval = simplify_cond (defval, insn_code, insn_index); - /* See if default value needs simplification. */ - if (GET_CODE (XEXP (exp, 1)) == COND) - { - value = simplify_cond (XEXP (exp, 1), insn_code, insn_index); - if (value != XEXP (exp, 1)) + for (i = len - 2; i >= 0; i -= 2) { - 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; + /* 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; } - - 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); } /* 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."); -- 2.30.2