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
This commit is contained in:
parent
7ece388150
commit
f9bf5a8e96
|
@ -1,3 +1,22 @@
|
|||
2011-08-11 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* 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 <avr@gjlay.de>
|
||||
|
||||
PR target/49687
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include <math.h>
|
||||
#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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue