diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/Makefile.in | 39 | ||||
-rw-r--r-- | gcc/genemit.c | 46 | ||||
-rw-r--r-- | gcc/genopinit.c | 240 | ||||
-rw-r--r-- | gcc/gensupport.c | 158 | ||||
-rw-r--r-- | gcc/gensupport.h | 86 | ||||
-rw-r--r-- | gcc/optabs.def | 25 |
7 files changed, 365 insertions, 261 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8d30d04..09bc243 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2015-12-02 Richard Sandiford <richard.sandiford@arm.com> + + * Makefile.in (GENSUPPORT_H): New macro. + (build/gensupport.o, build/read-rtl.o, build/genattr.o) + (build/genattr-common.o, build/genattrtab.o, build/genautomata.o) + (build/gencodes.o, build/genconditions.o, build/genconfig.o) + (build/genconstants.o, build/genextract.o, build/genflags.o) + (build/gentarget-def.o): Use it. + (build/genemit.o): Likewise. Depend on internal-fn.def. + * genopinit.c: Move block comment to optabs.def. + (optab_tag, optab_def): Move to gensupport.h + (pattern): Likewise, renaming to optab_pattern. + (match_pattern): Move to gensupport.c + (gen_insn): Use find_optab. + (patterns, pattern_cmp): Replace pattern with optab_pattern. + (main): Likewise. Use num_optabs. + * optabs.def: Add comment that was previously in genopinit.c. + * gensupport.h (optab_tag): Moved from genopinit.c + (optab_def): Likewise, expanding commentary. + (optab_pattern): Likewise, after renaming from pattern. + (optabs, num_optabs, find_optab): Declare. + * gensupport.c (optabs): Moved from genopinit.c. + (num_optabs): New variable. + (match_pattern): Moved from genopinit.c. + (find_optab): New function, extracted from genopinit.c:gen_insn. + * genemit.c (nofail_optabs): New variable. + (emit_c_code): New function. + (gen_expand): Check whether the instruction is an optab that isn't + allowed to fail. Call emit_c_code. + (gen_split): Call emit_c_code here too. + (main): Initialize nofail_optabs. Don't emit FAIL and DONE here. + 2015-12-02 Andreas Krebbel <krebbel@linux.vnet.ibm.com> * config/s390/predicates.md (const_mask_operand): New predicate. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bee2879..d2d09f6 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -978,6 +978,7 @@ GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h plugin.def \ PLUGIN_H = plugin.h $(GCC_PLUGIN_H) PLUGIN_VERSION_H = plugin-version.h configargs.h CONTEXT_H = context.h +GENSUPPORT_H = gensupport.h read-md.h optabs.def # # Now figure out from those variables how to compile and link. @@ -2476,7 +2477,7 @@ build/version.o: version.c version.h \ build/errors.o : errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h build/gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \ $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h $(HASHTAB_H) \ - $(READ_MD_H) gensupport.h + $(READ_MD_H) $(GENSUPPORT_H) build/ggc-none.o : ggc-none.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \ $(GGC_H) build/min-insn-modes.o : min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H) \ @@ -2487,7 +2488,7 @@ build/read-md.o: read-md.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \ $(HASHTAB_H) errors.h $(READ_MD_H) build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \ $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) $(READ_MD_H) \ - gensupport.h + $(GENSUPPORT_H) build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) \ $(RTL_H) $(GGC_H) errors.h build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H) \ @@ -2509,38 +2510,38 @@ build/gencondmd.o : \ # ...these are the programs themselves. build/genattr.o : genattr.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) 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 + $(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 $(FNMATCH_H) + $(READ_MD_H) $(GENSUPPORT_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 $(FNMATCH_H) + $(HASHTAB_H) $(GENSUPPORT_H) $(FNMATCH_H) build/gencheck.o : gencheck.c all-tree.def $(BCONFIG_H) $(GTM_H) \ $(SYSTEM_H) coretypes.h tree.def c-family/c-common.def \ $(lang_tree_files) gimple.def build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H) build/gencodes.o : gencodes.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h gensupport.h + coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) build/genconditions.o : genconditions.c $(RTL_BASE_H) $(BCONFIG_H) \ $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(HASHTAB_H) $(READ_MD_H) \ - gensupport.h + $(GENSUPPORT_H) build/genconfig.o : genconfig.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h gensupport.h + coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) build/genconstants.o : genconstants.c $(BCONFIG_H) $(SYSTEM_H) \ coretypes.h errors.h $(READ_MD_H) build/genemit.o : genemit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) internal-fn.def build/genenums.o : genenums.c $(BCONFIG_H) $(SYSTEM_H) \ coretypes.h errors.h $(READ_MD_H) build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H) \ - $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \ - $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) build/gentarget-def.o : gentarget-def.c $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) gensupport.h \ + coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \ $(HASH_TABLE_H) target-insns.def build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def @@ -2582,20 +2583,20 @@ build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h \ build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h \ $(HASHTAB_H) machmode.def $(extra_modes_file) build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h gensupport.h optabs.def + coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def build/genoutput.o : genoutput.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h gensupport.h toplev.h $(DIAGNOSTIC_CORE_H) + coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h $(DIAGNOSTIC_CORE_H) build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h $(OBSTACK_H) + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H) build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h \ + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \ $(HASH_TABLE_H) inchash.h build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF) \ $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \ - coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h + coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) build/genmatch.o : genmatch.c $(BCONFIG_H) $(SYSTEM_H) \ coretypes.h errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \ tree.def builtins.def internal-fn.def diff --git a/gcc/genemit.c b/gcc/genemit.c index e92f757..cd85a80 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -51,6 +51,8 @@ struct clobber_ent static void output_peephole2_scratches (rtx); +/* True for <X>_optab if that optab isn't allowed to fail. */ +static bool nofail_optabs[NUM_OPTABS]; static void print_code (RTX_CODE code) @@ -285,6 +287,28 @@ gen_emit_seq (rtvec vec, char *used) } } +/* Emit the given C code to the output file. The code is allowed to + fail if CAN_FAIL_P. NAME describes what we're generating, + for use in error messages. */ + +static void +emit_c_code (const char *code, bool can_fail_p, const char *name) +{ + if (can_fail_p) + printf ("#define FAIL return (end_sequence (), _val)\n"); + else + printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" + " (void)0\n", name); + printf ("#define DONE return (_val = get_insns ()," + "end_sequence (), _val)\n"); + + print_md_ptr_loc (code); + printf ("%s\n", code); + + printf ("#undef DONE\n"); + printf ("#undef FAIL\n"); +} + /* Generate the `gen_...' function for a DEFINE_INSN. */ static void @@ -478,8 +502,15 @@ gen_expand (md_rtx_info *info) /* Output the special code to be executed before the sequence is generated. */ - print_md_ptr_loc (XSTR (expand, 3)); - printf ("%s\n", XSTR (expand, 3)); + optab_pattern p; + bool can_fail_p = true; + if (find_optab (&p, XSTR (expand, 0))) + { + gcc_assert (p.op < NUM_OPTABS); + if (nofail_optabs[p.op]) + can_fail_p = false; + } + emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); /* Output code to copy the arguments back out of `operands' (unless we aren't going to use them at all). */ @@ -569,10 +600,7 @@ gen_split (md_rtx_info *info) before the actual construction. */ if (XSTR (split, 3)) - { - print_md_ptr_loc (XSTR (split, 3)); - printf ("%s\n", XSTR (split, 3)); - } + emit_c_code (XSTR (split, 3), true, name); /* Output code to copy the arguments back out of `operands' */ for (i = 0; i < stats.num_operand_vars; i++) @@ -724,6 +752,10 @@ main (int argc, char **argv) if (!init_rtx_reader_args (argc, argv)) return (FATAL_EXIT_CODE); +#define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \ + nofail_optabs[OPTAB##_optab] = true; +#include "internal-fn.def" + /* Assign sequential codes to all entries in the machine description in parallel with the tables in insn-output.c. */ @@ -764,8 +796,6 @@ from the machine description file `md'. */\n\n"); printf ("#include \"ggc.h\"\n"); printf ("#include \"dumpfile.h\"\n"); printf ("#include \"target.h\"\n\n"); - printf ("#define FAIL return (end_sequence (), _val)\n"); - printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n"); /* Read the machine description. */ diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 167815d..3b91112 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -35,246 +35,22 @@ static const char * const rtx_upname[] = { #undef DEF_RTL_EXPR - -/* The entries in optabs.def are categorized: - C: A "conversion" optab, which uses two modes; has libcall data. - N: A "normal" optab, which uses one mode; has libcall data. - D: A "direct" optab, which uses one mode; does not have libcall data. - V: An "oVerflow" optab. Like N, but does not record its code in - code_to_optab. - - CX, NX, VX: An extra pattern entry for a conversion or normal optab. - - These patterns may be present in the MD file with names that contain - the mode(s) used and the name of the operation. This array contains - a list of optabs that need to be initialized. Within each name, - $a and $b are used to match a short mode name (the part of the mode - name not including `mode' and converted to lower-case). - - $I means that only full integer modes should be considered for the - next mode, and $F means that only float modes should be considered. - $P means that both full and partial integer modes should be considered. - $Q means that only fixed-point modes should be considered. - - The pattern may be NULL if the optab exists only for the libcalls - that we plan to attach to it, and there are no named patterns in - the md files. */ - -#define OPTAB_CL(name, pat, c, b, l) name, -#define OPTAB_CX(name, pat) -#define OPTAB_CD(name, pat) name, -#define OPTAB_NL(name, pat, c, b, s, l) name, -#define OPTAB_NC(name, pat, c) name, -#define OPTAB_NX(name, pat) -#define OPTAB_VL(name, pat, c, b, s, l) name, -#define OPTAB_VC(name, pat, c) name, -#define OPTAB_VX(name, pat) -#define OPTAB_DC(name, pat, c) name, -#define OPTAB_D(name, pat) name, - -typedef enum optab_tag { - unknown_optab, -#include "optabs.def" - NUM_OPTABS -} optab; - -#undef OPTAB_CL -#undef OPTAB_CX -#undef OPTAB_CD -#undef OPTAB_NL -#undef OPTAB_NC -#undef OPTAB_NX -#undef OPTAB_VL -#undef OPTAB_VC -#undef OPTAB_VX -#undef OPTAB_DC -#undef OPTAB_D - -#define NS "NULL" -#define ZS "'\\0'" -#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 }, -#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 }, -#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 }, -#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 }, -#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 }, -#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, -#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 }, -#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 }, -#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, -#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 }, -#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 }, - -struct optab_def -{ - const char *name; - const char *pattern; - const char *base; - const char *suffix; - const char *libcall; - unsigned int op; - enum rtx_code fcode; - enum rtx_code rcode; - unsigned int kind; -}; - -static optab_def optabs[] = { - { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 }, -#include "optabs.def" -}; - -#undef OPTAB_CL -#undef OPTAB_CX -#undef OPTAB_CD -#undef OPTAB_NL -#undef OPTAB_NC -#undef OPTAB_NX -#undef OPTAB_VL -#undef OPTAB_VC -#undef OPTAB_VX -#undef OPTAB_DC -#undef OPTAB_D - /* Vector in which to collect insns that match. */ - -struct pattern -{ - const char *name; - unsigned int op; - unsigned int m1, m2; - unsigned int sort_num; -}; - - -static vec<pattern> patterns; - -static bool -match_pattern (pattern *p, const char *name, const char *pat) -{ - bool force_float = false; - bool force_int = false; - bool force_partial_int = false; - bool force_fixed = false; - - if (pat == NULL) - return false; - for (; ; ++pat) - { - if (*pat != '$') - { - if (*pat != *name++) - return false; - if (*pat == '\0') - return true; - continue; - } - switch (*++pat) - { - case 'I': - force_int = 1; - break; - case 'P': - force_partial_int = 1; - break; - case 'F': - force_float = 1; - break; - case 'Q': - force_fixed = 1; - break; - - case 'a': - case 'b': - { - int i; - - /* This loop will stop at the first prefix match, so - look through the modes in reverse order, in case - there are extra CC modes and CC is a prefix of the - CC modes (as it should be). */ - for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--) - { - const char *p, *q; - for (p = GET_MODE_NAME (i), q = name; *p; p++, q++) - if (TOLOWER (*p) != *q) - break; - if (*p == 0 - && (! force_int || mode_class[i] == MODE_INT - || mode_class[i] == MODE_VECTOR_INT) - && (! force_partial_int - || mode_class[i] == MODE_INT - || mode_class[i] == MODE_PARTIAL_INT - || mode_class[i] == MODE_VECTOR_INT) - && (! force_float - || mode_class[i] == MODE_FLOAT - || mode_class[i] == MODE_DECIMAL_FLOAT - || mode_class[i] == MODE_COMPLEX_FLOAT - || mode_class[i] == MODE_VECTOR_FLOAT) - && (! force_fixed - || mode_class[i] == MODE_FRACT - || mode_class[i] == MODE_UFRACT - || mode_class[i] == MODE_ACCUM - || mode_class[i] == MODE_UACCUM - || mode_class[i] == MODE_VECTOR_FRACT - || mode_class[i] == MODE_VECTOR_UFRACT - || mode_class[i] == MODE_VECTOR_ACCUM - || mode_class[i] == MODE_VECTOR_UACCUM)) - break; - } - - if (i < 0) - return false; - name += strlen (GET_MODE_NAME (i)); - if (*pat == 'a') - p->m1 = i; - else - p->m2 = i; - - force_int = false; - force_partial_int = false; - force_float = false; - force_fixed = false; - } - break; - - default: - gcc_unreachable (); - } - } -} +static vec<optab_pattern> patterns; static void gen_insn (md_rtx_info *info) { - rtx insn = info->def; - const char *name = XSTR (insn, 0); - pattern p; - unsigned pindex; - - /* Don't mention "unnamed" instructions. */ - if (*name == 0 || *name == '*') - return; - p.name = name; - - /* See if NAME matches one of the patterns we have for the optabs - we know about. */ - for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++) - { - p.m1 = p.m2 = 0; - if (match_pattern (&p, name, optabs[pindex].pattern)) - { - p.op = optabs[pindex].op; - p.sort_num = (p.op << 16) | (p.m2 << 8) | p.m1; - patterns.safe_push (p); - return; - } - } + optab_pattern p; + if (find_optab (&p, XSTR (info->def, 0))) + patterns.safe_push (p); } static int pattern_cmp (const void *va, const void *vb) { - const pattern *a = (const pattern *)va; - const pattern *b = (const pattern *)vb; + const optab_pattern *a = (const optab_pattern *)va; + const optab_pattern *b = (const optab_pattern *)vb; return a->sort_num - b->sort_num; } @@ -333,7 +109,7 @@ main (int argc, char **argv) { FILE *h_file, *s_file; unsigned int i, j, n, last_kind[5]; - pattern *p; + optab_pattern *p; progname = "genopinit"; @@ -365,7 +141,7 @@ main (int argc, char **argv) /* Now that we've handled the "extra" patterns, eliminate them from the optabs array. That way they don't get in the way below. */ - n = ARRAY_SIZE (optabs); + n = num_optabs; for (i = 0; i < n; ) if (optabs[i].base == NULL) optabs[i] = optabs[--n]; diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 484ead2..7969060 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -3061,3 +3061,161 @@ needs_barrier_p (rtx x) && GET_CODE (SET_DEST (x)) == PC && GET_CODE (SET_SRC (x)) == LABEL_REF); } + +#define NS "NULL" +#define ZS "'\\0'" +#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 }, +#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 }, +#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 }, +#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 }, +#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 }, +#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, +#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 }, +#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 }, +#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, +#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 }, +#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 }, + +/* An array of all optabs. Note that the same optab can appear more + than once, with a different pattern. */ +optab_def optabs[] = { + { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 }, +#include "optabs.def" +}; + +/* The number of entries in optabs[]. */ +unsigned int num_optabs = ARRAY_SIZE (optabs); + +#undef OPTAB_CL +#undef OPTAB_CX +#undef OPTAB_CD +#undef OPTAB_NL +#undef OPTAB_NC +#undef OPTAB_NX +#undef OPTAB_VL +#undef OPTAB_VC +#undef OPTAB_VX +#undef OPTAB_DC +#undef OPTAB_D + +/* Return true if instruction NAME matches pattern PAT, storing information + about the match in P if so. */ + +static bool +match_pattern (optab_pattern *p, const char *name, const char *pat) +{ + bool force_float = false; + bool force_int = false; + bool force_partial_int = false; + bool force_fixed = false; + + if (pat == NULL) + return false; + for (; ; ++pat) + { + if (*pat != '$') + { + if (*pat != *name++) + return false; + if (*pat == '\0') + return true; + continue; + } + switch (*++pat) + { + case 'I': + force_int = 1; + break; + case 'P': + force_partial_int = 1; + break; + case 'F': + force_float = 1; + break; + case 'Q': + force_fixed = 1; + break; + + case 'a': + case 'b': + { + int i; + + /* This loop will stop at the first prefix match, so + look through the modes in reverse order, in case + there are extra CC modes and CC is a prefix of the + CC modes (as it should be). */ + for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--) + { + const char *p, *q; + for (p = GET_MODE_NAME (i), q = name; *p; p++, q++) + if (TOLOWER (*p) != *q) + break; + if (*p == 0 + && (! force_int || mode_class[i] == MODE_INT + || mode_class[i] == MODE_VECTOR_INT) + && (! force_partial_int + || mode_class[i] == MODE_INT + || mode_class[i] == MODE_PARTIAL_INT + || mode_class[i] == MODE_VECTOR_INT) + && (! force_float + || mode_class[i] == MODE_FLOAT + || mode_class[i] == MODE_DECIMAL_FLOAT + || mode_class[i] == MODE_COMPLEX_FLOAT + || mode_class[i] == MODE_VECTOR_FLOAT) + && (! force_fixed + || mode_class[i] == MODE_FRACT + || mode_class[i] == MODE_UFRACT + || mode_class[i] == MODE_ACCUM + || mode_class[i] == MODE_UACCUM + || mode_class[i] == MODE_VECTOR_FRACT + || mode_class[i] == MODE_VECTOR_UFRACT + || mode_class[i] == MODE_VECTOR_ACCUM + || mode_class[i] == MODE_VECTOR_UACCUM)) + break; + } + + if (i < 0) + return false; + name += strlen (GET_MODE_NAME (i)); + if (*pat == 'a') + p->m1 = i; + else + p->m2 = i; + + force_int = false; + force_partial_int = false; + force_float = false; + force_fixed = false; + } + break; + + default: + gcc_unreachable (); + } + } +} + +/* Return true if NAME is the name of an optab, describing it in P if so. */ + +bool +find_optab (optab_pattern *p, const char *name) +{ + if (*name == 0 || *name == '*') + return false; + + /* See if NAME matches one of the patterns we have for the optabs + we know about. */ + for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++) + { + p->m1 = p->m2 = 0; + if (match_pattern (p, name, optabs[pindex].pattern)) + { + p->name = name; + p->op = optabs[pindex].op; + p->sort_num = (p->op << 16) | (p->m2 << 8) | p->m1; + return true; + } + } + return false; +} diff --git a/gcc/gensupport.h b/gcc/gensupport.h index 0199e39..456efa0 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -39,6 +39,91 @@ struct md_rtx_info { int index; }; +#define OPTAB_CL(name, pat, c, b, l) name, +#define OPTAB_CX(name, pat) +#define OPTAB_CD(name, pat) name, +#define OPTAB_NL(name, pat, c, b, s, l) name, +#define OPTAB_NC(name, pat, c) name, +#define OPTAB_NX(name, pat) +#define OPTAB_VL(name, pat, c, b, s, l) name, +#define OPTAB_VC(name, pat, c) name, +#define OPTAB_VX(name, pat) +#define OPTAB_DC(name, pat, c) name, +#define OPTAB_D(name, pat) name, + +/* Enumerates all optabs. */ +typedef enum optab_tag { + unknown_optab, +#include "optabs.def" + NUM_OPTABS +} optab; + +#undef OPTAB_CL +#undef OPTAB_CX +#undef OPTAB_CD +#undef OPTAB_NL +#undef OPTAB_NC +#undef OPTAB_NX +#undef OPTAB_VL +#undef OPTAB_VC +#undef OPTAB_VX +#undef OPTAB_DC +#undef OPTAB_D + +/* Describes one entry in optabs.def. */ +struct optab_def +{ + /* The name of the optab (e.g. "add_optab"). */ + const char *name; + + /* The pattern that matching define_expands and define_insns have. + See the comment at the head of optabs.def for details. */ + const char *pattern; + + /* The initializers (in the form of C code) for the libcall_basename, + libcall_suffix and libcall_gen fields of (convert_)optab_libcall_d. */ + const char *base; + const char *suffix; + const char *libcall; + + /* The optab's enum value. */ + unsigned int op; + + /* The value returned by optab_to_code (OP). */ + enum rtx_code fcode; + + /* CODE if code_to_optab (CODE) should return OP, otherwise UNKNOWN. */ + enum rtx_code rcode; + + /* 1: conversion optabs with libcall data, + 2: conversion optabs without libcall data, + 3: non-conversion optabs with libcall data ("normal" and "overflow" + optabs in the optabs.def comment) + 4: non-conversion optabs without libcall data ("direct" optabs). */ + unsigned int kind; +}; + +extern optab_def optabs[]; +extern unsigned int num_optabs; + +/* Information about an instruction name that matches an optab pattern. */ +struct optab_pattern +{ + /* The name of the instruction. */ + const char *name; + + /* The matching optab. */ + unsigned int op; + + /* The optab modes. M2 is only significant for conversion optabs; + it is zero otherwise. */ + unsigned int m1, m2; + + /* An index that provides a lexicographical sort of (OP, M2, M1). + Used by genopinit.c. */ + unsigned int sort_num; +}; + extern rtx add_implicit_parallel (rtvec); extern bool init_rtx_reader_args_cb (int, char **, bool (*)(const char *)); extern bool init_rtx_reader_args (int, char **); @@ -135,5 +220,6 @@ extern void compute_test_codes (rtx, file_location, char *); extern file_location get_file_location (rtx); extern const char *get_emit_function (rtx); extern bool needs_barrier_p (rtx); +extern bool find_optab (optab_pattern *, const char *); #endif /* GCC_GENSUPPORT_H */ diff --git a/gcc/optabs.def b/gcc/optabs.def index 20e4225..8feb394 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -17,8 +17,29 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -/* Entries here are categorized C, D, N, V. See genopinit.c for details - on the meaning of the categories and for the pattern dollar codes. */ +/* The entries in optabs.def are categorized: + C: A "conversion" optab, which uses two modes; has libcall data. + N: A "normal" optab, which uses one mode; has libcall data. + D: A "direct" optab, which uses one mode; does not have libcall data. + V: An "oVerflow" optab. Like N, but does not record its code in + code_to_optab. + + CX, NX, VX: An extra pattern entry for a conversion or normal optab. + + These patterns may be present in the MD file with names that contain + the mode(s) used and the name of the operation. This array contains + a list of optabs that need to be initialized. Within each name, + $a and $b are used to match a short mode name (the part of the mode + name not including `mode' and converted to lower-case). + + $I means that only full integer modes should be considered for the + next mode, and $F means that only float modes should be considered. + $P means that both full and partial integer modes should be considered. + $Q means that only fixed-point modes should be considered. + + The pattern may be NULL if the optab exists only for the libcalls + that we plan to attach to it, and there are no named patterns in + the md files. */ /* The extension libcalls are used for float extension. */ OPTAB_CL(sext_optab, "extend$b$a2", SIGN_EXTEND, "extend", gen_extend_conv_libfunc) |