diff options
Diffstat (limited to 'gcc/genattrtab.c')
-rw-r--r-- | gcc/genattrtab.c | 394 |
1 files changed, 215 insertions, 179 deletions
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 287c69b4631..755a9a41f02 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -109,23 +109,17 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "coretypes.h" #include "tm.h" #include "rtl.h" -#include "ggc.h" #include "gensupport.h" - -#ifdef HAVE_SYS_RESOURCE_H -# include <sys/resource.h> -#endif - -/* We must include obstack.h after <sys/time.h>, to avoid lossage with - /usr/include/sys/stdtypes.h on Sun OS 4.x. */ #include "obstack.h" #include "errors.h" -#include "genattrtab.h" +/* Flags for make_internal_attr's `special' parameter. */ +#define ATTR_NONE 0 +#define ATTR_SPECIAL (1 << 0) static struct obstack obstack1, obstack2; -struct obstack *hash_obstack = &obstack1; -struct obstack *temp_obstack = &obstack2; +static struct obstack *hash_obstack = &obstack1; +static struct obstack *temp_obstack = &obstack2; /* enough space to reserve for printing out ints */ #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3) @@ -183,7 +177,6 @@ struct attr_desc unsigned is_numeric : 1; /* Values of this attribute are numeric. */ unsigned is_const : 1; /* Attribute value constant for each run. */ unsigned is_special : 1; /* Don't call `write_attr_set'. */ - unsigned static_p : 1; /* Make the output function static. */ }; /* Structure for each DEFINE_DELAY. */ @@ -217,8 +210,6 @@ static int num_delays; static int have_annul_true, have_annul_false; static int num_insn_ents; -int num_dfa_decls; - /* Stores, for each insn code, the number of constraint alternatives. */ static int *insn_n_alternatives; @@ -240,16 +231,6 @@ static const char *delay_type_str; static const char *delay_1_0_str; static const char *num_delay_slots_str; -/* Indicate that REG_DEAD notes are valid if dead_or_set_p is ever - called. */ - -int reload_completed = 0; - -/* Some machines test `optimize' in macros called from rtlanal.c, so we need - to define it here. */ - -int optimize = 0; - /* Simplify an expression. Only call the routine if there is something to simplify. */ #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \ @@ -258,88 +239,44 @@ int optimize = 0; #define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S))) -/* These are referenced by rtlanal.c and hence need to be defined somewhere. - They won't actually be used. */ - -rtx global_rtl[GR_MAX]; -rtx pic_offset_table_rtx; - -static void attr_hash_add_rtx (int, rtx); -static void attr_hash_add_string (int, char *); -static rtx attr_rtx (enum rtx_code, ...); -static rtx attr_rtx_1 (enum rtx_code, va_list); -static char *attr_string (const char *, int); -static rtx check_attr_value (rtx, struct attr_desc *); -static rtx convert_set_attr_alternative (rtx, struct insn_def *); -static rtx convert_set_attr (rtx, struct insn_def *); -static void check_defs (void); -static rtx make_canonical (struct attr_desc *, rtx); -static struct attr_value *get_attr_value (rtx, struct attr_desc *, int); -static rtx copy_rtx_unchanging (rtx); -static rtx copy_boolean (rtx); -static void expand_delays (void); -static void fill_attr (struct attr_desc *); -static rtx substitute_address (rtx, rtx (*) (rtx), rtx (*) (rtx)); -static void make_length_attrs (void); -static rtx identity_fn (rtx); -static rtx zero_fn (rtx); -static rtx one_fn (rtx); -static rtx max_fn (rtx); -static rtx min_fn (rtx); -static void write_length_unit_log (void); -static rtx simplify_cond (rtx, int, int); -static void clear_struct_flag (rtx); -static void remove_insn_ent (struct attr_value *, struct insn_ent *); -static void insert_insn_ent (struct attr_value *, struct insn_ent *); -static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int); -static rtx make_alternative_compare (int); -static int compute_alternative_mask (rtx, enum rtx_code); -static rtx evaluate_eq_attr (rtx, rtx, int, int); -static rtx simplify_and_tree (rtx, rtx *, int, int); -static rtx simplify_or_tree (rtx, rtx *, int, int); -static rtx simplify_test_exp (rtx, int, int); -static rtx simplify_test_exp_in_temp (rtx, int, int); -static void optimize_attrs (void); -static void gen_attr (rtx, int); -static int count_alternatives (rtx); -static int compares_alternatives_p (rtx); -static int contained_in_p (rtx, rtx); -static void gen_insn (rtx, int); -static void gen_delay (rtx, int); -static void write_test_expr (rtx, int); -static int max_attr_value (rtx, int*); -static int min_attr_value (rtx, int*); -static int or_attr_value (rtx, int*); -static void walk_attr_value (rtx); -static void write_attr_get (struct attr_desc *); -static rtx eliminate_known_true (rtx, rtx, int, int); -static void write_attr_set (struct attr_desc *, int, rtx, - const char *, const char *, rtx, - int, int); -static void write_insn_cases (struct insn_ent *, int); -static void write_attr_case (struct attr_desc *, struct attr_value *, - int, const char *, const char *, int, rtx); -static void write_attr_valueq (struct attr_desc *, const char *); -static void write_attr_value (struct attr_desc *, rtx); -static void write_upcase (const char *); -static void write_indent (int); -static void write_eligible_delay (const char *); -static int write_expr_attr_cache (rtx, struct attr_desc *); -static void write_const_num_delay_slots (void); -static char *next_comma_elt (const char **); +/* Forward declarations of functions used before their definitions, only. */ +static char *attr_string (const char *, int); +static char *attr_printf (unsigned int, const char *, ...) + ATTRIBUTE_PRINTF_2; +static rtx make_numeric_value (int); static struct attr_desc *find_attr (const char **, int); -static struct attr_value *find_most_used (struct attr_desc *); -static rtx attr_eq (const char *, const char *); -static const char *attr_numeral (int); -static int attr_equal_p (rtx, rtx); -static rtx attr_copy_rtx (rtx); -static int attr_rtx_cost (rtx); -static bool attr_alt_subset_p (rtx, rtx); +static rtx mk_attr_alt (int); +static char *next_comma_elt (const char **); +static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int); +static rtx copy_boolean (rtx); +static int compares_alternatives_p (rtx); +static void make_internal_attr (const char *, rtx, int); +static void insert_insn_ent (struct attr_value *, struct insn_ent *); +static void walk_attr_value (rtx); +static int max_attr_value (rtx, int*); +static int min_attr_value (rtx, int*); +static int or_attr_value (rtx, int*); +static rtx simplify_test_exp (rtx, int, int); +static rtx simplify_test_exp_in_temp (rtx, int, int); +static rtx copy_rtx_unchanging (rtx); +static bool attr_alt_subset_p (rtx, rtx); static bool attr_alt_subset_of_compl_p (rtx, rtx); -static rtx attr_alt_intersection (rtx, rtx); -static rtx attr_alt_union (rtx, rtx); -static rtx attr_alt_complement (rtx); -static rtx mk_attr_alt (int); +static void clear_struct_flag (rtx); +static void write_attr_valueq (struct attr_desc *, const char *); +static struct attr_value *find_most_used (struct attr_desc *); +static void write_attr_set (struct attr_desc *, int, rtx, + const char *, const char *, rtx, + int, int); +static void write_attr_case (struct attr_desc *, struct attr_value *, + int, const char *, const char *, int, rtx); +static void write_attr_value (struct attr_desc *, rtx); +static void write_upcase (const char *); +static void write_indent (int); +static rtx identity_fn (rtx); +static rtx zero_fn (rtx); +static rtx one_fn (rtx); +static rtx max_fn (rtx); +static rtx min_fn (rtx); #define oballoc(size) obstack_alloc (hash_obstack, size) @@ -368,7 +305,7 @@ struct attr_hash for each. */ #define RTL_HASH_SIZE 4093 -struct attr_hash *attr_hash_table[RTL_HASH_SIZE]; +static struct attr_hash *attr_hash_table[RTL_HASH_SIZE]; /* Here is how primitive or already-shared RTL's hash codes are made. */ @@ -603,7 +540,7 @@ attr_rtx (enum rtx_code code, ...) rtx attr_printf (len, format, [arg1, ..., argn]) */ -char * +static char * attr_printf (unsigned int len, const char *fmt, ...) { char str[256]; @@ -644,7 +581,7 @@ attr_string (const char *str, int len) /* Compute the hash code. */ hashcode = (len + 1) * 613 + (unsigned) str[0]; - for (i = 1; i <= len; i += 2) + for (i = 1; i < len; i += 2) hashcode = ((hashcode * 613) + (unsigned) str[i]); if (hashcode < 0) hashcode = -hashcode; @@ -773,7 +710,7 @@ attr_copy_rtx (rtx orig) Return the new expression, if any. */ -rtx +static rtx check_attr_test (rtx exp, int is_const, int lineno) { struct attr_desc *attr; @@ -3711,8 +3648,6 @@ write_attr_get (struct attr_desc *attr) /* Write out start of function, then all values with explicit `case' lines, then a `default', then the value with the most uses. */ - if (attr->static_p) - printf ("static "); if (!attr->is_numeric) printf ("enum attr_%s\n", attr->name); else @@ -4281,7 +4216,6 @@ find_attr (const char **name_p, int create) attr->name = DEF_ATTR_STRING (name); attr->first_value = attr->default_val = NULL; attr->is_numeric = attr->is_const = attr->is_special = 0; - attr->static_p = 0; attr->next = attrs[index]; attrs[index] = attr; @@ -4292,7 +4226,7 @@ find_attr (const char **name_p, int create) /* Create internal attribute with the given default value. */ -void +static void make_internal_attr (const char *name, rtx value, int special) { struct attr_desc *attr; @@ -4303,7 +4237,6 @@ make_internal_attr (const char *name, rtx value, int special) attr->is_numeric = 1; attr->is_const = 0; attr->is_special = (special & ATTR_SPECIAL) != 0; - attr->static_p = (special & ATTR_STATIC) != 0; attr->default_val = get_attr_value (value, attr, -2); } @@ -4328,7 +4261,7 @@ find_most_used (struct attr_desc *attr) /* Return (attr_value "n") */ -rtx +static rtx make_numeric_value (int n) { static rtx int_values[20]; @@ -4388,6 +4321,168 @@ write_const_num_delay_slots (void) printf (" }\n}\n\n"); } } + +/* Synthetic attributes used by insn-automata.c and the scheduler. + These are primarily concerned with (define_insn_reservation) + patterns. */ + +struct insn_reserv +{ + struct insn_reserv *next; + + const char *name; + int default_latency; + rtx condexp; + + /* Sequence number of this insn. */ + int insn_num; + + /* Whether a (define_bypass) construct names this insn in its + output list. */ + bool bypassed; +}; + +static struct insn_reserv *all_insn_reservs = 0; +static struct insn_reserv **last_insn_reserv_p = &all_insn_reservs; +static size_t n_insn_reservs; + +/* Store information from a DEFINE_INSN_RESERVATION for future + attribute generation. */ +static void +gen_insn_reserv (rtx def) +{ + struct insn_reserv *decl = oballoc (sizeof (struct insn_reserv)); + + decl->name = DEF_ATTR_STRING (XSTR (def, 0)); + decl->default_latency = XINT (def, 1); + decl->condexp = check_attr_test (XEXP (def, 2), 0, 0); + decl->insn_num = n_insn_reservs; + decl->bypassed = false; + decl->next = 0; + + *last_insn_reserv_p = decl; + last_insn_reserv_p = &decl->next; + n_insn_reservs++; +} + +/* Store information from a DEFINE_BYPASS for future attribute + generation. The only thing we care about is the list of output + insns, which will later be used to tag reservation structures with + a 'bypassed' bit. */ + +struct bypass_list +{ + struct bypass_list *next; + const char *insn; +}; + +static struct bypass_list *all_bypasses; +static size_t n_bypasses; + +static void +gen_bypass_1 (const char *s, size_t len) +{ + struct bypass_list *b; + + if (len == 0) + return; + + s = attr_string (s, len); + for (b = all_bypasses; b; b = b->next) + if (s == b->insn) + return; /* already got that one */ + + b = oballoc (sizeof (struct bypass_list)); + b->insn = s; + b->next = all_bypasses; + all_bypasses = b; + n_bypasses++; +} + +static void +gen_bypass (rtx def) +{ + const char *p, *base; + + for (p = base = XSTR (def, 1); *p; p++) + if (*p == ',') + { + gen_bypass_1 (base, p - base); + base = p + 1; + } + gen_bypass_1 (base, p - base); +} + +/* Find and mark all of the bypassed insns. */ +static void +process_bypasses (void) +{ + struct bypass_list *b; + struct insn_reserv *r; + + /* The reservation list is likely to be much longer than the bypass + list. */ + for (r = all_insn_reservs; r; r = r->next) + for (b = all_bypasses; b; b = b->next) + if (r->name == b->insn) + r->bypassed = true; +} + +/* Create all of the attributes that describe automaton properties. */ +static void +make_automaton_attrs (void) +{ + int i; + struct insn_reserv *decl; + rtx code_exp, lats_exp, byps_exp; + + if (n_insn_reservs == 0) + return; + + code_exp = rtx_alloc (COND); + lats_exp = rtx_alloc (COND); + + XVEC (code_exp, 0) = rtvec_alloc (n_insn_reservs * 2); + XVEC (lats_exp, 0) = rtvec_alloc (n_insn_reservs * 2); + + XEXP (code_exp, 1) = make_numeric_value (n_insn_reservs + 1); + XEXP (lats_exp, 1) = make_numeric_value (0); + + for (decl = all_insn_reservs, i = 0; + decl; + decl = decl->next, i += 2) + { + XVECEXP (code_exp, 0, i) = decl->condexp; + XVECEXP (lats_exp, 0, i) = decl->condexp; + + XVECEXP (code_exp, 0, i+1) = make_numeric_value (decl->insn_num); + XVECEXP (lats_exp, 0, i+1) = make_numeric_value (decl->default_latency); + } + + if (n_bypasses == 0) + byps_exp = make_numeric_value (0); + else + { + process_bypasses (); + + byps_exp = rtx_alloc (COND); + XVEC (byps_exp, 0) = rtvec_alloc (n_bypasses * 2); + XEXP (byps_exp, 1) = make_numeric_value (0); + for (decl = all_insn_reservs, i = 0; + decl; + decl = decl->next) + if (decl->bypassed) + { + XVECEXP (byps_exp, 0, i) = decl->condexp; + XVECEXP (byps_exp, 0, i+1) = make_numeric_value (1); + i += 2; + } + } + + make_internal_attr ("*internal_dfa_insn_code", code_exp, ATTR_NONE); + make_internal_attr ("*insn_default_latency", lats_exp, ATTR_NONE); + make_internal_attr ("*bypass_p", byps_exp, ATTR_NONE); +} int main (int argc, char **argv) @@ -4425,7 +4520,6 @@ from the machine description file `md'. */\n\n"); /* Read the machine description. */ - initiate_automaton_gen (argc, argv); while (1) { int lineno; @@ -4450,54 +4544,14 @@ from the machine description file `md'. */\n\n"); gen_delay (desc, lineno); break; - case DEFINE_CPU_UNIT: - gen_cpu_unit (desc); - break; - - case DEFINE_QUERY_CPU_UNIT: - gen_query_cpu_unit (desc); + case DEFINE_INSN_RESERVATION: + gen_insn_reserv (desc); break; case DEFINE_BYPASS: gen_bypass (desc); break; - case EXCLUSION_SET: - gen_excl_set (desc); - break; - - case PRESENCE_SET: - gen_presence_set (desc); - break; - - case FINAL_PRESENCE_SET: - gen_final_presence_set (desc); - break; - - case ABSENCE_SET: - gen_absence_set (desc); - break; - - case FINAL_ABSENCE_SET: - gen_final_absence_set (desc); - break; - - case DEFINE_AUTOMATON: - gen_automaton (desc); - break; - - case AUTOMATA_OPTION: - gen_automata_option (desc); - break; - - case DEFINE_RESERVATION: - gen_reserv (desc); - break; - - case DEFINE_INSN_RESERVATION: - gen_insn_reserv (desc); - break; - default: break; } @@ -4522,11 +4576,6 @@ from the machine description file `md'. */\n\n"); if (num_delays) expand_delays (); - /* Build DFA, output some functions and expand DFA information - to new attributes. */ - if (num_dfa_decls) - expand_automata (); - printf ("#include \"config.h\"\n"); printf ("#include \"system.h\"\n"); printf ("#include \"coretypes.h\"\n"); @@ -4557,6 +4606,9 @@ from the machine description file `md'. */\n\n"); if (id->insn_code >= 0) insn_n_alternatives[id->insn_code] = id->num_alternatives; + /* Construct extra attributes for automata. */ + make_automaton_attrs (); + /* Prepare to write out attribute subroutines by checking everything stored away and building the attribute cases. */ @@ -4587,18 +4639,7 @@ from the machine description file `md'. */\n\n"); for (attr = attrs[i]; attr; attr = attr->next) { if (! attr->is_special && ! attr->is_const) - { - int insn_alts_p; - - insn_alts_p - = (attr->name [0] == '*' - && strcmp (&attr->name[1], INSN_ALTS_FUNC_NAME) == 0); - if (insn_alts_p) - printf ("\n#if AUTOMATON_ALTS\n"); - write_attr_get (attr); - if (insn_alts_p) - printf ("#endif\n\n"); - } + write_attr_get (attr); } /* Write out delay eligibility information, if DEFINE_DELAY present. @@ -4613,11 +4654,6 @@ from the machine description file `md'. */\n\n"); write_eligible_delay ("annul_false"); } - /* Output code for pipeline hazards recognition based on DFA - (deterministic finite-state automata). */ - if (num_dfa_decls) - write_automata (); - /* Write out constant delay slot info. */ write_const_num_delay_slots (); |