X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fgenattrtab.c;h=14ecac1f1e55969078bd8395e535be489e6af7c8;hp=69259dde251a052b25ec3b9a36e5b04a5d8ad6aa;hb=1045c81583528e3b5603c64bc6113461be8e4538;hpb=fd004d82d76aab2c057a79e2d9390a01d0500d92 diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 69259dde251..14ecac1f1e5 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -1,6 +1,6 @@ /* Generate code from machine description to compute values of attributes. - Copyright (C) 1991 Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@nyu.edu) + Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -16,7 +16,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ /* This program handles insn attributes and the DEFINE_DELAY and DEFINE_FUNCTION_UNIT definitions. @@ -94,13 +95,28 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ EQ_ATTR rtx is true if !volatil and false if volatil. */ -#include "gvarargs.h" -#include "config.h" +#include "hconfig.h" +/* varargs must always be included after *config.h. */ +#ifdef __STDC__ +#include +#else +#include +#endif #include "rtl.h" -#include "obstack.h" #include "insn-config.h" /* For REGISTER_CONSTRAINTS */ #include +#ifndef VMS +#ifndef USG +#include +#include +#endif +#endif + +/* We must include obstack.h after , to avoid lossage with + /usr/include/sys/stdtypes.h on Sun OS 4.x. */ +#include "obstack.h" + static struct obstack obstack, obstack1, obstack2; struct obstack *rtl_obstack = &obstack; struct obstack *hash_obstack = &obstack1; @@ -130,12 +146,12 @@ void fancy_abort (); struct insn_def { - int insn_code; /* Instruction number. */ - int insn_index; /* Expression numer in file, for errors. */ - struct insn_def *next; /* Next insn in chain. */ - rtx def; /* The DEFINE_... */ + int insn_code; /* Instruction number. */ + int insn_index; /* Expression numer in file, for errors. */ + struct insn_def *next; /* Next insn in chain. */ + rtx def; /* The DEFINE_... */ int num_alternatives; /* Number of alternatives. */ - int vec_idx; /* Index of attribute vector in `def'. */ + int vec_idx; /* Index of attribute vector in `def'. */ }; /* Once everything has been read in, we store in each attribute value a list @@ -166,15 +182,15 @@ struct attr_value struct attr_desc { - char *name; /* Name of attribute. */ - struct attr_desc *next; /* Next attribute. */ - int is_numeric; /* Values of this attribute are numeric. */ + char *name; /* Name of attribute. */ + struct attr_desc *next; /* Next attribute. */ + int is_numeric; /* Values of this attribute are numeric. */ int negative_ok; /* Allow negative numeric values. */ int unsigned_p; /* Make the output function unsigned int. */ int is_const; /* Attribute value constant for each run. */ - int is_special; /* Don't call `write_attr_set'. */ - struct attr_value *first_value; /* First value of this attribute. */ - struct attr_value *default_val; /* Default value for this attribute. */ + int is_special; /* Don't call `write_attr_set'. */ + struct attr_value *first_value; /* First value of this attribute. */ + struct attr_value *default_val; /* Default value for this attribute. */ }; #define NULL_ATTR (struct attr_desc *) NULL @@ -192,7 +208,7 @@ struct range struct delay_desc { rtx def; /* DEFINE_DELAY expression. */ - struct delay_desc *next; /* Next DEFINE_DELAY. */ + struct delay_desc *next; /* Next DEFINE_DELAY. */ int num; /* Number of DEFINE_DELAY, starting at 1. */ }; @@ -220,12 +236,12 @@ struct function_unit int multiplicity; /* Number of units of this type. */ int simultaneity; /* Maximum number of simultaneous insns on this function unit or 0 if unlimited. */ - rtx condexp; /* Expression TRUE for insn needing unit. */ + rtx condexp; /* Expression TRUE for insn needing unit. */ int num_opclasses; /* Number of different operation types. */ struct function_unit_op *ops; /* Pointer to first operation type. */ int needs_conflict_function; /* Nonzero if a conflict function required. */ int needs_blockage_function; /* Nonzero if a blockage function required. */ - int needs_range_function; /* Nonzero if a blockage range function required. */ + int needs_range_function; /* Nonzero if blockage range function needed.*/ rtx default_cost; /* Conflict cost, if constant. */ struct range issue_delay; /* Range of issue delay values. */ int max_blockage; /* Maximum time an insn blocks the unit. */ @@ -240,7 +256,50 @@ static struct insn_def *defs; static struct delay_desc *delays; static struct function_unit *units; -/* Other variables. */ +/* An expression where all the unknown terms are EQ_ATTR tests can be + rearranged into a COND provided we can enumerate all possible + combinations of the unknown values. The set of combinations become the + tests of the COND; the value of the expression given that combination is + computed and becomes the corresponding value. To do this, we must be + able to enumerate all values for each attribute used in the expression + (currently, we give up if we find a numeric attribute). + + If the set of EQ_ATTR tests used in an expression tests the value of N + different attributes, the list of all possible combinations can be made + by walking the N-dimensional attribute space defined by those + attributes. We record each of these as a struct dimension. + + The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an + expression are the same, the will also have the same address. We find + all the EQ_ATTR nodes by marking them MEM_VOLATILE_P. This bit later + represents the value of an EQ_ATTR node, so once all nodes are marked, + they are also given an initial value of FALSE. + + We then separate the set of EQ_ATTR nodes into dimensions for each + attribute and put them on the VALUES list. Terms are added as needed by + `add_values_to_cover' so that all possible values of the attribute are + tested. + + Each dimension also has a current value. This is the node that is + currently considered to be TRUE. If this is one of the nodes added by + `add_values_to_cover', all the EQ_ATTR tests in the original expression + will be FALSE. Otherwise, only the CURRENT_VALUE will be true. + + NUM_VALUES is simply the length of the VALUES list and is there for + convenience. + + Once the dimensions are created, the algorithm enumerates all possible + values and computes the current value of the given expression. */ + +struct dimension +{ + struct attr_desc *attr; /* Attribute for this dimension. */ + rtx values; /* List of attribute values used. */ + rtx current_value; /* Position in the list for the TRUE value. */ + int num_values; /* Length of the values list. */ +}; + +/* Other variables. */ static int insn_code_number; static int insn_index_number; @@ -248,9 +307,11 @@ static int got_define_asm_attributes; static int must_extract; static int must_constrain; static int address_used; +static int length_used; static int num_delays; static int have_annul_true, have_annul_false; static int num_units; +static int num_insn_ents; /* Used as operand to `operate_exp': */ @@ -297,85 +358,96 @@ static char *alternative_name; /* These are referenced by rtlanal.c and hence need to be defined somewhere. They won't actually be used. */ -rtx frame_pointer_rtx, stack_pointer_rtx, arg_pointer_rtx; +rtx frame_pointer_rtx, hard_frame_pointer_rtx, stack_pointer_rtx; +rtx arg_pointer_rtx; -static rtx attr_rtx (); +static rtx attr_rtx PVPROTO((enum rtx_code, ...)); +#ifdef HAVE_VPRINTF +static char *attr_printf PVPROTO((int, char *, ...)); +#else static char *attr_printf (); -static char *attr_string (); -static rtx check_attr_test (); -static rtx check_attr_value (); -static rtx convert_set_attr_alternative (); -static rtx convert_set_attr (); -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 rtx copy_boolean (); -static void expand_delays (); -static rtx operate_exp (); -static void expand_units (); -static rtx simplify_knowing (); -static rtx encode_units_mask (); -static void fill_attr (); -static rtx substitute_address (); -static void make_length_attrs (); -static rtx identity_fn (); -static rtx zero_fn (); -static rtx one_fn (); -static rtx max_fn (); -static rtx simplify_cond (); -static rtx simplify_by_alternatives (); -static rtx simplify_by_exploding (); -static int find_and_mark_used_attributes (); -static void unmark_used_attributes (); -static int add_values_to_cover (); -static int increment_current_value (); -static rtx test_for_current_value (); -static rtx simplify_with_current_value (); -static rtx simplify_with_current_value_aux (); -static void remove_insn_ent (); -static void insert_insn_ent (); -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_test_exp (); -static void optimize_attrs (); -static void gen_attr (); -static int count_alternatives (); -static int compares_alternatives_p (); -static int contained_in_p (); -static void gen_insn (); -static void gen_delay (); -static void gen_unit (); -static void write_test_expr (); -static int max_attr_value (); -static void walk_attr_value (); -static void write_attr_get (); -static rtx eliminate_known_true (); -static void write_attr_set (); -static void write_attr_case (); -static void write_attr_value (); -static void write_attr_valueq (); -static void write_upcase (); -static void write_indent (); -static void write_eligible_delay (); -static void write_function_unit_info (); -static void write_complex_function (); -static int n_comma_elts (); -static char *next_comma_elt (); -static struct attr_desc *find_attr (); -static void make_internal_attr (); -static struct attr_value *find_most_used (); -static rtx find_single_value (); -static rtx make_numeric_value (); -static void extend_range (); -char *xrealloc (); -char *xmalloc (); -static void fatal (); +#endif + +static char *attr_string PROTO((char *, int)); +static rtx check_attr_test PROTO((rtx, int)); +static rtx check_attr_value PROTO((rtx, struct attr_desc *)); +static rtx convert_set_attr_alternative PROTO((rtx, int, int, int)); +static rtx convert_set_attr PROTO((rtx, int, int, int)); +static void check_defs PROTO((void)); +static rtx convert_const_symbol_ref PROTO((rtx, struct attr_desc *)); +static rtx make_canonical PROTO((struct attr_desc *, rtx)); +static struct attr_value *get_attr_value PROTO((rtx, struct attr_desc *, int)); +static rtx copy_rtx_unchanging PROTO((rtx)); +static rtx copy_boolean PROTO((rtx)); +static void expand_delays PROTO((void)); +static rtx operate_exp PROTO((enum operator, rtx, rtx)); +static void expand_units PROTO((void)); +static rtx simplify_knowing PROTO((rtx, rtx)); +static rtx encode_units_mask PROTO((rtx)); +static void fill_attr PROTO((struct attr_desc *)); +/* dpx2 compiler chokes if we specify the arg types of the args. */ +static rtx substitute_address PROTO((rtx, rtx (*) (), rtx (*) ())); +static void make_length_attrs PROTO((void)); +static rtx identity_fn PROTO((rtx)); +static rtx zero_fn PROTO((rtx)); +static rtx one_fn PROTO((rtx)); +static rtx max_fn PROTO((rtx)); +static rtx simplify_cond PROTO((rtx, int, int)); +static rtx simplify_by_alternatives PROTO((rtx, int, int)); +static rtx simplify_by_exploding PROTO((rtx)); +static int find_and_mark_used_attributes PROTO((rtx, rtx *, int *)); +static void unmark_used_attributes PROTO((rtx, struct dimension *, int)); +static int add_values_to_cover PROTO((struct dimension *)); +static int increment_current_value PROTO((struct dimension *, int)); +static rtx test_for_current_value PROTO((struct dimension *, int)); +static rtx simplify_with_current_value PROTO((rtx, struct dimension *, int)); +static rtx simplify_with_current_value_aux PROTO((rtx)); +static void clear_struct_flag PROTO((rtx)); +static int count_sub_rtxs PROTO((rtx, int)); +static void remove_insn_ent PROTO((struct attr_value *, struct insn_ent *)); +static void insert_insn_ent PROTO((struct attr_value *, struct insn_ent *)); +static rtx insert_right_side PROTO((enum rtx_code, rtx, rtx, int, int)); +static rtx make_alternative_compare PROTO((int)); +static int compute_alternative_mask PROTO((rtx, enum rtx_code)); +static rtx evaluate_eq_attr PROTO((rtx, rtx, int, int)); +static rtx simplify_and_tree PROTO((rtx, rtx *, int, int)); +static rtx simplify_or_tree PROTO((rtx, rtx *, int, int)); +static rtx simplify_test_exp PROTO((rtx, int, int)); +static void optimize_attrs PROTO((void)); +static void gen_attr PROTO((rtx)); +static int count_alternatives PROTO((rtx)); +static int compares_alternatives_p PROTO((rtx)); +static int contained_in_p PROTO((rtx, rtx)); +static void gen_insn PROTO((rtx)); +static void gen_delay PROTO((rtx)); +static void gen_unit PROTO((rtx)); +static void write_test_expr PROTO((rtx, int)); +static int max_attr_value PROTO((rtx)); +static void walk_attr_value PROTO((rtx)); +static void write_attr_get PROTO((struct attr_desc *)); +static rtx eliminate_known_true PROTO((rtx, rtx, int, int)); +static void write_attr_set PROTO((struct attr_desc *, int, rtx, char *, + char *, rtx, int, int)); +static void write_attr_case PROTO((struct attr_desc *, struct attr_value *, + int, char *, char *, int, rtx)); +static void write_attr_valueq PROTO((struct attr_desc *, char *)); +static void write_attr_value PROTO((struct attr_desc *, rtx)); +static void write_upcase PROTO((char *)); +static void write_indent PROTO((int)); +static void write_eligible_delay PROTO((char *)); +static void write_function_unit_info PROTO((void)); +static void write_complex_function PROTO((struct function_unit *, char *, + char *)); +static int n_comma_elts PROTO((char *)); +static char *next_comma_elt PROTO((char **)); +static struct attr_desc *find_attr PROTO((char *, int)); +static void make_internal_attr PROTO((char *, rtx, int)); +static struct attr_value *find_most_used PROTO((struct attr_desc *)); +static rtx find_single_value PROTO((struct attr_desc *)); +static rtx make_numeric_value PROTO((int)); +static void extend_range PROTO((struct range *, int, int)); +char *xrealloc PROTO((char *, unsigned)); +char *xmalloc PROTO((unsigned)); #define oballoc(size) obstack_alloc (hash_obstack, size) @@ -457,11 +529,12 @@ attr_hash_add_string (hashcode, str) /*VARARGS1*/ static rtx -attr_rtx (va_alist) - va_dcl +attr_rtx VPROTO((enum rtx_code code, ...)) { - va_list p; +#ifndef __STDC__ enum rtx_code code; +#endif + va_list p; register int i; /* Array indices... */ register char *fmt; /* Current rtx's format... */ register rtx rt_val; /* RTX to return to caller... */ @@ -469,8 +542,11 @@ attr_rtx (va_alist) register struct attr_hash *h; struct obstack *old_obstack = rtl_obstack; - va_start (p); + VA_START (p, code); + +#ifndef __STDC__ code = va_arg (p, enum rtx_code); +#endif /* For each of several cases, search the hash table for an existing entry. Use that entry if one is found; otherwise create a new RTL and add it @@ -652,19 +728,24 @@ attr_rtx (va_alist) /*VARARGS2*/ static char * -attr_printf (va_alist) - va_dcl +attr_printf VPROTO((register int len, char *fmt, ...)) { - va_list p; +#ifndef __STDC__ register int len; - register char *fmt; + char *fmt; +#endif + va_list p; register char *str; - /* Print the string into a temporary location. */ - va_start (p); + VA_START (p, fmt); + +#ifndef __STDC__ len = va_arg (p, int); - str = (char *) alloca (len); fmt = va_arg (p, char *); +#endif + + /* Print the string into a temporary location. */ + str = (char *) alloca (len); vsprintf (str, fmt, p); va_end (p); @@ -925,13 +1006,16 @@ check_attr_test (exp, is_const) while ((p = next_comma_elt (&name_ptr)) != NULL) { newexp = attr_eq (XSTR (exp, 0), p); - orexp = insert_right_side (IOR, orexp, newexp, -2); + orexp = insert_right_side (IOR, orexp, newexp, -2, -2); } return check_attr_test (orexp, is_const); } break; + case ATTR_FLAG: + break; + case CONST_INT: /* Either TRUE or FALSE. */ if (XWINT (exp, 0)) @@ -1068,10 +1152,10 @@ check_attr_value (exp, attr) /* A constant SYMBOL_REF is valid as a constant attribute test and is expanded later by make_canonical into a COND. */ return attr_rtx (SYMBOL_REF, XSTR (exp, 0)); - /* Otherwise, fall through... */ + /* Otherwise, fall through... */ default: - fatal ("Illegal operation `%s' for attribute value", + fatal ("Invalid operation `%s' for attribute value", GET_RTX_NAME (GET_CODE (exp))); } @@ -1155,7 +1239,7 @@ convert_set_attr (exp, num_alt, insn_code, insn_index) /* Scan all definitions, checking for validity. Also, convert any SET_ATTR and SET_ATTR_ALTERNATIVE expressions to the corresponding SET - expressions. */ + expressions. */ static void check_defs () @@ -1319,7 +1403,7 @@ make_canonical (attr, exp) int allsame = 1; rtx defval; - /* First, check for degenerate COND. */ + /* 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)); @@ -1720,8 +1804,6 @@ expand_units () for (unit = units; unit; unit = unit->next) { - rtx min_issue = make_numeric_value (unit->issue_delay.min); - unit->condexp = check_attr_test (unit->condexp, 0); for (op = unit->ops; op; op = op->next) @@ -1803,7 +1885,7 @@ expand_units () * sizeof (struct function_unit_op *)); for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next) - bcopy (unit_ops[unit->num], &op_array[i], + bcopy ((char *) unit_ops[unit->num], (char *) &op_array[i], unit->num_opclasses * sizeof (struct function_unit_op *)); /* Compute the ready cost function for each unit by computing the @@ -1854,7 +1936,7 @@ expand_units () if (op->ready <= 1) break; else if (op->ready == value) - orexp = insert_right_side (IOR, orexp, op->condexp, -2); + orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2); else { XVECEXP (readycost, 0, nvalues * 2) = orexp; @@ -1884,6 +1966,10 @@ expand_units () candidate insn, so in the expressions below, C is a known term and E is an unknown term. + We compute the blockage cost for each E for every possible C. + Thus OP represents E, and READYCOST is a list of values for + every possible C. + The issue delay function for C is op->issue_exp and is used to write the `_unit_conflict_cost' function. Symbolicly this is "ISSUE-DELAY (E,C)". @@ -1917,16 +2003,19 @@ expand_units () for (op = unit->ops; op; op = op->next) { - rtx blockage = readycost; - int delay = op->ready - 1; + rtx blockage = operate_exp (POS_MINUS_OP, readycost, + make_numeric_value (1)); if (unit->simultaneity != 0) - delay = MIN (delay, ((unit->simultaneity - 1) - * unit->issue_delay.min)); + { + rtx filltime = make_numeric_value ((unit->simultaneity - 1) + * unit->issue_delay.min); + blockage = operate_exp (MIN_OP, blockage, filltime); + } - if (delay > 0) - blockage = operate_exp (POS_MINUS_OP, blockage, - make_numeric_value (delay)); + blockage = operate_exp (POS_MINUS_OP, + make_numeric_value (op->ready), + blockage); blockage = operate_exp (MAX_OP, blockage, op->issue_exp); blockage = simplify_knowing (blockage, unit->condexp); @@ -2239,8 +2328,8 @@ make_length_attrs () static char *new_names[] = {"*insn_default_length", "*insn_variable_length_p", "*insn_current_length"}; - static rtx (*no_address_fn[]) () = {identity_fn, zero_fn, zero_fn}; - static rtx (*address_fn[]) () = {max_fn, one_fn, identity_fn}; + static rtx (*no_address_fn[]) PROTO((rtx)) = {identity_fn, zero_fn, zero_fn}; + static rtx (*address_fn[]) PROTO((rtx)) = {max_fn, one_fn, identity_fn}; int i; struct attr_desc *length_attr, *new_attr; struct attr_value *av, *new_av; @@ -2329,16 +2418,15 @@ simplify_cond (exp, insn_code, insn_index) then build a new expression if they don't match EXP. */ rtx defval = XEXP (exp, 1); rtx new_defval = XEXP (exp, 1); - int len = XVECLEN (exp, 0); - rtx *tests = (rtx *) alloca (len * sizeof (rtx)); + rtunion *tests = (rtunion *) alloca (len * sizeof (rtunion)); int allsame = 1; char *first_spacer; /* This lets us free all storage allocated below, if appropriate. */ first_spacer = (char *) obstack_finish (rtl_obstack); - bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx)); + bcopy ((char *) XVEC (exp, 0)->elem, (char *) tests, len * sizeof (rtunion)); /* See if default value needs simplification. */ if (GET_CODE (defval) == COND) @@ -2351,10 +2439,10 @@ simplify_cond (exp, insn_code, insn_index) rtx newtest, newval; /* Simplify this test. */ - newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index); - tests[i] = newtest; + newtest = SIMPLIFY_TEST_EXP (tests[i].rtx, insn_code, insn_index); + tests[i].rtx = newtest; - newval = tests[i + 1]; + newval = tests[i + 1].rtx; /* See if this value may need simplification. */ if (GET_CODE (newval) == COND) newval = simplify_cond (newval, insn_code, insn_index); @@ -2365,7 +2453,7 @@ simplify_cond (exp, insn_code, insn_index) /* If test is true, make this value the default and discard this + any following tests. */ len = i; - defval = tests[i + 1]; + defval = tests[i + 1].rtx; new_defval = newval; } @@ -2373,33 +2461,33 @@ simplify_cond (exp, insn_code, insn_index) { /* If test is false, discard it and its value. */ for (j = i; j < len - 2; j++) - tests[j] = tests[j + 2]; + tests[j].rtx = tests[j + 2].rtx; len -= 2; } - else if (i > 0 && attr_equal_p (newval, tests[i - 1])) + else if (i > 0 && attr_equal_p (newval, tests[i - 1].rtx)) { /* If this value and the value for the prev test are the same, merge the tests. */ - tests[i - 2] - = insert_right_side (IOR, tests[i - 2], newtest, + tests[i - 2].rtx + = insert_right_side (IOR, tests[i - 2].rtx, newtest, insn_code, insn_index); /* Delete this test/value. */ for (j = i; j < len - 2; j++) - tests[j] = tests[j + 2]; + tests[j].rtx = tests[j + 2].rtx; len -= 2; } else - tests[i + 1] = newval; + tests[i + 1].rtx = newval; } /* If the last test in a COND has the same value as the default value, that test isn't needed. */ - while (len > 0 && attr_equal_p (tests[len - 1], new_defval)) + while (len > 0 && attr_equal_p (tests[len - 1].rtx, new_defval)) len -= 2; /* See if we changed anything. */ @@ -2407,7 +2495,7 @@ simplify_cond (exp, insn_code, insn_index) allsame = 0; else for (i = 0; i < len; i++) - if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i))) + if (! attr_equal_p (tests[i].rtx, XVECEXP (exp, 0, i))) { allsame = 0; break; @@ -2430,7 +2518,8 @@ simplify_cond (exp, insn_code, insn_index) rtx newexp = rtx_alloc (COND); XVEC (newexp, 0) = rtvec_alloc (len); - bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx)); + bcopy ((char *) tests, (char *) XVEC (newexp, 0)->elem, + len * sizeof (rtunion)); XEXP (newexp, 1) = new_defval; return newexp; } @@ -2457,6 +2546,8 @@ remove_insn_ent (av, ie) av->num_insns--; if (ie->insn_code == -1) av->has_asm_insn = 0; + + num_insn_ents--; } /* Insert an insn entry in an attribute value list. */ @@ -2471,6 +2562,8 @@ insert_insn_ent (av, ie) av->num_insns++; if (ie->insn_code == -1) av->has_asm_insn = 1; + + num_insn_ents++; } /* This is a utility routine to take an expression that is a tree of either @@ -2484,7 +2577,7 @@ insert_insn_ent (av, ie) static rtx insert_right_side (code, exp, term, insn_code, insn_index) - RTX_CODE code; + enum rtx_code code; rtx exp; rtx term; int insn_code, insn_index; @@ -2546,13 +2639,12 @@ insert_right_side (code, exp, term, insn_code, insn_index) If so, we can optimize. Similarly for IOR's of EQ_ATTR. This routine is passed an expression and either AND or IOR. It returns a - bitmask indicating which alternatives are present. - ??? What does "present" mean? */ + bitmask indicating which alternatives are mentioned within EXP. */ static int compute_alternative_mask (exp, code) rtx exp; - RTX_CODE code; + enum rtx_code code; { char *string; if (GET_CODE (exp) == code) @@ -2600,9 +2692,10 @@ make_alternative_compare (mask) of "attr" for this insn code. From that value, we can compute a test showing when the EQ_ATTR will be true. This routine performs that 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!!! */ + EXP is the EQ_ATTR expression and VALUE is the value of that attribute + for the insn corresponding to INSN_CODE and INSN_INDEX. */ static rtx evaluate_eq_attr (exp, value, insn_code, insn_index) @@ -2634,7 +2727,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) For each possible COND value, call ourselves recursively. The extra TRUE and FALSE expressions will be eliminated by another - call to the simplification routine. */ + call to the simplification routine. */ orexp = false_rtx; andexp = true_rtx; @@ -2652,8 +2745,10 @@ evaluate_eq_attr (exp, value, 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), - insn_code, insn_index), + evaluate_eq_attr (exp, + XVECEXP (value, 0, + i + 1), + insn_code, insn_index), insn_code, insn_index); orexp = insert_right_side (IOR, orexp, right, insn_code, insn_index); @@ -2667,7 +2762,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index) /* Handle the default case. */ right = insert_right_side (AND, andexp, evaluate_eq_attr (exp, XEXP (value, 1), - insn_code, insn_index), + insn_code, insn_index), insn_code, insn_index); newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index); } @@ -2914,16 +3009,6 @@ simplify_test_exp (exp, insn_code, insn_index) rtx newexp = exp; char *spacer = (char *) obstack_finish (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) || MEM_IN_STRUCT_P (exp)) return exp; @@ -3000,10 +3085,10 @@ simplify_test_exp (exp, insn_code, insn_index) { i = compute_alternative_mask (exp, AND); if (i & ~insn_alternatives[insn_code]) - fatal ("Illegal alternative specified for pattern number %d", + fatal ("Invalid alternative specified for pattern number %d", insn_index); - /* If all alternatives are excluded, this is false. */ + /* If all alternatives are excluded, this is false. */ i ^= insn_alternatives[insn_code]; if (i == 0) return false_rtx; @@ -3093,10 +3178,10 @@ simplify_test_exp (exp, insn_code, insn_index) { i = compute_alternative_mask (exp, IOR); if (i & ~insn_alternatives[insn_code]) - fatal ("Illegal alternative specified for pattern number %d", + fatal ("Invalid alternative specified for pattern number %d", insn_index); - /* If all alternatives are included, this is true. */ + /* If all alternatives are included, this is true. */ i ^= insn_alternatives[insn_code]; if (i == 0) return true_rtx; @@ -3194,9 +3279,6 @@ simplify_test_exp (exp, insn_code, insn_index) 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 @@ -3216,34 +3298,48 @@ optimize_attrs () struct attr_desc * attr; struct attr_value_list *next; }; struct attr_value_list **insn_code_values; + struct attr_value_list *ivbuf; struct attr_value_list *iv; /* For each insn code, make a list of all the insn_ent's for it, for all values for all attributes. */ + if (num_insn_ents == 0) + return; + /* Make 2 extra elements, for "code" values -2 and -1. */ insn_code_values = (struct attr_value_list **) alloca ((insn_code_number + 2) * sizeof (struct attr_value_list *)); - bzero (insn_code_values, + bzero ((char *) insn_code_values, (insn_code_number + 2) * sizeof (struct attr_value_list *)); + /* Offset the table address so we can index by -2 or -1. */ insn_code_values += 2; + /* Allocate the attr_value_list structures using xmalloc rather than + alloca, because using alloca can overflow the maximum permitted + stack limit on SPARC Lynx. */ + iv = ivbuf = ((struct attr_value_list *) + xmalloc (num_insn_ents * sizeof (struct attr_value_list))); + for (i = 0; i < MAX_ATTRS_INDEX; i++) for (attr = attrs[i]; attr; attr = attr->next) for (av = attr->first_value; av; av = av->next) for (ie = av->first_insn; ie; ie = ie->next) { - iv = ((struct attr_value_list *) - alloca (sizeof (struct attr_value_list))); iv->attr = attr; iv->av = av; iv->ie = ie; iv->next = insn_code_values[ie->insn_code]; insn_code_values[ie->insn_code] = iv; + iv++; } + /* Sanity check on num_insn_ents. */ + if (iv != ivbuf + num_insn_ents) + abort (); + /* Process one insn code at a time. */ for (i = -2; i < insn_code_number; i++) { @@ -3293,6 +3389,8 @@ optimize_attrs () } } } + + free (ivbuf); } #if 0 @@ -3329,49 +3427,6 @@ simplify_by_alternatives (exp, insn_code, insn_index) } #endif -/* An expression where all the unknown terms are EQ_ATTR tests can be - rearranged into a COND provided we can enumerate all possible - combinations of the unknown values. The set of combinations become the - tests of the COND; the value of the expression given that combination is - computed and becomes the corresponding value. To do this, we must be - able to enumerate all values for each attribute used in the expression - (currently, we give up if we find a numeric attribute). - - If the set of EQ_ATTR tests used in an expression tests the value of N - different attributes, the list of all possible combinations can be made - by walking the N-dimensional attribute space defined by those - attributes. We record each of these as a struct dimension. - - The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an - expression are the same, the will also have the same address. We find - all the EQ_ATTR nodes by marking them MEM_VOLATILE_P. This bit later - represents the value of an EQ_ATTR node, so once all nodes are marked, - they are also given an initial value of FALSE. - - We then separate the set of EQ_ATTR nodes into dimensions for each - attribute and put them on the VALUES list. Terms are added as needed by - `add_values_to_cover' so that all possible values of the attribute are - tested. - - Each dimension also has a current value. This is the node that is - currently considered to be TRUE. If this is one of the nodes added by - `add_values_to_cover', all the EQ_ATTR tests in the original expression - will be FALSE. Otherwise, only the CURRENT_VALUE will be true. - - NUM_VALUES is simply the length of the VALUES list and is there for - convenience. - - Once the dimensions are created, the algorithm enumerates all possible - values and computes the current value of the given expression. */ - -struct dimension -{ - struct attr_desc *attr; /* Attribute for this dimension. */ - rtx values; /* List of attribute values used. */ - rtx current_value; /* Position in the list for the TRUE value. */ - int num_values; /* Length of the values list. */ -}; - /* If EXP is a suitable expression, reorganize it by constructing an equivalent expression that is a COND with the tests being all combinations of attribute values and the values being simple constants. */ @@ -3645,7 +3700,7 @@ add_values_to_cover (dim) prev = &dim->values; for (link = dim->values; link; link = *prev) { - orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2); + orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2); prev = &XEXP (link, 1); } link = rtx_alloc (EXPR_LIST); @@ -3689,7 +3744,8 @@ test_for_current_value (space, ndim) rtx exp = true_rtx; for (i = 0; i < ndim; i++) - exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0), -2); + exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0), + -2, -2); return exp; } @@ -3808,6 +3864,7 @@ simplify_with_current_value_aux (exp) /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */ +static void clear_struct_flag (x) rtx x; { @@ -3833,6 +3890,7 @@ clear_struct_flag (x) case PC: case CC0: case EQ_ATTR: + case ATTR_FLAG: return; } @@ -3860,6 +3918,7 @@ clear_struct_flag (x) /* Return the number of RTX objects making up the expression X. But if we count more more than MAX objects, stop counting. */ +static int count_sub_rtxs (x, max) rtx x; int max; @@ -3883,6 +3942,7 @@ count_sub_rtxs (x, max) case PC: case CC0: case EQ_ATTR: + case ATTR_FLAG: return 1; } @@ -3958,7 +4018,7 @@ gen_attr (exp) if (! strcmp (attr->name, "length") && ! attr->is_numeric) fatal ("`length' attribute must take numeric values"); - /* Set up the default value. */ + /* Set up the default value. */ XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2); } @@ -4204,7 +4264,7 @@ gen_unit (def) int i; for (i = 0; i < XVECLEN (def, 6); i++) - orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2); + orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2); op->conflict_exp = orexp; extend_range (&unit->issue_delay, 1, issue_delay); @@ -4217,7 +4277,7 @@ gen_unit (def) /* Merge our conditional into that of the function unit so we can determine which insns are used by the function unit. */ - unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2); + unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2); } /* Given a piece of RTX, print a C expression to test it's truth value. @@ -4249,7 +4309,7 @@ write_test_expr (exp, in_comparison) case PLUS: case MINUS: case MULT: case DIV: case MOD: case AND: case IOR: case XOR: - case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT: + case ASHIFT: case LSHIFTRT: case ASHIFTRT: write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator); switch (code) { @@ -4313,7 +4373,6 @@ write_test_expr (exp, in_comparison) case XOR: printf (" ^ "); break; - case LSHIFT: case ASHIFT: printf (" << "); break; @@ -4378,7 +4437,7 @@ write_test_expr (exp, in_comparison) if (attr->is_const) { write_test_expr (evaluate_eq_attr (exp, attr->default_val->value, - 0, 0), + -2, -2), in_comparison); } else @@ -4388,6 +4447,13 @@ write_test_expr (exp, in_comparison) } break; + /* Comparison test of flags for define_delays. */ + case ATTR_FLAG: + if (in_comparison) + fatal ("ATTR_FLAG not valid inside comparison"); + printf ("(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0)); + break; + /* See if an operand matches a predicate. */ case MATCH_OPERAND: /* If only a mode is given, just ensure the mode matches the operand. @@ -4405,7 +4471,7 @@ write_test_expr (exp, in_comparison) XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp))); break; - /* Constant integer. */ + /* Constant integer. */ case CONST_INT: #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT printf ("%d", XWINT (exp, 0)); @@ -4414,14 +4480,15 @@ write_test_expr (exp, in_comparison) #endif break; - /* A random C expression. */ + /* A random C expression. */ case SYMBOL_REF: printf ("%s", XSTR (exp, 0)); break; /* The address of the branch target. */ case MATCH_DUP: - printf ("insn_addresses[INSN_UID (JUMP_LABEL (insn))]"); + printf ("insn_addresses[INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])]", + XINT (exp, 0), XINT (exp, 0), XINT (exp, 0)); break; /* The address of the current insn. It would be more consistent with @@ -4489,6 +4556,7 @@ max_attr_value (exp) `must_extract' if we need to extract the insn operands `must_constrain' if we must compute `which_alternative' `address_used' if an address expression was used + `length_used' if an (eq_attr "length" ...) was used */ static void @@ -4520,12 +4588,21 @@ walk_attr_value (exp) case EQ_ATTR: if (XSTR (exp, 0) == alternative_name) must_extract = must_constrain = 1; + else if (strcmp (XSTR (exp, 0), "length") == 0) + length_used = 1; return; case MATCH_DUP: + must_extract = 1; + address_used = 1; + return; + case PC: address_used = 1; return; + + case ATTR_FLAG: + return; } for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++) @@ -4553,7 +4630,7 @@ write_attr_get (attr) struct attr_value *av, *common_av; /* Find the most used attribute value. Handle that as the `default' of the - switch we will generate. */ + switch we will generate. */ common_av = find_most_used (attr); /* Write out start of function, then all values with explicit `case' lines, @@ -4732,7 +4809,8 @@ write_attr_set (attr, indent, value, prefix, suffix, known_true, /* Write out the computation for one attribute value. */ static void -write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, known_true) +write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, + known_true) struct attr_desc *attr; struct attr_value *av; int write_case_lines; @@ -4772,7 +4850,7 @@ write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, known_true) printf ("default:\n"); } - /* See what we have to do to handle output this value. */ + /* See what we have to do to output this value. */ must_extract = must_constrain = address_used = 0; walk_attr_value (av->value); @@ -4893,10 +4971,12 @@ write_eligible_delay (kind) /* Write function prelude. */ printf ("int\n"); - printf ("eligible_for_%s (delay_insn, slot, candidate_insn)\n", kind); + printf ("eligible_for_%s (delay_insn, slot, candidate_insn, flags)\n", + kind); printf (" rtx delay_insn;\n"); printf (" int slot;\n"); printf (" rtx candidate_insn;\n"); + printf (" int flags;\n"); printf ("{\n"); printf (" rtx insn;\n"); printf ("\n"); @@ -5077,7 +5157,7 @@ write_complex_function (unit, name, connection) printf ("{\n"); printf (" rtx insn;\n"); printf (" int casenum;\n\n"); - printf (" insn = candidate_insn;\n"); + printf (" insn = executing_insn;\n"); printf (" switch (recog_memoized (insn))\n"); printf (" {\n"); @@ -5099,7 +5179,7 @@ write_complex_function (unit, name, connection) /* Now write an outer switch statement on each case. Then write the tests on the executing function within each. */ - printf (" insn = executing_insn;\n"); + printf (" insn = candidate_insn;\n"); printf (" switch (casenum)\n"); printf (" {\n"); @@ -5123,7 +5203,7 @@ write_complex_function (unit, name, connection) /* If single value, just write it. */ value = find_single_value (attr); if (value) - write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2); + write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2); else { common_av = find_most_used (attr); @@ -5383,7 +5463,7 @@ copy_rtx_unchanging (orig) PUT_MODE (copy, GET_MODE (orig)); RTX_UNCHANGING_P (copy) = 1; - bcopy (&XEXP (orig, 0), &XEXP (copy, 0), + bcopy ((char *) &XEXP (orig, 0), (char *) &XEXP (copy, 0), GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx)); return copy; #endif @@ -5392,6 +5472,7 @@ copy_rtx_unchanging (orig) static void fatal (s, a1, a2) char *s; + char *a1, *a2; { fprintf (stderr, "genattrtab: "); fprintf (stderr, s, a1, a2); @@ -5408,7 +5489,9 @@ fancy_abort () fatal ("Internal gcc abort."); } -/* Determine if an insn has a constant number of delay slots. */ +/* Determine if an insn has a constant number of delay slots, i.e., the + number of delay slots is not a function of the length of the insn. */ + void write_const_num_delay_slots () { @@ -5420,19 +5503,24 @@ write_const_num_delay_slots () if (attr) { printf ("int\nconst_num_delay_slots (insn)\n"); - printf (" rtx *insn;\n"); + printf (" rtx insn;\n"); printf ("{\n"); printf (" switch (recog_memoized (insn))\n"); printf (" {\n"); for (av = attr->first_value; av; av = av->next) - if (GET_CODE (av->value) == COND && av->num_insns) - { - for (ie = av->first_insn; ie; ie = ie->next) + { + length_used = 0; + walk_attr_value (av->value); + if (length_used) + { + for (ie = av->first_insn; ie; ie = ie->next) if (ie->insn_code != -1) printf (" case %d:\n", ie->insn_code); - printf (" return 0;\n"); - } + printf (" return 0;\n"); + } + } + printf (" default:\n"); printf (" return 1;\n"); printf (" }\n}\n"); @@ -5453,6 +5541,18 @@ main (argc, argv) rtx tem; int i; +#ifdef RLIMIT_STACK + /* Get rid of any avoidable limit on stack size. */ + { + struct rlimit rlim; + + /* Set the stack limit huge so that alloca does not fail. */ + getrlimit (RLIMIT_STACK, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit (RLIMIT_STACK, &rlim); + } +#endif /* RLIMIT_STACK defined */ + obstack_init (rtl_obstack); obstack_init (hash_obstack); obstack_init (temp_obstack); @@ -5576,7 +5676,7 @@ from the machine description file `md'. */\n\n"); /* Construct extra attributes for `length'. */ make_length_attrs (); - /* Perform any possible optimizations to speed up compilation. */ + /* Perform any possible optimizations to speed up compilation. */ optimize_attrs (); /* Now write out all the `gen_attr_...' routines. Do these before the