From: Richard Sandiford Date: Thu, 11 Aug 2011 08:25:41 +0000 (+0000) Subject: md.texi (define_bypass): Say that the instruction names can be filename-style globs. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f9bf5a8e96ec9c6f04877a0c4922201d80b80a6e;p=gcc.git md.texi (define_bypass): Say that the instruction names can be filename-style globs. gcc/ * doc/md.texi (define_bypass): Say that the instruction names can be filename-style globs. * Makefile.in (FNMATCH_H): Define. (build/genattrtab.o, build/genautomata.o): Depend on $(FNMATCH_H). * genattrtab.c: Include fnmatch.h. (bypass_list): Change field name from "insn" to "pattern". (gen_bypass_1): Update accordingly. (process_bypasses): Use fnmatch to check for matches between insn reservations and define_bypasses. * genautomata.c: Include fnmatch.h. (bypass_decl): Rename in_insn_name and out_insn_name to in_pattern and out_pattern respectively. (gen_bypass, insert_bypass): Update accordingly. (for_each_matching_insn, process_bypass_2, process_bypass_1) (process_bypass): New functions. (process_decls): Use process_bypass. Update after field name changes. From-SVN: r177649 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0220752fed5..3b84e8bfe69 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2011-08-11 Richard Sandiford + + * doc/md.texi (define_bypass): Say that the instruction names can + be filename-style globs. + * Makefile.in (FNMATCH_H): Define. + (build/genattrtab.o, build/genautomata.o): Depend on $(FNMATCH_H). + * genattrtab.c: Include fnmatch.h. + (bypass_list): Change field name from "insn" to "pattern". + (gen_bypass_1): Update accordingly. + (process_bypasses): Use fnmatch to check for matches between + insn reservations and define_bypasses. + * genautomata.c: Include fnmatch.h. + (bypass_decl): Rename in_insn_name and out_insn_name to in_pattern + and out_pattern respectively. + (gen_bypass, insert_bypass): Update accordingly. + (for_each_matching_insn, process_bypass_2, process_bypass_1) + (process_bypass): New functions. + (process_decls): Use process_bypass. Update after field name changes. + 2011-08-11 Georg-Johann Lay PR target/49687 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 4e97ea536e1..b0874bcac64 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -444,6 +444,7 @@ PARTITION_H = $(srcdir)/../include/partition.h MD5_H = $(srcdir)/../include/md5.h DWARF2_H = $(srcdir)/../include/dwarf2.h XREGEX_H = $(srcdir)/../include/xregex.h +FNMATCH_H = $(srcdir)/../include/fnmatch.h # Linker plugin API headers LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h @@ -3939,10 +3940,10 @@ build/genattr-common.o : genattr-common.c $(RTL_BASE_H) $(BCONFIG_H) \ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h build/genattrtab.o : genattrtab.c $(RTL_BASE_H) $(OBSTACK_H) \ $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(GGC_H) \ - $(READ_MD_H) gensupport.h vecprim.h + $(READ_MD_H) gensupport.h vecprim.h $(FNMATCH_H) build/genautomata.o : genautomata.c $(RTL_BASE_H) $(OBSTACK_H) \ $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(VEC_H) \ - $(HASHTAB_H) gensupport.h + $(HASHTAB_H) gensupport.h $(FNMATCH_H) build/gencheck.o : gencheck.c all-tree.def $(BCONFIG_H) $(GTM_H) \ $(SYSTEM_H) coretypes.h $(lang_tree_files) gimple.def build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 3eae212ea3b..49dfda9db6c 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -7783,8 +7783,16 @@ latency time for given instruction pair. This is so called bypasses. @var{number} defines when the result generated by the instructions given in string @var{out_insn_names} will be ready for the -instructions given in string @var{in_insn_names}. The instructions in -the string are separated by commas. +instructions given in string @var{in_insn_names}. Each of these +strings is a comma-separated list of filename-style globs and +they refer to the names of @code{define_insn_reservation}s. +For example: +@smallexample +(define_bypass 1 "cpu1_load_*, cpu1_store_*" "cpu1_load_*") +@end smallexample +defines a bypass between instructions that start with +@samp{cpu1_load_} or @samp{cpu1_store_} and those that start with +@samp{cpu1_load_}. @var{guard} is an optional string giving the name of a C function which defines an additional guard for the bypass. The function will get the diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index e927ca2492c..a3da97868a9 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -114,6 +114,7 @@ along with GCC; see the file COPYING3. If not see #include "read-md.h" #include "gensupport.h" #include "vecprim.h" +#include "fnmatch.h" /* Flags for make_internal_attr's `special' parameter. */ #define ATTR_NONE 0 @@ -4553,7 +4554,7 @@ gen_insn_reserv (rtx def) struct bypass_list { struct bypass_list *next; - const char *insn; + const char *pattern; }; static struct bypass_list *all_bypasses; @@ -4569,11 +4570,11 @@ gen_bypass_1 (const char *s, size_t len) s = attr_string (s, len); for (b = all_bypasses; b; b = b->next) - if (s == b->insn) + if (s == b->pattern) return; /* already got that one */ b = oballoc (struct bypass_list); - b->insn = s; + b->pattern = s; b->next = all_bypasses; all_bypasses = b; n_bypasses++; @@ -4607,7 +4608,7 @@ process_bypasses (void) list. */ for (r = all_insn_reservs; r; r = r->next) for (b = all_bypasses; b; b = b->next) - if (r->name == b->insn) + if (fnmatch (b->pattern, r->name, 0) == 0) r->bypassed = true; } diff --git a/gcc/genautomata.c b/gcc/genautomata.c index 71809661592..e5260fa3c3d 100644 --- a/gcc/genautomata.c +++ b/gcc/genautomata.c @@ -117,6 +117,7 @@ along with GCC; see the file COPYING3. If not see #include #include "hashtab.h" #include "vec.h" +#include "fnmatch.h" #ifndef CHAR_BIT #define CHAR_BIT 8 @@ -384,8 +385,8 @@ struct unit_decl struct bypass_decl { int latency; - const char *out_insn_name; - const char *in_insn_name; + const char *out_pattern; + const char *in_pattern; const char *bypass_guard_name; /* The following fields are defined by checker. */ @@ -1306,17 +1307,17 @@ static void gen_bypass (rtx def) { decl_t decl; - char **out_insns; + char **out_patterns; int out_length; - char **in_insns; + char **in_patterns; int in_length; int i, j; - out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE); - if (out_insns == NULL) + out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE); + if (out_patterns == NULL) fatal ("invalid string `%s' in define_bypass", XSTR (def, 1)); - in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE); - if (in_insns == NULL) + in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE); + if (in_patterns == NULL) fatal ("invalid string `%s' in define_bypass", XSTR (def, 2)); for (i = 0; i < out_length; i++) for (j = 0; j < in_length; j++) @@ -1325,8 +1326,8 @@ gen_bypass (rtx def) decl->mode = dm_bypass; decl->pos = 0; DECL_BYPASS (decl)->latency = XINT (def, 0); - DECL_BYPASS (decl)->out_insn_name = out_insns [i]; - DECL_BYPASS (decl)->in_insn_name = in_insns [j]; + DECL_BYPASS (decl)->out_pattern = out_patterns[i]; + DECL_BYPASS (decl)->in_pattern = in_patterns[j]; DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3); VEC_safe_push (decl_t, heap, decls, decl); } @@ -2397,19 +2398,19 @@ insert_bypass (struct bypass_decl *bypass) { if (!w_flag) error ("the same bypass `%s - %s' is already defined", - bypass->out_insn_name, bypass->in_insn_name); + bypass->out_pattern, bypass->in_pattern); else warning ("the same bypass `%s - %s' is already defined", - bypass->out_insn_name, bypass->in_insn_name); + bypass->out_pattern, bypass->in_pattern); } else if (!w_flag) error ("the same bypass `%s - %s' (guard %s) is already defined", - bypass->out_insn_name, bypass->in_insn_name, + bypass->out_pattern, bypass->in_pattern, bypass->bypass_guard_name); else warning ("the same bypass `%s - %s' (guard %s) is already defined", - bypass->out_insn_name, bypass->in_insn_name, + bypass->out_pattern, bypass->in_pattern, bypass->bypass_guard_name); return; } @@ -2434,6 +2435,92 @@ insert_bypass (struct bypass_decl *bypass) } } +/* BYPASS is a define_bypass decl that includes glob pattern PATTERN. + Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */ + +static void +for_each_matching_insn (decl_t bypass, const char *pattern, + void (*fn) (decl_t, decl_t, void *), void *data) +{ + decl_t insn_reserv; + bool matched_p; + int i; + + matched_p = false; + if (strpbrk (pattern, "*?[")) + for (i = 0; i < description->decls_num; i++) + { + insn_reserv = description->decls[i]; + if (insn_reserv->mode == dm_insn_reserv + && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0) + { + fn (bypass, insn_reserv, data); + matched_p = true; + } + } + else + { + insn_reserv = find_insn_decl (pattern); + if (insn_reserv) + { + fn (bypass, insn_reserv, data); + matched_p = true; + } + } + if (!matched_p) + error ("there is no insn reservation that matches `%s'", pattern); +} + +/* A subroutine of process_bypass that is called for each pair + of matching instructions. OUT_INSN_RESERV is the output + instruction and DATA is the input instruction. */ + +static void +process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data) +{ + struct bypass_decl *bypass; + decl_t in_insn_reserv; + + in_insn_reserv = (decl_t) data; + if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name, + DECL_BYPASS (model)->in_pattern) == 0 + && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name, + DECL_BYPASS (model)->out_pattern) == 0) + bypass = DECL_BYPASS (model); + else + { + bypass = XCNEW (struct bypass_decl); + bypass->latency = DECL_BYPASS (model)->latency; + bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name; + bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name; + bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name; + } + bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv); + bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv); + insert_bypass (bypass); +} + +/* A subroutine of process_bypass that is called for each input + instruction IN_INSN_RESERV. */ + +static void +process_bypass_1 (decl_t bypass, decl_t in_insn_reserv, + void *data ATTRIBUTE_UNUSED) +{ + for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern, + process_bypass_2, in_insn_reserv); +} + +/* Process define_bypass decl BYPASS, inserting a bypass for each specific + pair of insn reservations. */ + +static void +process_bypass (decl_t bypass) +{ + for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern, + process_bypass_1, NULL); +} + /* The function processes pipeline description declarations, checks their correctness, and forms exclusion/presence/absence sets. */ static void @@ -2442,8 +2529,6 @@ process_decls (void) decl_t decl; decl_t automaton_decl; decl_t decl_in_table; - decl_t out_insn_reserv; - decl_t in_insn_reserv; int automaton_presence; int i; @@ -2489,8 +2574,8 @@ process_decls (void) { if (DECL_BYPASS (decl)->latency < 0) error ("define_bypass `%s - %s' has negative latency time", - DECL_BYPASS (decl)->out_insn_name, - DECL_BYPASS (decl)->in_insn_name); + DECL_BYPASS (decl)->out_pattern, + DECL_BYPASS (decl)->in_pattern); } else if (decl->mode == dm_unit || decl->mode == dm_reserv) { @@ -2551,24 +2636,7 @@ process_decls (void) { decl = description->decls [i]; if (decl->mode == dm_bypass) - { - out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name); - in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name); - if (out_insn_reserv == NULL) - error ("there is no insn reservation `%s'", - DECL_BYPASS (decl)->out_insn_name); - else if (in_insn_reserv == NULL) - error ("there is no insn reservation `%s'", - DECL_BYPASS (decl)->in_insn_name); - else - { - DECL_BYPASS (decl)->out_insn_reserv - = DECL_INSN_RESERV (out_insn_reserv); - DECL_BYPASS (decl)->in_insn_reserv - = DECL_INSN_RESERV (in_insn_reserv); - insert_bypass (DECL_BYPASS (decl)); - } - } + process_bypass (decl); } /* Check exclusion set declarations and form exclusion sets. */ @@ -8757,8 +8825,8 @@ output_description (void) else if (decl->mode == dm_bypass) fprintf (output_description_file, "bypass %d %s %s\n", DECL_BYPASS (decl)->latency, - DECL_BYPASS (decl)->out_insn_name, - DECL_BYPASS (decl)->in_insn_name); + DECL_BYPASS (decl)->out_pattern, + DECL_BYPASS (decl)->in_pattern); } fprintf (output_description_file, "\n\f\n"); }