This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Prune unused insn patterns


It is common for MD patterns to have a final C test that depends on
the subarchitecture; these often evaluate to compile-time constants
that turn out to be false.  When this happens, that pattern can never
be used for anything by the compiler, but we will still generate a
substantial amount of code to attempt to recognize it, emit it, etc.
Most of that cannot be eliminated by optimization.

This patch implements a prescan of the MD file to locate all the
expressions that are provably false at compile time.  The patterns
using those test expressions are then ignored by most of the gen*
programs.  (In order to avoid changes to the back ends, genflags and
gencodes have to emit dummy gen_foo functions and CODE_FOR_foo entries
for these patterns.)  The upshot is an 138kB reduction in the size of
a native i686-linux cc1.  I expect similar or perhaps even larger
space benefits on other popular architectures.  The bootstrap is about
1% faster, which is liable to be noise.

I have built cross compilers from i686-linux to one target for every
architecture that we have, using gcc 3.1 as the native compiler so
that insn-conditions.c is active (__builtin_constant_p does not work
sufficiently well prior to 3.0).

alpha-linux      m68k-elf              h8300-elf        powerpc-eabisim
arc-elf          m88k-aout             hppa1.0-linux    romp-openbsd *
arm-elf          mcore-elf             i370-linux       s390-linux
avr-none         mips-elf              i386-openbsd     sh-elf
c4x-none         mmix-knuth-mmixware   i960-coff        sparc-elf
cris-elf         mn10200-elf           ia64-elf         v850-elf
d30v-elf         mn10300-elf           ip2k-elf *       vax-openbsd
dsp16xx-elf *    ns32k-netbsd *        m32r-elf         xstormy16-elf
fr30-elf         pdp11-bsd             m68hc11-elf      xtensa-elf

Starred targets do not build due to unrelated bugs.  If I kludge
around those bugs, I can build cc1 for all targets successfully.
No changes to any back end are required.

OK to apply?

zw

	* gensupport.c: Include hashtab.h.
	(insn_elision, condition_table, hash_c_test, cmp_c_test,
	maybe_eval_c_test): New routines and data structures to
	support insn elision.
	(init_md_reader): Read and initialize the condition_table.
	(read_md_rtx): Discard insn patterns whose C test is provably
	always false.
	* gensupport.h: Declare new functions and data structures.

	* genconditions.c, dummy-conditions.c: New files.
	* Makefile.in: Build genconditions; run it to construct
	insn-conditions.c; build that and link it into most gen*
	programs.
	(HOST_SUPPORT, HOST_EARLY_SUPPORT): New variables.
	(GEN): Delete, unused.
	(STAGESTUFF): Update.

	* gencodes.c: (gen_insn): #define CODE_FOR_xxx equal to
	CODE_FOR_nothing for all elided patterns.
	(main): Tweaked to support this.
	* genflags.c (gen_proto): Emit a static inline generator
	function here for all elided patterns, which simply returns
	NULL_RTX.
	(gen_insn): Do not define HAVE_xxx for elided patterns.
	(main): Tweaked to support this.  No need to forward-declare
	struct rtx_def.
	* genrecog.c: Do not bother emitting the C test if it's known
	to be true at compile time.

===================================================================
Index: Makefile.in
--- Makefile.in	26 Jul 2002 13:45:32 -0000	1.913
+++ Makefile.in	26 Jul 2002 20:14:19 -0000
@@ -622,7 +622,9 @@ SYSLIBS = @GNAT_LIBEXC@
 HOST_LIBS = $(BUILD_LIBIBERTY)
 
 HOST_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \
-		$(BUILD_PREFIX)ggc-none.o gensupport.o
+		$(BUILD_PREFIX)ggc-none.o
+HOST_SUPPORT = gensupport.o insn-conditions.o
+HOST_EARLY_SUPPORT = gensupport.o dummy-conditions.o
 
 HOST_PRINT = $(BUILD_PREFIX)print-rtl.o
 HOST_ERRORS = $(BUILD_PREFIX)errors.o
@@ -742,29 +744,20 @@ OBJS = alias.o bb-reorder.o bitmap.o bui
 
 BACKEND = main.o libbackend.a
 
-# GEN files are listed separately, so they can be built before doing parallel
-#  makes for cc1 or cc1plus.  Otherwise sequent parallel make attempts to load
-#  them before rtl.o is compiled.
-GEN= genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
- 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)
-
 # 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 gtyp-gen.h \
- s-output s-recog s-emit s-extract s-peep s-check \
+ s-output s-recog s-emit s-extract s-peep s-check s-conditions \
  s-attr s-attrtab s-opinit s-preds s-constants s-crt0 \
  genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
  genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
  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) \
@@ -1698,6 +1691,21 @@ 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) \
+  $(TM_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 insn-constants.h
+	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) insn-conditions.c
+
+dummy-conditions.o : dummy-conditions.c $(GCONFIG_H) $(SYSTEM_H) gensupport.h
+	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+	    $(srcdir)/dummy-conditions.c $(OUTPUT_OPTION)
+
 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
@@ -1904,88 +1912,109 @@ read-rtl.o: read-rtl.c $(HCONFIG_H) $(SY
 gensupport.o: gensupport.c $(RTL_H) $(OBSTACK_H) $(SYSTEM_H) errors.h gensupport.h
 	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gensupport.c $(OUTPUT_OPTION)
 
-genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_SUPPORT) \
+  $(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
 	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c $(OUTPUT_OPTION)
 
-genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_EARLY_SUPPORT) \
+  $(HOST_ERRORS) $(HOST_LIBDEPS)
 	$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-	 genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBS)
+	 genconstants.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
+	    $(HOST_ERRORS) $(HOST_LIBS)
 
 genconstants.o : genconstants.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
 	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconstants.c $(OUTPUT_OPTION)
 
-genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_SUPPORT) \
+  $(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
@@ -1995,9 +2024,11 @@ 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
@@ -2043,6 +2074,16 @@ $(srcdir)/gengtype-yacc.c: $(srcdir)/gen
 	(cd $(srcdir) && \
 	 $(BISON) $(BISONFLAGS) -d -o gengtype-yacc.c gengtype-yacc.y || \
 	 ( rm -f $@ && false ) )
+
+genconditions$(build_exeext) : genconditions.o $(HOST_EARLY_SUPPORT) \
+  $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS)
+	$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
+	 genconditions.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
+	    $(HOST_ERRORS) $(HOST_LIBS)
+
+genconditions.o : genconditions.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
+	$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/genconditions.c $(OUTPUT_OPTION)
 
 #
 # Compile the libraries to be used by gen*.
===================================================================
Index: dummy-conditions.c
--- dummy-conditions.c	1 Jan 1970 00:00:00 -0000
+++ dummy-conditions.c	26 Jul 2002 20:14:19 -0000
@@ -0,0 +1,34 @@
+/* Support for calculating constant conditions.
+   Copyright (C) 2002 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.  */
+
+#include "hconfig.h"
+#include "system.h"
+#include "gensupport.h"
+
+/* MD generators that are run before insn-conditions.c exists should
+   link against this file instead.  Currently that is genconditions
+   and genconstants.  */
+
+/* Empty conditions table to prevent link errors.  */
+const struct c_test insn_conditions[1] = { { 0, 0 } };
+const size_t n_insn_conditions = 0;
+
+/* Disable insn elision, since it is currently impossible.  */
+const int insn_elision_unavailable = 1;
===================================================================
Index: gencodes.c
--- gencodes.c	2 Dec 2001 00:04:18 -0000	1.45
+++ gencodes.c	26 Jul 2002 20:14:20 -0000
@@ -28,18 +28,26 @@ Software Foundation, 59 Temple Place - S
 #include "errors.h"
 #include "gensupport.h"
 
-static void gen_insn PARAMS ((const char *, int));
+static void gen_insn PARAMS ((rtx, int));
 
 static void
-gen_insn (name, code)
-     const char *name;
+gen_insn (insn, code)
+     rtx insn;
      int code;
 {
+  const char *name = XSTR (insn, 0);
+  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
      to be recognized.  */
   if (name[0] != 0 && name[0] != '*')
-    printf ("  CODE_FOR_%s = %d,\n", name, code);
+    {
+      if (truth == 0)
+	printf ("#define CODE_FOR_%s CODE_FOR_nothing\n", name);
+      else
+	printf ("  CODE_FOR_%s = %d,\n", name, code);
+    }
 }
 
 extern int main PARAMS ((int, char **));
