[patch] e500 port
Zack Weinberg
zack@codesourcery.com
Wed Jul 24 11:29:00 GMT 2002
On Wed, Jul 24, 2002 at 12:38:20PM -0400, David Edelsohn wrote:
> Where could we short-circuit the TARGET_FPRS, TARGET_SPE, and
> TARGET_ISEL macros the same way that we short-circuit DEFAULT_ABI. This
> would allow GCC to optimize away the tests and the resulting dead code
> when an OS will never run on e500.
>
> Is e500 suppose to run anything other than SVR4 and eABI? It
> definitely will not run AIX or Darwin or 64-bit Linux. I am not sure
> about Linux and FreeBSD. I am trying to minimize the performance impact
> of this change for other PowerPC targets. Too bad that MD files do not
> have conditional includes.
Maybe I should dust off the concept patch I did last year to elide
patterns from insn-*.c when the compiler can prove that the C
condition will always be false. It made a nice dent in the size of
the x86 cc1 binary, and looking at rs6000.md I think it will help
there too.
I'll append what I have for reactions. It would certainly require
modification to work with the modern tree.
zw
===================================================================
Index: Makefile.in
--- Makefile.in 1 Jul 2002 16:13:01 -0000 1.907
+++ Makefile.in 2 Jul 2002 23:45:11 -0000
@@ -548,6 +548,7 @@ HOOKS_H = hooks.h
LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
TARGET_DEF_H = target-def.h $(HOOKS_H)
TM_P_H = tm_p.h $(tm_p_file_list) tm-preds.h
+GTM_P_H = tm_p.h $(tm_p_file_list)
MACHMODE_H = machmode.h machmode.def @extra_modes_file@
RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
@@ -622,6 +623,7 @@ HOST_LIBS = $(BUILD_LIBIBERTY)
HOST_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \
$(BUILD_PREFIX)ggc-none.o gensupport.o
+HOST_SUPPORT = gensupport.o insn-conditions.o
HOST_PRINT = $(BUILD_PREFIX)print-rtl.o
HOST_ERRORS = $(BUILD_PREFIX)errors.o
@@ -747,13 +749,13 @@ GEN= genemit$(build_exeext) genoutput$(b
genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
genconfig$(build_exeext) genpeep$(build_exeext) gengenrtl$(build_exeext) \
gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) \
- gengtype$(build_exeext)
+ gengtype$(build_exeext) genconditions$(build_exeext)
# Files to be copied away after each stage in building.
STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
insn-attr.h insn-attrtab.c insn-opinit.c insn-constants.h tm-preds.h \
- tree-check.h \
+ tree-check.h insn-conditions.c \
s-flags s-config s-codes s-mlib s-under s-genrtl s-gtype \
s-output s-recog s-emit s-extract s-peep s-check \
s-attr s-attrtab s-opinit s-preds s-constants s-crt0 \
@@ -762,7 +764,7 @@ STAGESTUFF = *$(objext) insn-flags.h ins
genconfig$(build_exeext) genpeep$(build_exeext) genattrtab$(build_exeext) \
genattr$(build_exeext) genopinit$(build_exeext) gengenrtl$(build_exeext) \
gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) \
- gengtype$(build_exeext) \
+ gengtype$(build_exeext) genconditions$(build_exeext) \
genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c \
xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
$(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) cc1obj$(exeext) \
@@ -1396,7 +1398,7 @@ rtl-error.o: rtl-error.c system.h $(RTL_
rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
+print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) \
hard-reg-set.h $(BASIC_BLOCK_H)
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
@@ -1683,6 +1685,17 @@ s-config : $(md_file) genconfig$(build_e
$(SHELL) $(srcdir)/move-if-change tmp-config.h insn-config.h
$(STAMP) s-config
+insn-conditions.c: s-conditions ; @true
+s-conditions : $(md_file) genconditions$(build_exeext) $(srcdir)/move-if-change
+ ./genconditions$(build_exeext) $(md_file) > tmp-conditions.c
+ $(SHELL) $(srcdir)/move-if-change tmp-conditions.c insn-conditions.c
+ $(STAMP) s-conditions
+
+insn-conditions.o : insn-conditions.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) \
+ $(GTM_P_H) $(REGS_H) function.h $(RECOG_H) real.h output.h flags.h \
+ hard-reg-set.h resource.h toplev.h reload.h gensupport.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) insn-conditions.c
+
insn-flags.h: s-flags ; @true
s-flags : $(md_file) genflags$(build_exeext) $(srcdir)/move-if-change
./genflags$(build_exeext) $(md_file) > tmp-flags.h
@@ -1860,23 +1873,23 @@ gensupport.o: gensupport.c $(RTL_H) $(OB
genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genconfig.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genconfig.o : genconfig.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c $(OUTPUT_OPTION)
-genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genflags.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genflags.o : genflags.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c $(OUTPUT_OPTION)
-gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ gencodes.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
gencodes.o : gencodes.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
@@ -1891,55 +1904,56 @@ genconstants.o : genconstants.c $(RTL_H)
genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genemit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genemit.o : genemit.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c $(OUTPUT_OPTION)
-genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genopinit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genopinit.o : genopinit.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genopinit.c $(OUTPUT_OPTION)
-genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genrecog.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genrecog.o : genrecog.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c $(OUTPUT_OPTION)
-genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genextract.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genextract.o : genextract.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) insn-config.h errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c $(OUTPUT_OPTION)
-genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genpeep.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genpeep.o : genpeep.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c $(OUTPUT_OPTION)
-genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genattr.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genattr.o : genattr.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c $(OUTPUT_OPTION)
genattrtab$(build_exeext) : genattrtab.o genautomata.o \
- $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) $(HOST_LIBDEPS)
+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) \
+ $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
genattrtab.o genautomata.o \
- $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) \
- $(HOST_LIBS) -lm
+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) \
+ $(HOST_VARRAY) $(HOST_LIBS) -lm
genattrtab.o : genattrtab.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h $(GGC_H) gensupport.h genattrtab.h
@@ -1949,9 +1963,9 @@ genautomata.o : genautomata.c $(RTL_H) $
$(SYSTEM_H) errors.h varray.h genattrtab.h $(HASHTAB_H)
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genautomata.c $(OUTPUT_OPTION)
-genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genoutput.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
genoutput.o : genoutput.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
===================================================================
Index: genconditions.c
--- genconditions.c 1 Jan 1970 00:00:00 -0000
+++ genconditions.c 2 Jul 2002 23:45:11 -0000
@@ -0,0 +1,286 @@
+/* Process machine description and calculate constant conditions.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* In a machine description, all of the insn patterns - define_insn,
+ define_expand, define_split, define_peephole, define_peephole2 -
+ contain an optional C expression which makes the final decision
+ about whether or not this pattern is usable. That expression may
+ turn out to be always false when the compiler is built. If it is,
+ most of the programs that generate code from the machine
+ description can simply ignore the entire pattern. */
+
+#include "hconfig.h"
+#include "system.h"
+#include "rtl.h"
+#include "errors.h"
+#include "gensupport.h"
+#include "hashtab.h"
+
+/* routines duplicated in gensupport.c */
+static hashval_t hash_c_test PARAMS ((const PTR));
+static int cmp_c_test PARAMS ((const PTR, const PTR));
+
+/* routines duplicated in gencodes.c */
+static int print_md_constant PARAMS ((void **, void *));
+
+/* so we can include except.h in the generated file */
+static int saw_eh_return;
+
+/* Dummies so we can link. They are normally provided by the file we
+ are about to generate. */
+const struct c_test insn_conditions[1] = { { 0, 0 } };
+const size_t n_insn_conditions = 0;
+
+static htab_t condition_table;
+
+static void add_condition PARAMS ((const char *));
+static void write_header PARAMS ((void));
+static void write_conditions PARAMS ((void));
+static int write_one_condition PARAMS ((PTR *, PTR));
+
+extern int main PARAMS ((int, char **));
+
+static hashval_t
+hash_c_test (x)
+ const PTR x;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const unsigned char *base, *s = (const unsigned char *) a->expr;
+ hashval_t hash;
+ unsigned char c;
+ unsigned int len;
+
+ base = s;
+ hash = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ }
+
+ len = s - base;
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+static int
+cmp_c_test (x, y)
+ const PTR x;
+ const PTR y;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const struct c_test *b = (const struct c_test *) y;
+
+ return !strcmp (a->expr, b->expr);
+}
+
+static void
+add_condition (expr)
+ const char *expr;
+{
+ struct c_test *test;
+
+ if (expr[0] == 0)
+ return;
+
+ test = (struct c_test *) xmalloc (sizeof (struct c_test));
+ test->expr = expr;
+ test->value = -1;
+
+ *(htab_find_slot (condition_table, test, INSERT)) = test;
+}
+
+/* Called via traverse_md_constants; emit a #define for
+ the current constant definition. */
+static int
+print_md_constant (slot, info)
+ void **slot;
+ void *info;
+{
+ struct md_constant *def = *slot;
+ FILE *file = info;
+
+ fprintf (file, "#define %s %s\n", def->name, def->value);
+ return 1;
+}
+
+static void
+write_header ()
+{
+ puts ("\
+/* Generated automatically by the program `genconditions' from the target\n\
+ machine description file. */\n\
+\n\
+#include \"config.h\"\n\
+#include \"system.h\"\n\
+#include \"rtl.h\"\n\
+#include \"tm_p.h\"\n\
+#include \"function.h\"\n");
+
+ puts ("\
+/* Fake - insn-config.h doesn't exist yet. */\n\
+#define MAX_RECOG_OPERANDS 10\n\
+#define MAX_DUP_OPERANDS 10\n\
+#define MAX_INSNS_PER_SPLIT 5\n");
+
+ puts ("\
+/* #defines from (define_constants ...) are normally found in\n\
+ insn-codes.h, but that doesn't exist yet, either. */");
+ traverse_md_constants (print_md_constant, stdout);
+ putchar ('\n');
+
+ puts ("\
+#include \"regs.h\"\n\
+#include \"recog.h\"\n\
+#include \"real.h\"\n\
+#include \"output.h\"\n\
+#include \"flags.h\"\n\
+#include \"hard-reg-set.h\"\n\
+#include \"resource.h\"\n\
+#include \"toplev.h\"\n\
+#include \"reload.h\"\n\
+#include \"gensupport.h\"\n");
+
+ if (saw_eh_return)
+ puts ("#define HAVE_eh_return 1");
+ puts ("#include \"except.h\"\n");
+
+ puts ("\
+/* Dummy external declarations. */\n\
+extern rtx insn;\n\
+extern rtx ins1;\n\
+extern rtx operands[];\n\
+extern int next_insn_tests_no_inequality PARAMS ((rtx));\n");
+
+ puts ("\
+/* If we don't have __builtin_constant_p, or it's not acceptable in\n\
+ array initializers, fall back to assuming that all conditions\n\
+ potentially vary at run time. It works in 3.0.1 and later; 3.0\n\
+ only when not optimizing. */\n\
+#if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)\n\
+# define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)\n\
+#else\n\
+# define MAYBE_EVAL(expr) -1\n\
+#endif\n");
+}
+
+static int
+write_one_condition (slot, dummy)
+ PTR *slot;
+ PTR dummy ATTRIBUTE_UNUSED;
+{
+ const struct c_test *test = * (const struct c_test **) slot;
+ const char *p;
+
+ fputs (" { \"", stdout);
+ for (p = test->expr; *p; p++)
+ {
+ if (*p == '\n')
+ fputs ("\\n\\\n", stdout);
+ else if (*p == '"')
+ fputs ("\\\"", stdout);
+ else
+ putchar (*p);
+ }
+
+ printf ("\",\n MAYBE_EVAL (%s) },\n", test->expr);
+ return 1;
+}
+
+static void
+write_conditions ()
+{
+ puts ("\
+/* This table lists each condition found in the machine description.\n\
+ Each condition is mapped to its truth value (0 or 1), or -1 if that\n\
+ cannot be calculated at compile time. */\n\
+\n\
+const struct c_test insn_conditions[] = {");
+
+ htab_traverse (condition_table, write_one_condition, 0);
+
+ puts ("};\n");
+
+ printf ("const size_t n_insn_conditions = %lu;\n",
+ (unsigned long) htab_elements (condition_table));
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ rtx desc;
+ int pattern_lineno; /* not used */
+ int code;
+
+ progname = "genconditions";
+
+ if (argc <= 1)
+ fatal ("No input file name.");
+
+ /* Tell gensupport it isn't to elide insns automatically - since
+ we are creating the logic it uses to do that! */
+ no_insn_elision = 1;
+
+ if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ return (FATAL_EXIT_CODE);
+
+ condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL);
+
+ /* Read the machine description. */
+
+ while (1)
+ {
+ desc = read_md_rtx (&pattern_lineno, &code);
+ if (desc == NULL)
+ break;
+
+ /* N.B. define_insn_and_split, define_cond_exec are handled
+ entirely within read_md_rtx; we never see them. */
+ switch (GET_CODE (desc))
+ {
+ default:
+ break;
+
+ case DEFINE_INSN:
+ case DEFINE_EXPAND:
+ add_condition (XSTR (desc, 2));
+ if (!strcmp (XSTR (desc, 0), "eh_return"))
+ saw_eh_return = 1;
+ break;
+
+ case DEFINE_SPLIT:
+ case DEFINE_PEEPHOLE:
+ case DEFINE_PEEPHOLE2:
+ add_condition (XSTR (desc, 1));
+ break;
+ }
+ }
+
+ write_header ();
+ write_conditions ();
+
+ fflush (stdout);
+ return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
+}
===================================================================
Index: genflags.c
--- genflags.c 11 Mar 2002 22:39:35 -0000 1.43
+++ genflags.c 2 Jul 2002 23:45:11 -0000
@@ -136,6 +136,7 @@ gen_proto (insn)
{
int num = num_operands (insn);
const char *name = XSTR (insn, 0);
+ int truth = maybe_eval_c_test (XSTR (insn, 2));
/* Many md files don't refer to the last two operands passed to the
call patterns. This means their generator functions will be two
@@ -156,19 +157,33 @@ gen_proto (insn)
gen_macro (name, num, 5);
}
- printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
-
- if (num == 0)
- printf ("void");
+ if (truth == 0)
+ {
+ printf ("#define gen_%s(", name);
+ if (num > 0)
+ {
+ while (num-- > 1)
+ printf ("dummy%d, ", num);
+ printf ("dummy%d", num);
+ }
+ puts (") (NULL_RTX)");
+ }
else
{
- while (num-- > 1)
- printf ("struct rtx_def *, ");
+ printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
- printf ("struct rtx_def *");
- }
+ if (num == 0)
+ printf ("void");
+ else
+ {
+ while (num-- > 1)
+ printf ("struct rtx_def *, ");
- printf ("));\n");
+ printf ("struct rtx_def *");
+ }
+
+ printf ("));\n");
+ }
}
@@ -179,6 +194,7 @@ gen_insn (insn)
const char *name = XSTR (insn, 0);
const char *p;
int len;
+ int truth = maybe_eval_c_test (XSTR (insn, 2));
/* Don't mention instructions whose names are the null string
or begin with '*'. They are in the machine description just
@@ -191,22 +207,23 @@ gen_insn (insn)
if (len > max_id_len)
max_id_len = len;
- printf ("#define HAVE_%s ", name);
- if (strlen (XSTR (insn, 2)) == 0)
- printf ("1\n");
+ if (truth == 0)
+ /* emit nothing */;
+ else if (truth == 1)
+ printf ("#define HAVE_%s 1\n", name);
else
{
/* Write the macro definition, putting \'s at the end of each line,
if more than one. */
- printf ("(");
+ printf ("#define HAVE_%s (", name);
for (p = XSTR (insn, 2); *p; p++)
{
if (IS_VSPACE (*p))
- printf (" \\\n");
+ fputs (" \\\n", stdout);
else
- printf ("%c", *p);
+ putchar (*p);
}
- printf (")\n");
+ fputs (")\n", stdout);
}
obstack_grow (&obstack, &insn, sizeof (rtx));
@@ -227,6 +244,10 @@ main (argc, argv)
progname = "genflags";
obstack_init (&obstack);
+ /* We need to see all the possibilities. Elided insns may have
+ direct calls to their generators in C code. */
+ no_insn_elision = 1;
+
if (argc <= 1)
fatal ("no input file name");
@@ -242,7 +263,7 @@ main (argc, argv)
while (1)
{
- int line_no, insn_code_number = 0;
+ int line_no, insn_code_number;
desc = read_md_rtx (&line_no, &insn_code_number);
if (desc == NULL)
@@ -256,7 +277,7 @@ main (argc, argv)
obstack_grow (&obstack, &dummy, sizeof (rtx));
insns = (rtx *) obstack_finish (&obstack);
- printf ("struct rtx_def;\n");
+ puts ("\nstruct rtx_def;");
for (insn_ptr = insns; *insn_ptr; insn_ptr++)
gen_proto (*insn_ptr);
===================================================================
Index: genrecog.c
--- genrecog.c 11 Jun 2002 12:22:11 -0000 1.118
+++ genrecog.c 2 Jul 2002 23:45:12 -0000
@@ -2452,6 +2452,7 @@ make_insn_sequence (insn, type)
{
rtx x;
const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
+ int truth = maybe_eval_c_test (c_test);
struct decision *last;
struct decision_test *test, **place;
struct decision_head head;
@@ -2504,7 +2505,8 @@ make_insn_sequence (insn, type)
continue;
place = &test->next;
- if (c_test[0])
+ /* Skip the C test if it's known to be true at compile time. */
+ if (truth != 1)
{
/* Need a new node if we have another test to add. */
if (test->type == DT_accept_op)
@@ -2577,7 +2579,7 @@ make_insn_sequence (insn, type)
place = &last->tests;
}
- if (c_test[0])
+ if (truth != 1)
{
test = new_decision_test (DT_c_test, &place);
test->u.c_test = c_test;
===================================================================
Index: gensupport.c
--- gensupport.c 7 Jun 2002 17:59:18 -0000 1.33
+++ gensupport.c 2 Jul 2002 23:45:12 -0000
@@ -24,6 +24,7 @@
#include "obstack.h"
#include "errors.h"
#include "gensupport.h"
+#include "hashtab.h"
/* In case some macros used by files we include need it, define this here. */
@@ -42,6 +43,9 @@ static int predicable_default;
static const char *predicable_true;
static const char *predicable_false;
+int no_insn_elision = 0;
+static htab_t condition_table;
+
static char *base_dir = NULL;
/* We initially queue all patterns, process the define_insn and
@@ -99,6 +103,10 @@ static const char *alter_output_for_insn
int, int));
static void process_one_cond_exec PARAMS ((struct queue_elem *));
static void process_define_cond_exec PARAMS ((void));
+
+static hashval_t hash_c_test PARAMS ((const PTR));
+static int cmp_c_test PARAMS ((const PTR, const PTR));
+
static void process_include PARAMS ((rtx, int));
static char *save_string PARAMS ((const char *, int));
@@ -953,6 +961,7 @@ init_md_reader (filename)
{
FILE *input_file;
int c;
+ size_t i;
char *lastsl;
lastsl = strrchr (filename, '/');
@@ -967,6 +976,14 @@ init_md_reader (filename)
return FATAL_EXIT_CODE;
}
+ /* Initialize the table of insn conditions. */
+ condition_table = htab_create (n_insn_conditions,
+ hash_c_test, cmp_c_test, NULL);
+
+ for (i = 0; i < n_insn_conditions; i++)
+ *(htab_find_slot (condition_table, (PTR) &insn_conditions[i], INSERT))
+ = (PTR) &insn_conditions[i];
+
obstack_init (rtl_obstack);
errors = 0;
sequence_num = 0;
@@ -1005,6 +1022,8 @@ read_md_rtx (lineno, seqnr)
struct queue_elem **queue, *elem;
rtx desc;
+ discard:
+
/* Read all patterns from a given queue before moving on to the next. */
if (define_attr_queue != NULL)
queue = &define_attr_queue;
@@ -1024,13 +1043,26 @@ read_md_rtx (lineno, seqnr)
free (elem);
+ /* Discard insn patterns which we know can never match (because
+ their C test is provably always false). If no_insn_elision is
+ true, our caller needs to see all the patterns. Note that the
+ pattern numbering will be different if no_insn_elision is on. */
switch (GET_CODE (desc))
{
case DEFINE_INSN:
case DEFINE_EXPAND:
+ if (! no_insn_elision && maybe_eval_c_test (XSTR (desc, 2)) == 0)
+ goto discard;
+
+ sequence_num++;
+ break;
+
case DEFINE_SPLIT:
case DEFINE_PEEPHOLE:
case DEFINE_PEEPHOLE2:
+ if (! no_insn_elision && maybe_eval_c_test (XSTR (desc, 1)) == 0)
+ goto discard;
+
sequence_num++;
break;
@@ -1039,6 +1071,62 @@ read_md_rtx (lineno, seqnr)
}
return desc;
+}
+
+/* Helper functions for insn elision. */
+static hashval_t
+hash_c_test (x)
+ const PTR x;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const unsigned char *base, *s = (const unsigned char *) a->expr;
+ hashval_t hash;
+ unsigned char c;
+ unsigned int len;
+
+ base = s;
+ hash = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ }
+
+ len = s - base;
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+static int
+cmp_c_test (x, y)
+ const PTR x;
+ const PTR y;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const struct c_test *b = (const struct c_test *) y;
+
+ return !strcmp (a->expr, b->expr);
+}
+
+int
+maybe_eval_c_test (expr)
+ const char *expr;
+{
+ const struct c_test *test;
+ struct c_test dummy;
+
+ if (expr[0] == 0)
+ return 1;
+
+ dummy.expr = expr;
+ test = (const struct c_test *) htab_find (condition_table, &dummy);
+ if (!test)
+ abort ();
+
+ return test->value;
}
/* Given a string, return the number of comma-separated elements in it.
===================================================================
Index: gensupport.h
--- gensupport.h 12 May 2002 18:43:33 -0000 1.5
+++ gensupport.h 2 Jul 2002 23:45:12 -0000
@@ -18,6 +18,9 @@ along with GCC; see the file COPYING. I
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+#ifndef GCC_GENSUPPORT_H
+#define GCC_GENSUPPORT_H
+
struct obstack;
extern struct obstack *rtl_obstack;
@@ -28,6 +31,28 @@ extern rtx read_md_rtx PARAMS ((int *,
extern void message_with_line PARAMS ((int, const char *, ...))
ATTRIBUTE_PRINTF_2;
+/* Set this to 1 to disable automatic elision of insn patterns which
+ can never be used in this configuration. See genconditions.c.
+ Must be set before calling init_md_reader. */
+extern int no_insn_elision;
+
+/* If the C test passed as the argument can be evaluated at compile
+ time, return its truth value; else return -1. The test must have
+ appeared somewhere in the machine description when genconditions
+ was run. */
+extern int maybe_eval_c_test PARAMS ((const char *));
+
+/* This table should not be accessed directly; use maybe_eval_c_test. */
+struct c_test
+{
+ const char *expr;
+ int value;
+};
+
+extern const struct c_test insn_conditions[];
+extern const size_t n_insn_conditions;
+
extern int n_comma_elts PARAMS ((const char *));
extern const char *scan_comma_elt PARAMS ((const char **));
+#endif /* GCC_GENSUPPORT_H */
===================================================================
Index: print-rtl.c
--- print-rtl.c 18 Jun 2002 20:12:13 -0000 1.84
+++ print-rtl.c 2 Jul 2002 23:45:12 -0000
@@ -23,11 +23,6 @@ Software Foundation, 59 Temple Place - S
#include "config.h"
#include "system.h"
#include "rtl.h"
-
-/* We don't want the tree code checking code for the access to the
- DECL_NAME to be included in the gen* programs. */
-#undef ENABLE_TREE_CHECKING
-#include "tree.h"
#include "real.h"
#include "flags.h"
#include "hard-reg-set.h"
===================================================================
Index: print-tree.c
--- print-tree.c 28 May 2002 17:32:28 -0000 1.59
+++ print-tree.c 2 Jul 2002 23:45:12 -0000
@@ -753,3 +753,27 @@ print_node (file, prefix, node, indent)
fprintf (file, ">");
}
+
+/* Simple print for the tree expression associated with a MEM rtx.
+ This is here so that print-rtl.c need not depend on tree.h. */
+void
+print_mem_expr (outfile, expr)
+ FILE *outfile;
+ tree expr;
+{
+ if (TREE_CODE (expr) == COMPONENT_REF)
+ {
+ if (TREE_OPERAND (expr, 0))
+ print_mem_expr (outfile, TREE_OPERAND (expr, 0));
+ else
+ fputs (" <variable>", outfile);
+ fprintf (outfile, ".%s",
+ IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (expr, 1))));
+ }
+ else if (DECL_NAME (expr))
+ fprintf (outfile, " %s", IDENTIFIER_POINTER (DECL_NAME (expr)));
+ else if (TREE_CODE (expr) == RESULT_DECL)
+ fputs (" <result>", outfile);
+ else
+ fputs (" <anonymous>", outfile);
+}
More information about the Gcc-patches
mailing list