@@ -53,6 +61,10 @@ main (argc, argv)
 
   progname = "gencodes";
 
+  /* We need to see all the possibilities.  Elided insns may have
+     direct references to CODE_FOR_xxx in C code.  */
+  insn_elision = 0;
+
   if (argc <= 1)
     fatal ("no input file name");
 
@@ -80,10 +92,10 @@ enum insn_code {");
 	break;
 
       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
-	gen_insn (XSTR (desc, 0), insn_code_number);
+	gen_insn (desc, insn_code_number);
     }
 
-  puts ("CODE_FOR_nothing\n\
+  puts ("  CODE_FOR_nothing\n\
 };\n\
 \n\
 #endif /* GCC_INSN_CODES_H */");
===================================================================
Index: genconditions.c
--- genconditions.c	1 Jan 1970 00:00:00 -0000
+++ genconditions.c	26 Jul 2002 20:14:20 -0000
@@ -0,0 +1,225 @@
+/* Process machine description and calculate constant conditions.
+   Copyright (C) 2001, 2002 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 "hashtab.h"
+#include "gensupport.h"
+
+/* so we can include except.h in the generated file */
+static int saw_eh_return;
+
+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 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;
+
+  *(htab_find_slot (condition_table, test, INSERT)) = test;
+}
+
+static void
+write_header ()
+{
+  puts ("\
+/* Generated automatically by the program `genconditions' from the target\n\
+   machine description file.  */\n\
+\n\
+#include \"hconfig.h\"\n\
+#include \"insn-constants.h\"\n");
+
+  puts ("\
+/* Do not allow checking to confuse the issue.  */\n\
+#undef ENABLE_CHECKING\n\
+#undef ENABLE_TREE_CHECKING\n\
+#undef ENABLE_RTL_CHECKING\n\
+#undef ENABLE_RTL_FLAG_CHECKING\n\
+#undef ENABLE_GC_CHECKING\n\
+#undef ENABLE_GC_ALWAYS_COLLECT\n");
+
+  puts ("\
+#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 ("\
+#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));
+  puts ("const int insn_elision_unavailable = 0;");
+}
+
+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.");
+
+  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	23 Jul 2002 06:21:53 -0000	1.44
+++ genflags.c	26 Jul 2002 20:14:20 -0000
@@ -131,7 +131,9 @@ gen_proto (insn)
      rtx insn;
 {
   int num = num_operands (insn);
+  int i;
   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
@@ -152,19 +154,41 @@ gen_proto (insn)
 	gen_macro (name, num, 5);
     }
 
-  printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
+  if (truth != 0)
+    printf ("extern rtx        gen_%-*s PARAMS ((", max_id_len, name);
+  else
+    printf ("static inline rtx gen_%-*s PARAMS ((", max_id_len, name);
 
   if (num == 0)
-    printf ("void");
+    fputs ("void", stdout);
   else
     {
-      while (num-- > 1)
-	printf ("struct rtx_def *, ");
-
-      printf ("struct rtx_def *");
+      for (i = 1; i < num; i++)
+	fputs ("rtx, ", stdout);
+      
+      fputs ("rtx", stdout);
     }
 
-  printf ("));\n");
+  puts ("));");
+
+  /* Some back ends want to take the address of generator functions,
+     so we cannot simply use #define for these dummy definitions.  */
+  if (truth == 0)
+    {
+      printf ("static inline rtx\ngen_%s", name);
+      if (num > 0)
+	{
+	  putchar ('(');
+	  for (i = 0; i < num-1; i++)
+	    printf ("%c, ", 'a' + i);
+	  printf ("%c)\n", 'a' + i);
+	  for (i = 0; i < num; i++)
+	    printf ("     rtx %c ATTRIBUTE_UNUSED;\n", 'a' + i);
+	}
+      else
+	puts ("()");
+      puts ("{\n  return 0;\n}");
+    }
 
 }
 
@@ -175,6 +199,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
@@ -187,22 +212,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));
@@ -223,6 +249,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.  */
+  insn_elision = 0;
+
   if (argc <= 1)
     fatal ("no input file name");
 
@@ -252,7 +282,6 @@ main (argc, argv)
   obstack_grow (&obstack, &dummy, sizeof (rtx));
   insns = (rtx *) obstack_finish (&obstack);
 
-  printf ("struct rtx_def;\n");
   for (insn_ptr = insns; *insn_ptr; insn_ptr++)
     gen_proto (*insn_ptr);
 
===================================================================
Index: genrecog.c
--- genrecog.c	22 Jul 2002 14:20:19 -0000	1.119
+++ genrecog.c	26 Jul 2002 20:14:20 -0000
@@ -2452,11 +2452,16 @@ 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;
   char c_test_pos[2];
 
+  /* We should never see an insn whose C test is false at compile time.  */
+  if (truth == 0)
+    abort ();
+
   record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
 
   c_test_pos[0] = '\0';
@@ -2504,7 +2509,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 +2583,9 @@ make_insn_sequence (insn, type)
 		  place = &last->tests;
 		}
 
-	      if (c_test[0])
+	      /* Skip the C test if it's known to be true at compile
+                 time.  */
+	      if (truth == -1)
 		{
 		  test = new_decision_test (DT_c_test, &place);
 		  test->u.c_test = c_test;
===================================================================
Index: gensupport.c
--- gensupport.c	23 Jul 2002 06:21:53 -0000	1.34
+++ gensupport.c	26 Jul 2002 20:14:20 -0000
@@ -23,12 +23,15 @@
 #include "rtl.h"
 #include "obstack.h"
 #include "errors.h"
+#include "hashtab.h"
 #include "gensupport.h"
 
 
 /* In case some macros used by files we include need it, define this here.  */
 int target_flags;
 
+int insn_elision = 1;
+
 static struct obstack obstack;
 struct obstack *rtl_obstack = &obstack;
 
@@ -39,6 +42,8 @@ static int predicable_default;
 static const char *predicable_true;
 static const char *predicable_false;
 
+static htab_t condition_table;
+
 static char *base_dir = NULL;
 
 /* We initially queue all patterns, process the define_insn and
@@ -950,6 +955,7 @@ init_md_reader (filename)
 {
   FILE *input_file;
   int c;
+  size_t i;
   char *lastsl;
 
   lastsl = strrchr (filename, '/');
@@ -964,6 +970,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;
@@ -1002,6 +1016,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;
@@ -1021,14 +1037,29 @@ 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 insn_elision is
+     false, our caller needs to see all the patterns.  Note that the
+     elided patterns are never counted by the sequence numbering; it
+     it is the caller's responsibility, when insn_elision is false, not
+     to use elided pattern numbers for anything.  */
   switch (GET_CODE (desc))
     {
     case DEFINE_INSN:
     case DEFINE_EXPAND:
+      if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
+	sequence_num++;
+      else if (insn_elision)
+	goto discard;
+      break;
+
     case DEFINE_SPLIT:
     case DEFINE_PEEPHOLE:
     case DEFINE_PEEPHOLE2:
-      sequence_num++;
+      if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
+	sequence_num++;
+      else if (insn_elision)
+	    goto discard;
       break;
 
     default:
@@ -1036,6 +1067,65 @@ read_md_rtx (lineno, seqnr)
     }
 
   return desc;
+}
+
+/* Helper functions for insn elision.  Shared with genconditions.c.  */
+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;
+}
+
+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;
+
+  if (insn_elision_unavailable)
+    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	26 Jul 2002 20:14:20 -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,36 @@ extern rtx read_md_rtx		PARAMS ((int *, 
 extern void message_with_line	PARAMS ((int, const char *, ...))
      ATTRIBUTE_PRINTF_2;
 
+/* Set this to 0 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 insn_elision;
+
+/* If this is 1, the insn elision table doesn't even exist yet.  */
+extern const int insn_elision_unavailable;
+
+/* 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;
+
+#ifdef __HASHTAB_H__
+extern hashval_t hash_c_test PARAMS ((const PTR));
+extern int cmp_c_test PARAMS ((const PTR, const PTR));
+#endif
+
 extern int n_comma_elts		PARAMS ((const char *));
 extern const char *scan_comma_elt PARAMS ((const char **));
 
+#endif /* GCC_GENSUPPORT_H */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]