Patchwork [4/4] Reduce the size of optabs representation

login
register
mail settings
Submitter Richard Henderson
Date July 19, 2012, 6:24 p.m.
Message ID <1342722250-25934-5-git-send-email-rth@redhat.com>
Download mbox | patch
Permalink /patch/172012/
State New
Headers show

Comments

Richard Henderson - July 19, 2012, 6:24 p.m.
---
 gcc/Makefile.in |   19 +-
 gcc/genopinit.c |  932 +++++++++++++++++++++++++----------------------------
 gcc/libfuncs.h  |    2 +-
 gcc/optabs.c    |  653 ++++++-------------------------------
 gcc/optabs.def  |  289 +++++++++++++++++
 gcc/optabs.h    |  960 ++++++-------------------------------------------------
 gcc/rtl.h       |    7 +-
 7 files changed, 953 insertions(+), 1909 deletions(-)
 create mode 100644 gcc/optabs.def
Jakub Jelinek - July 19, 2012, 8:24 p.m.
On Thu, Jul 19, 2012 at 11:24:10AM -0700, Richard Henderson wrote:
> --- /dev/null
> +++ b/gcc/optabs.def
> @@ -0,0 +1,289 @@
> +/* 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.  */

I'm impressed, but haven't looked into details yet.  Just a quick note, I
think optabs.def is large enough that it should start with the standard
boilerplate.

	Jakub

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 06b8179..a1cdf3f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -889,7 +889,7 @@  OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
 FUNCTION_H = function.h $(HASHTAB_H) vecprim.h $(TM_H) hard-reg-set.h \
 	$(VEC_H) vecir.h $(INPUT_H) $(MACHMODE_H)
 EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
-OPTABS_H = optabs.h insn-codes.h
+OPTABS_H = optabs.h insn-codes.h insn-opinit.h
 REGS_H = regs.h $(MACHMODE_H) hard-reg-set.h
 SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) \
 	vecprim.h $(REGSET_H)
@@ -1484,7 +1484,7 @@  BACKEND = libbackend.a main.o @TREEBROWSER@ libcommon-target.a libcommon.a \
 MOSTLYCLEANFILES = 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-attr-common.h insn-attrtab.c insn-dfatab.c \
- insn-latencytab.c insn-opinit.c insn-preds.c insn-constants.h \
+ insn-latencytab.c insn-opinit.c insn-opinit.h insn-preds.c insn-constants.h \
  tm-preds.h tm-constrs.h checksum-options \
  tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
@@ -3430,7 +3430,7 @@  insn-modes.o : insn-modes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h	$(TM_H) \
   $(MACHMODE_H)
 insn-opinit.o : insn-opinit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h	\
   $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h $(FLAGS_H) $(RECOG_H)	\
-  $(EXPR_H) $(OPTABS_H) reload.h
+  $(EXPR_H) $(OPTABS_H)
 insn-output.o : insn-output.c $(CONFIG_H) $(SYSTEM_H) coretypes.h	\
   $(TM_H) $(RTL_H) $(GGC_H) $(REGS_H) conditions.h			\
   hard-reg-set.h insn-config.h $(INSN_ATTR_H) $(EXPR_H) output.h	\
@@ -3459,7 +3459,7 @@  simple_rtl_generated_h	= insn-attr.h insn-attr-common.h insn-codes.h \
 			  insn-config.h insn-flags.h
 
 simple_rtl_generated_c	= insn-automata.c insn-emit.c \
-			  insn-extract.c insn-opinit.c insn-output.c \
+			  insn-extract.c insn-output.c \
 			  insn-peep.c insn-recog.c
 
 simple_generated_h	= $(simple_rtl_generated_h) insn-constants.h
@@ -3506,6 +3506,15 @@  s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
 	$(SHELL) $(srcdir)/../move-if-change tmp-latencytab.c insn-latencytab.c
 	$(STAMP) s-attrtab
 
+# genopinit produces two files.
+insn-opinit.c insn-opinit.h: s-opinit ; @true
+s-opinit: $(MD_DEPS) build/genopinit$(build_exeext) insn-conditions.md
+	$(RUN_GEN) build/genopinit$(build_exeext) $(md_file) \
+	  insn-conditions.md -htmp-opinit.h -ctmp-opinit.c
+	$(SHELL) $(srcdir)/../move-if-change tmp-opinit.h insn-opinit.h
+	$(SHELL) $(srcdir)/../move-if-change tmp-opinit.c insn-opinit.c
+	$(STAMP) s-opinit
+
 # gencondmd doesn't use the standard naming convention.
 build/gencondmd.c: s-conditions; @true
 s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
@@ -3859,7 +3868,7 @@  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
+  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
 build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)	\
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 2d6757e..5261279 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -1,7 +1,5 @@ 
 /* Generate code to initialize optabs from machine description.
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1993-2012 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -29,542 +27,498 @@  along with GCC; see the file COPYING3.  If not see
 #include "gensupport.h"
 
 
-/* Many parts of GCC use arrays that are indexed by machine mode and
-   contain the insn codes for pattern in the MD file that perform a given
-   operation on operands of that mode.
+#define DEF_RTL_EXPR(V, N, X, C) #V,
 
-   These patterns are present in the MD file with names that contain
-   the mode(s) used and the name of the operation.  This program
-   writes a function `init_all_optabs' that initializes the optabs with
-   all the insn codes of the relevant patterns present in the MD file.
+static const char * const rtx_upname[] = {
+#include "rtl.def"
+};
+
+#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.
 
-   This array contains a list of optabs that need to be initialized.  Within
-   each string, the name of the pattern to be matched against is delimited
-   with $( and $).  In the string, $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).  When writing out the initializer, the entire string is
-   used.  $A and $B are replaced with the full name of the mode; $a and $b
-   are replaced with the short form of the name, as above.
+     CX, NX, VX: An extra pattern entry for a conversion or normal optab.
 
-   If $N is present in the pattern, it means the two modes must be in
-   the same mode class, and $b must be greater than $a (e.g, QImode
-   and HImode).
+   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.
 
-   $V means to emit 'v' if the first mode is a MODE_FLOAT mode.
-
-   For some optabs, we store the operation by RTL codes.  These are only
-   used for comparisons.  In that case, $c and $C are the lower-case and
-   upper-case forms of the comparison, respectively.  */
-
-static const char * const optabs[] =
-{ "set_convert_optab_handler (sext_optab, $B, $A, CODE_FOR_$(extend$a$b2$))",
-  "set_convert_optab_handler (zext_optab, $B, $A, CODE_FOR_$(zero_extend$a$b2$))",
-  "set_convert_optab_handler (sfix_optab, $B, $A, CODE_FOR_$(fix$F$a$I$b2$))",
-  "set_convert_optab_handler (ufix_optab, $B, $A, CODE_FOR_$(fixuns$F$a$b2$))",
-  "set_convert_optab_handler (sfixtrunc_optab, $B, $A, CODE_FOR_$(fix_trunc$F$a$I$b2$))",
-  "set_convert_optab_handler (ufixtrunc_optab, $B, $A, CODE_FOR_$(fixuns_trunc$F$a$I$b2$))",
-  "set_convert_optab_handler (sfloat_optab, $B, $A, CODE_FOR_$(float$I$a$F$b2$))",
-  "set_convert_optab_handler (ufloat_optab, $B, $A, CODE_FOR_$(floatuns$I$a$F$b2$))",
-  "set_convert_optab_handler (trunc_optab, $B, $A, CODE_FOR_$(trunc$a$b2$))",
-  "set_convert_optab_handler (fract_optab, $B, $A, CODE_FOR_$(fract$a$b2$))",
-  "set_convert_optab_handler (fractuns_optab, $B, $A, CODE_FOR_$(fractuns$I$a$Q$b2$))",
-  "set_convert_optab_handler (fractuns_optab, $B, $A, CODE_FOR_$(fractuns$Q$a$I$b2$))",
-  "set_convert_optab_handler (satfract_optab, $B, $A, CODE_FOR_$(satfract$a$Q$b2$))",
-  "set_convert_optab_handler (satfractuns_optab, $B, $A, CODE_FOR_$(satfractuns$I$a$Q$b2$))",
-  "set_convert_optab_handler (vec_load_lanes_optab, $A, $B, CODE_FOR_$(vec_load_lanes$a$b$))",
-  "set_convert_optab_handler (vec_store_lanes_optab, $A, $B, CODE_FOR_$(vec_store_lanes$a$b$))",
-  "set_optab_handler (add_optab, $A, CODE_FOR_$(add$P$a3$))",
-  "set_optab_handler (addv_optab, $A, CODE_FOR_$(add$F$a3$)),\n\
-    set_optab_handler (add_optab, $A, CODE_FOR_$(add$F$a3$))",
-  "set_optab_handler (addv_optab, $A, CODE_FOR_$(addv$I$a3$))",
-  "set_optab_handler (add_optab, $A, CODE_FOR_$(add$Q$a3$))",
-  "set_optab_handler (ssadd_optab, $A, CODE_FOR_$(ssadd$Q$a3$))",
-  "set_optab_handler (usadd_optab, $A, CODE_FOR_$(usadd$Q$a3$))",
-  "set_optab_handler (sub_optab, $A, CODE_FOR_$(sub$P$a3$))",
-  "set_optab_handler (subv_optab, $A, CODE_FOR_$(sub$F$a3$)),\n\
-    set_optab_handler (sub_optab, $A, CODE_FOR_$(sub$F$a3$))",
-  "set_optab_handler (subv_optab, $A, CODE_FOR_$(subv$I$a3$))",
-  "set_optab_handler (sub_optab, $A, CODE_FOR_$(sub$Q$a3$))",
-  "set_optab_handler (sssub_optab, $A, CODE_FOR_$(sssub$Q$a3$))",
-  "set_optab_handler (ussub_optab, $A, CODE_FOR_$(ussub$Q$a3$))",
-  "set_optab_handler (smul_optab, $A, CODE_FOR_$(mul$Q$a3$))",
-  "set_optab_handler (ssmul_optab, $A, CODE_FOR_$(ssmul$Q$a3$))",
-  "set_optab_handler (usmul_optab, $A, CODE_FOR_$(usmul$Q$a3$))",
-  "set_optab_handler (smul_optab, $A, CODE_FOR_$(mul$P$a3$))",
-  "set_optab_handler (smulv_optab, $A, CODE_FOR_$(mul$F$a3$)),\n\
-    set_optab_handler (smul_optab, $A, CODE_FOR_$(mul$F$a3$))",
-  "set_optab_handler (smulv_optab, $A, CODE_FOR_$(mulv$I$a3$))",
-  "set_optab_handler (umul_highpart_optab, $A, CODE_FOR_$(umul$a3_highpart$))",
-  "set_optab_handler (smul_highpart_optab, $A, CODE_FOR_$(smul$a3_highpart$))",
-  "set_widening_optab_handler (smul_widen_optab, $B, $A, CODE_FOR_$(mul$a$b3$)$N)",
-  "set_widening_optab_handler (umul_widen_optab, $B, $A, CODE_FOR_$(umul$a$b3$)$N)",
-  "set_widening_optab_handler (usmul_widen_optab, $B, $A, CODE_FOR_$(usmul$a$b3$)$N)",
-  "set_widening_optab_handler (smadd_widen_optab, $B, $A, CODE_FOR_$(madd$a$b4$)$N)",
-  "set_widening_optab_handler (umadd_widen_optab, $B, $A, CODE_FOR_$(umadd$a$b4$)$N)",
-  "set_widening_optab_handler (ssmadd_widen_optab, $B, $A, CODE_FOR_$(ssmadd$a$b4$)$N)",
-  "set_widening_optab_handler (usmadd_widen_optab, $B, $A, CODE_FOR_$(usmadd$a$b4$)$N)",
-  "set_widening_optab_handler (smsub_widen_optab, $B, $A, CODE_FOR_$(msub$a$b4$)$N)",
-  "set_widening_optab_handler (umsub_widen_optab, $B, $A, CODE_FOR_$(umsub$a$b4$)$N)",
-  "set_widening_optab_handler (ssmsub_widen_optab, $B, $A, CODE_FOR_$(ssmsub$a$b4$)$N)",
-  "set_widening_optab_handler (usmsub_widen_optab, $B, $A, CODE_FOR_$(usmsub$a$b4$)$N)",
-  "set_optab_handler (sdiv_optab, $A, CODE_FOR_$(div$a3$))",
-  "set_optab_handler (ssdiv_optab, $A, CODE_FOR_$(ssdiv$Q$a3$))",
-  "set_optab_handler (sdivv_optab, $A, CODE_FOR_$(div$V$I$a3$))",
-  "set_optab_handler (udiv_optab, $A, CODE_FOR_$(udiv$I$a3$))",
-  "set_optab_handler (udiv_optab, $A, CODE_FOR_$(udiv$Q$a3$))",
-  "set_optab_handler (usdiv_optab, $A, CODE_FOR_$(usdiv$Q$a3$))",
-  "set_optab_handler (sdivmod_optab, $A, CODE_FOR_$(divmod$a4$))",
-  "set_optab_handler (udivmod_optab, $A, CODE_FOR_$(udivmod$a4$))",
-  "set_optab_handler (smod_optab, $A, CODE_FOR_$(mod$a3$))",
-  "set_optab_handler (umod_optab, $A, CODE_FOR_$(umod$a3$))",
-  "set_optab_handler (fmod_optab, $A, CODE_FOR_$(fmod$a3$))",
-  "set_optab_handler (remainder_optab, $A, CODE_FOR_$(remainder$a3$))",
-  "set_optab_handler (ftrunc_optab, $A, CODE_FOR_$(ftrunc$F$a2$))",
-  "set_optab_handler (and_optab, $A, CODE_FOR_$(and$a3$))",
-  "set_optab_handler (ior_optab, $A, CODE_FOR_$(ior$a3$))",
-  "set_optab_handler (xor_optab, $A, CODE_FOR_$(xor$a3$))",
-  "set_optab_handler (ashl_optab, $A, CODE_FOR_$(ashl$a3$))",
-  "set_optab_handler (ssashl_optab, $A, CODE_FOR_$(ssashl$Q$a3$))",
-  "set_optab_handler (usashl_optab, $A, CODE_FOR_$(usashl$Q$a3$))",
-  "set_optab_handler (ashr_optab, $A, CODE_FOR_$(ashr$a3$))",
-  "set_optab_handler (lshr_optab, $A, CODE_FOR_$(lshr$a3$))",
-  "set_optab_handler (rotl_optab, $A, CODE_FOR_$(rotl$a3$))",
-  "set_optab_handler (rotr_optab, $A, CODE_FOR_$(rotr$a3$))",
-  "set_optab_handler (vashr_optab, $A, CODE_FOR_$(vashr$a3$))",
-  "set_optab_handler (vlshr_optab, $A, CODE_FOR_$(vlshr$a3$))",
-  "set_optab_handler (vashl_optab, $A, CODE_FOR_$(vashl$a3$))",
-  "set_optab_handler (vrotl_optab, $A, CODE_FOR_$(vrotl$a3$))",
-  "set_optab_handler (vrotr_optab, $A, CODE_FOR_$(vrotr$a3$))",
-  "set_optab_handler (smin_optab, $A, CODE_FOR_$(smin$a3$))",
-  "set_optab_handler (smax_optab, $A, CODE_FOR_$(smax$a3$))",
-  "set_optab_handler (umin_optab, $A, CODE_FOR_$(umin$I$a3$))",
-  "set_optab_handler (umax_optab, $A, CODE_FOR_$(umax$I$a3$))",
-  "set_optab_handler (pow_optab, $A, CODE_FOR_$(pow$a3$))",
-  "set_optab_handler (atan2_optab, $A, CODE_FOR_$(atan2$a3$))",
-  "set_optab_handler (neg_optab, $A, CODE_FOR_$(neg$P$a2$))",
-  "set_optab_handler (negv_optab, $A, CODE_FOR_$(neg$F$a2$)),\n\
-    set_optab_handler (neg_optab, $A, CODE_FOR_$(neg$F$a2$))",
-  "set_optab_handler (negv_optab, $A, CODE_FOR_$(negv$I$a2$))",
-  "set_optab_handler (neg_optab, $A, CODE_FOR_$(neg$Q$a2$))",
-  "set_optab_handler (ssneg_optab, $A, CODE_FOR_$(ssneg$Q$a2$))",
-  "set_optab_handler (usneg_optab, $A, CODE_FOR_$(usneg$Q$a2$))",
-  "set_optab_handler (abs_optab, $A, CODE_FOR_$(abs$P$a2$))",
-  "set_optab_handler (absv_optab, $A, CODE_FOR_$(abs$F$a2$)),\n\
-    set_optab_handler (abs_optab, $A, CODE_FOR_$(abs$F$a2$))",
-  "set_optab_handler (absv_optab, $A, CODE_FOR_$(absv$I$a2$))",
-  "set_optab_handler (copysign_optab, $A, CODE_FOR_$(copysign$F$a3$))",
-  "set_optab_handler (signbit_optab, $A, CODE_FOR_$(signbit$F$a2$))",
-  "set_optab_handler (isinf_optab, $A, CODE_FOR_$(isinf$a2$))",
-  "set_optab_handler (sqrt_optab, $A, CODE_FOR_$(sqrt$a2$))",
-  "set_optab_handler (floor_optab, $A, CODE_FOR_$(floor$a2$))",
-  "set_convert_optab_handler (lfloor_optab, $B, $A, CODE_FOR_$(lfloor$F$a$I$b2$))",
-  "set_optab_handler (fma_optab, $A, CODE_FOR_$(fma$a4$))",
-  "set_optab_handler (fms_optab, $A, CODE_FOR_$(fms$a4$))",
-  "set_optab_handler (fnma_optab, $A, CODE_FOR_$(fnma$a4$))",
-  "set_optab_handler (fnms_optab, $A, CODE_FOR_$(fnms$a4$))",
-  "set_optab_handler (ceil_optab, $A, CODE_FOR_$(ceil$a2$))",
-  "set_convert_optab_handler (lceil_optab, $B, $A, CODE_FOR_$(lceil$F$a$I$b2$))",
-  "set_optab_handler (round_optab, $A, CODE_FOR_$(round$a2$))",
-  "set_optab_handler (btrunc_optab, $A, CODE_FOR_$(btrunc$a2$))",
-  "set_optab_handler (nearbyint_optab, $A, CODE_FOR_$(nearbyint$a2$))",
-  "set_optab_handler (rint_optab, $A, CODE_FOR_$(rint$a2$))",
-  "set_convert_optab_handler (lrint_optab, $B, $A, CODE_FOR_$(lrint$F$a$I$b2$))",
-  "set_convert_optab_handler (lround_optab, $B, $A, CODE_FOR_$(lround$F$a$I$b2$))",
-  "set_optab_handler (sincos_optab, $A, CODE_FOR_$(sincos$a3$))",
-  "set_optab_handler (sin_optab, $A, CODE_FOR_$(sin$a2$))",
-  "set_optab_handler (asin_optab, $A, CODE_FOR_$(asin$a2$))",
-  "set_optab_handler (cos_optab, $A, CODE_FOR_$(cos$a2$))",
-  "set_optab_handler (acos_optab, $A, CODE_FOR_$(acos$a2$))",
-  "set_optab_handler (exp_optab, $A, CODE_FOR_$(exp$a2$))",
-  "set_optab_handler (exp10_optab, $A, CODE_FOR_$(exp10$a2$))",
-  "set_optab_handler (exp2_optab, $A, CODE_FOR_$(exp2$a2$))",
-  "set_optab_handler (expm1_optab, $A, CODE_FOR_$(expm1$a2$))",
-  "set_optab_handler (ldexp_optab, $A, CODE_FOR_$(ldexp$a3$))",
-  "set_optab_handler (scalb_optab, $A, CODE_FOR_$(scalb$a3$))",
-  "set_optab_handler (significand_optab, $A, CODE_FOR_$(significand$a2$))",
-  "set_optab_handler (logb_optab, $A, CODE_FOR_$(logb$a2$))",
-  "set_optab_handler (ilogb_optab, $A, CODE_FOR_$(ilogb$a2$))",
-  "set_optab_handler (log_optab, $A, CODE_FOR_$(log$a2$))",
-  "set_optab_handler (log10_optab, $A, CODE_FOR_$(log10$a2$))",
-  "set_optab_handler (log2_optab, $A, CODE_FOR_$(log2$a2$))",
-  "set_optab_handler (log1p_optab, $A, CODE_FOR_$(log1p$a2$))",
-  "set_optab_handler (tan_optab, $A, CODE_FOR_$(tan$a2$))",
-  "set_optab_handler (atan_optab, $A, CODE_FOR_$(atan$a2$))",
-  "set_optab_handler (strlen_optab, $A, CODE_FOR_$(strlen$a$))",
-  "set_optab_handler (one_cmpl_optab, $A, CODE_FOR_$(one_cmpl$a2$))",
-  "set_optab_handler (bswap_optab, $A, CODE_FOR_$(bswap$a2$))",
-  "set_optab_handler (ffs_optab, $A, CODE_FOR_$(ffs$a2$))",
-  "set_optab_handler (clz_optab, $A, CODE_FOR_$(clz$a2$))",
-  "set_optab_handler (ctz_optab, $A, CODE_FOR_$(ctz$a2$))",
-  "set_optab_handler (clrsb_optab, $A, CODE_FOR_$(clrsb$a2$))",
-  "set_optab_handler (popcount_optab, $A, CODE_FOR_$(popcount$a2$))",
-  "set_optab_handler (parity_optab, $A, CODE_FOR_$(parity$a2$))",
-  "set_optab_handler (mov_optab, $A, CODE_FOR_$(mov$a$))",
-  "set_optab_handler (movstrict_optab, $A, CODE_FOR_$(movstrict$a$))",
-  "set_optab_handler (movmisalign_optab, $A, CODE_FOR_$(movmisalign$a$))",
-  "set_optab_handler (storent_optab, $A, CODE_FOR_$(storent$a$))",
-  "set_optab_handler (addcc_optab, $A, CODE_FOR_$(add$acc$))",
-  "set_direct_optab_handler (movcc_optab, $A, CODE_FOR_$(mov$acc$))",
-  "set_optab_handler (cbranch_optab, $A, CODE_FOR_$(cbranch$a4$))",
-  "set_optab_handler (cmov_optab, $A, CODE_FOR_$(cmov$a6$))",
-  "set_optab_handler (cstore_optab, $A, CODE_FOR_$(cstore$a4$))",
-  "set_optab_handler (ctrap_optab, $A, CODE_FOR_$(ctrap$a4$))",
-  "set_optab_handler (push_optab, $A, CODE_FOR_$(push$a1$))",
-  "set_direct_optab_handler (reload_in_optab, $A, CODE_FOR_$(reload_in$a$))",
-  "set_direct_optab_handler (reload_out_optab, $A, CODE_FOR_$(reload_out$a$))",
-  "set_direct_optab_handler (movmem_optab, $A, CODE_FOR_$(movmem$a$))",
-  "set_direct_optab_handler (cmpstr_optab, $A, CODE_FOR_$(cmpstr$a$))",
-  "set_direct_optab_handler (cmpstrn_optab, $A, CODE_FOR_$(cmpstrn$a$))",
-  "set_direct_optab_handler (cmpmem_optab, $A, CODE_FOR_$(cmpmem$a$))",
-  "set_direct_optab_handler (setmem_optab, $A, CODE_FOR_$(setmem$a$))",
-  "set_direct_optab_handler (sync_add_optab, $A, CODE_FOR_$(sync_add$I$a$))",
-  "set_direct_optab_handler (sync_sub_optab, $A, CODE_FOR_$(sync_sub$I$a$))",
-  "set_direct_optab_handler (sync_ior_optab, $A, CODE_FOR_$(sync_ior$I$a$))",
-  "set_direct_optab_handler (sync_and_optab, $A, CODE_FOR_$(sync_and$I$a$))",
-  "set_direct_optab_handler (sync_xor_optab, $A, CODE_FOR_$(sync_xor$I$a$))",
-  "set_direct_optab_handler (sync_nand_optab, $A, CODE_FOR_$(sync_nand$I$a$))",
-  "set_optab_handler (sync_old_add_optab, $A, CODE_FOR_$(sync_old_add$I$a$))",
-  "set_optab_handler (sync_old_sub_optab, $A, CODE_FOR_$(sync_old_sub$I$a$))",
-  "set_optab_handler (sync_old_ior_optab, $A, CODE_FOR_$(sync_old_ior$I$a$))",
-  "set_optab_handler (sync_old_and_optab, $A, CODE_FOR_$(sync_old_and$I$a$))",
-  "set_optab_handler (sync_old_xor_optab, $A, CODE_FOR_$(sync_old_xor$I$a$))",
-  "set_optab_handler (sync_old_nand_optab, $A, CODE_FOR_$(sync_old_nand$I$a$))",
-  "set_optab_handler (sync_new_add_optab, $A, CODE_FOR_$(sync_new_add$I$a$))",
-  "set_optab_handler (sync_new_sub_optab, $A, CODE_FOR_$(sync_new_sub$I$a$))",
-  "set_optab_handler (sync_new_ior_optab, $A, CODE_FOR_$(sync_new_ior$I$a$))",
-  "set_optab_handler (sync_new_and_optab, $A, CODE_FOR_$(sync_new_and$I$a$))",
-  "set_optab_handler (sync_new_xor_optab, $A, CODE_FOR_$(sync_new_xor$I$a$))",
-  "set_optab_handler (sync_new_nand_optab, $A, CODE_FOR_$(sync_new_nand$I$a$))",
-  "set_optab_handler (sync_compare_and_swap_optab, $A, CODE_FOR_$(sync_compare_and_swap$I$a$))",
-  "set_optab_handler (sync_lock_test_and_set_optab, $A, CODE_FOR_$(sync_lock_test_and_set$I$a$))",
-  "set_direct_optab_handler (sync_lock_release_optab, $A, CODE_FOR_$(sync_lock_release$I$a$))",
-  "set_direct_optab_handler (atomic_exchange_optab, $A, CODE_FOR_$(atomic_exchange$I$a$))",
-  "set_direct_optab_handler (atomic_compare_and_swap_optab, $A, CODE_FOR_$(atomic_compare_and_swap$I$a$))",
-  "set_direct_optab_handler (atomic_load_optab, $A, CODE_FOR_$(atomic_load$I$a$))",
-  "set_direct_optab_handler (atomic_store_optab, $A, CODE_FOR_$(atomic_store$I$a$))",
-  "set_direct_optab_handler (atomic_add_fetch_optab, $A, CODE_FOR_$(atomic_add_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_sub_fetch_optab, $A, CODE_FOR_$(atomic_sub_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_and_fetch_optab, $A, CODE_FOR_$(atomic_and_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_nand_fetch_optab, $A, CODE_FOR_$(atomic_nand_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_xor_fetch_optab, $A, CODE_FOR_$(atomic_xor_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_or_fetch_optab, $A, CODE_FOR_$(atomic_or_fetch$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_add_optab, $A, CODE_FOR_$(atomic_fetch_add$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_sub_optab, $A, CODE_FOR_$(atomic_fetch_sub$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_and_optab, $A, CODE_FOR_$(atomic_fetch_and$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_nand_optab, $A, CODE_FOR_$(atomic_fetch_nand$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_xor_optab, $A, CODE_FOR_$(atomic_fetch_xor$I$a$))",
-  "set_direct_optab_handler (atomic_fetch_or_optab, $A, CODE_FOR_$(atomic_fetch_or$I$a$))",
-  "set_direct_optab_handler (atomic_add_optab, $A, CODE_FOR_$(atomic_add$I$a$))",
-  "set_direct_optab_handler (atomic_sub_optab, $A, CODE_FOR_$(atomic_sub$I$a$))",
-  "set_direct_optab_handler (atomic_and_optab, $A, CODE_FOR_$(atomic_and$I$a$))",
-  "set_direct_optab_handler (atomic_nand_optab, $A, CODE_FOR_$(atomic_nand$I$a$))",
-  "set_direct_optab_handler (atomic_xor_optab, $A, CODE_FOR_$(atomic_xor$I$a$))",
-  "set_direct_optab_handler (atomic_or_optab, $A, CODE_FOR_$(atomic_or$I$a$))",
-  "set_optab_handler (vec_set_optab, $A, CODE_FOR_$(vec_set$a$))",
-  "set_optab_handler (vec_extract_optab, $A, CODE_FOR_$(vec_extract$a$))",
-  "set_optab_handler (vec_init_optab, $A, CODE_FOR_$(vec_init$a$))",
-  "set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
-  "set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
-  "set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
-  "set_direct_optab_handler (vec_perm_optab, $A, CODE_FOR_$(vec_perm$a$))",
-  "set_direct_optab_handler (vec_perm_const_optab, $A, CODE_FOR_$(vec_perm_const$a$))",
-  "set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
-  "set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
-  "set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
-  "set_optab_handler (usum_widen_optab, $A, CODE_FOR_$(widen_usum$I$a3$))",
-  "set_optab_handler (udot_prod_optab, $A, CODE_FOR_$(udot_prod$I$a$))",
-  "set_optab_handler (sdot_prod_optab, $A, CODE_FOR_$(sdot_prod$I$a$))",
-  "set_optab_handler (reduc_smax_optab, $A, CODE_FOR_$(reduc_smax_$a$))",
-  "set_optab_handler (reduc_umax_optab, $A, CODE_FOR_$(reduc_umax_$a$))",
-  "set_optab_handler (reduc_smin_optab, $A, CODE_FOR_$(reduc_smin_$a$))",
-  "set_optab_handler (reduc_umin_optab, $A, CODE_FOR_$(reduc_umin_$a$))",
-  "set_optab_handler (reduc_splus_optab, $A, CODE_FOR_$(reduc_splus_$a$))" ,
-  "set_optab_handler (reduc_uplus_optab, $A, CODE_FOR_$(reduc_uplus_$a$))",
-  "set_optab_handler (vec_widen_umult_hi_optab, $A, CODE_FOR_$(vec_widen_umult_hi_$a$))",
-  "set_optab_handler (vec_widen_umult_lo_optab, $A, CODE_FOR_$(vec_widen_umult_lo_$a$))",
-  "set_optab_handler (vec_widen_smult_hi_optab, $A, CODE_FOR_$(vec_widen_smult_hi_$a$))",
-  "set_optab_handler (vec_widen_smult_lo_optab, $A, CODE_FOR_$(vec_widen_smult_lo_$a$))",
-  "set_optab_handler (vec_widen_umult_even_optab, $A, CODE_FOR_$(vec_widen_umult_even_$a$))",
-  "set_optab_handler (vec_widen_umult_odd_optab, $A, CODE_FOR_$(vec_widen_umult_odd_$a$))",
-  "set_optab_handler (vec_widen_smult_even_optab, $A, CODE_FOR_$(vec_widen_smult_even_$a$))",
-  "set_optab_handler (vec_widen_smult_odd_optab, $A, CODE_FOR_$(vec_widen_smult_odd_$a$))",
-  "set_optab_handler (vec_widen_ushiftl_hi_optab, $A, CODE_FOR_$(vec_widen_ushiftl_hi_$a$))",
-  "set_optab_handler (vec_widen_ushiftl_lo_optab, $A, CODE_FOR_$(vec_widen_ushiftl_lo_$a$))",
-  "set_optab_handler (vec_widen_sshiftl_hi_optab, $A, CODE_FOR_$(vec_widen_sshiftl_hi_$a$))",
-  "set_optab_handler (vec_widen_sshiftl_lo_optab, $A, CODE_FOR_$(vec_widen_sshiftl_lo_$a$))",
-  "set_optab_handler (vec_unpacks_hi_optab, $A, CODE_FOR_$(vec_unpacks_hi_$a$))",
-  "set_optab_handler (vec_unpacks_lo_optab, $A, CODE_FOR_$(vec_unpacks_lo_$a$))",
-  "set_optab_handler (vec_unpacku_hi_optab, $A, CODE_FOR_$(vec_unpacku_hi_$a$))",
-  "set_optab_handler (vec_unpacku_lo_optab, $A, CODE_FOR_$(vec_unpacku_lo_$a$))",
-  "set_optab_handler (vec_unpacks_float_hi_optab, $A, CODE_FOR_$(vec_unpacks_float_hi_$a$))",
-  "set_optab_handler (vec_unpacks_float_lo_optab, $A, CODE_FOR_$(vec_unpacks_float_lo_$a$))",
-  "set_optab_handler (vec_unpacku_float_hi_optab, $A, CODE_FOR_$(vec_unpacku_float_hi_$a$))",
-  "set_optab_handler (vec_unpacku_float_lo_optab, $A, CODE_FOR_$(vec_unpacku_float_lo_$a$))",
-  "set_optab_handler (vec_pack_trunc_optab, $A, CODE_FOR_$(vec_pack_trunc_$a$))",
-  "set_optab_handler (vec_pack_ssat_optab, $A, CODE_FOR_$(vec_pack_ssat_$a$))",
-  "set_optab_handler (vec_pack_usat_optab, $A, CODE_FOR_$(vec_pack_usat_$a$))",
-  "set_optab_handler (vec_pack_sfix_trunc_optab, $A, CODE_FOR_$(vec_pack_sfix_trunc_$a$))",
-  "set_optab_handler (vec_pack_ufix_trunc_optab, $A, CODE_FOR_$(vec_pack_ufix_trunc_$a$))"
+   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 },
+
+typedef struct optab_def_d
+{
+  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;
+} optab_def;
+
+static optab_def optabs[] = {
+  { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
+#include "optabs.def"
 };
 
-static void gen_insn (rtx);
+#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.  */
+
+typedef struct pattern_d
+{
+  const char *name;
+  unsigned int op;
+  unsigned int m1, m2;
+  unsigned int sort_num;
+} pattern;
+
+DEF_VEC_O(pattern);
+DEF_VEC_ALLOC_O(pattern, heap);
+
+static VEC(pattern, heap) *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 void
 gen_insn (rtx insn)
 {
   const char *name = XSTR (insn, 0);
-  int m1 = 0, m2 = 0, op = 0;
-  size_t pindex;
-  int i;
-  const char *np, *pp, *p, *q;
-
-  /* Don't mention instructions whose names are the null string.
-     They are in the machine description just to be recognized.  */
-  if (*name == 0)
-    return;
+  pattern p;
+  unsigned pindex;
 
-  /* See if NAME matches one of the patterns we have for the optabs we know
-     about.  */
+  /* 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++)
     {
-      int force_float = 0, force_int = 0, force_partial_int = 0;
-      int force_fixed = 0;
-      int force_wider = 0;
-      int matches = 1;
-
-      for (pp = optabs[pindex]; pp[0] != '$' || pp[1] != '('; pp++)
-	;
-
-      for (pp += 2, np = name; matches && ! (pp[0] == '$' && pp[1] == ')');
-	   pp++)
+      p.m1 = p.m2 = 0;
+      if (match_pattern (&p, name, optabs[pindex].pattern))
 	{
-	  if (*pp != '$')
-	    {
-	      if (*pp != *np++)
-		break;
-	    }
-	  else
-	    switch (*++pp)
-	      {
-	      case 'N':
-		force_wider = 1;
-		break;
-	      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 'V':
-                break;
-	      case 'c':
-		for (op = 0; op < NUM_RTX_CODE; op++)
-		  {
-		    for (p = GET_RTX_NAME(op), q = np; *p; p++, q++)
-		      if (*p != *q)
-			break;
-
-		    /* We have to be concerned about matching "gt" and
-		       missing "gtu", e.g., so verify we have reached the
-		       end of thing we are to match.  */
-		    if (*p == 0 && *q == 0
-			&& (GET_RTX_CLASS (op) == RTX_COMPARE
-			    || GET_RTX_CLASS (op) == RTX_COMM_COMPARE))
-		      break;
-		  }
-
-		if (op == NUM_RTX_CODE)
-		  matches = 0;
-		else
-		  np += strlen (GET_RTX_NAME(op));
-		break;
-	      case 'a':
-	      case 'b':
-		/* 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--)
-		  {
-		    for (p = GET_MODE_NAME(i), q = np; *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)
-			&& (! force_wider
-			    || *pp == 'a'
-			    || m1 < i))
-		      break;
-		  }
-
-		if (i < 0)
-		  matches = 0;
-		else if (*pp == 'a')
-		  m1 = i, np += strlen (GET_MODE_NAME(i));
-		else
-		  m2 = i, np += strlen (GET_MODE_NAME(i));
-
-		force_int = force_partial_int = force_float = force_fixed = 0;
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  p.op = optabs[pindex].op;
+	  p.sort_num = (p.op << 16) | (p.m2 << 8) | p.m1;
+	  VEC_safe_push (pattern, heap, patterns, &p);
+	  return;
 	}
-
-      if (matches && pp[0] == '$' && pp[1] == ')'
-	  && *np == 0)
-	break;
     }
+}
 
-  if (pindex == ARRAY_SIZE (optabs))
-    return;
+static int
+pattern_cmp (const void *va, const void *vb)
+{
+  const pattern *a = (const pattern *)va;
+  const pattern *b = (const pattern *)vb;
+  return a->sort_num - b->sort_num;
+}
 
-  /* We found a match.  If this pattern is only conditionally present,
-     write out the "if" and two extra blanks.  */
+static int
+optab_kind_cmp (const void *va, const void *vb)
+{
+  const optab_def *a = (const optab_def *)va;
+  const optab_def *b = (const optab_def *)vb;
+  int diff = a->kind - b->kind;
+  if (diff == 0)
+    diff = a->op - b->op;
+  return diff;
+}
 
-  if (*XSTR (insn, 2) != 0)
-    printf ("  if (HAVE_%s)\n  ", name);
+static int
+optab_rcode_cmp (const void *va, const void *vb)
+{
+  const optab_def *a = (const optab_def *)va;
+  const optab_def *b = (const optab_def *)vb;
+  return a->rcode - b->rcode;
+}
 
-  printf ("  ");
+static const char *header_file_name = "init-opinit.h";
+static const char *source_file_name = "init-opinit.c";
 
-  /* Now write out the initialization, making all required substitutions.  */
-  for (pp = optabs[pindex]; *pp; pp++)
+static bool
+handle_arg (const char *arg)
+{
+  switch (arg[1])
     {
-      if (*pp != '$')
-	putchar (*pp);
-      else
-	switch (*++pp)
-	  {
-	  case '(':  case ')':
-	  case 'I':  case 'F':  case 'N':
-	    break;
-	  case 'V':
-	    if (SCALAR_FLOAT_MODE_P (m1))
-              printf ("v");
-            break;
-	  case 'a':
-	    for (np = GET_MODE_NAME(m1); *np; np++)
-	      putchar (TOLOWER (*np));
-	    break;
-	  case 'b':
-	    for (np = GET_MODE_NAME(m2); *np; np++)
-	      putchar (TOLOWER (*np));
-	    break;
-	  case 'A':
-	    printf ("%smode", GET_MODE_NAME(m1));
-	    break;
-	  case 'B':
-	    printf ("%smode", GET_MODE_NAME(m2));
-	    break;
-	  case 'c':
-	    printf ("%s", GET_RTX_NAME(op));
-	    break;
-	  case 'C':
-	    for (np = GET_RTX_NAME(op); *np; np++)
-	      putchar (TOUPPER (*np));
-	    break;
-	  }
+    case 'h':
+      header_file_name = &arg[2];
+      return true;
+    case 'c':
+      source_file_name = &arg[2];
+      return true;
+    default:
+      return false;
     }
-
-  printf (";\n");
 }
 
-extern int main (int, char **);
+static FILE *
+open_outfile (const char *file_name)
+{
+  FILE *f = fopen (file_name, "w");
+  if (!f)
+    fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
+  fprintf (f,
+	   "/* Generated automatically by the program `genopinit'\n"
+	   "   from the machine description file `md'.  */\n\n");
+  return f;
+}
 
 int
 main (int argc, char **argv)
 {
-  rtx desc;
+  FILE *h_file, *s_file;
+  unsigned int i, j, n, last_kind[5];
+  pattern *p;
 
   progname = "genopinit";
 
-  if (!init_rtx_reader_args (argc, argv))
+  if (NUM_OPTABS > 0xffff || MAX_MACHINE_MODE >= 0xff)
+    fatal ("genopinit range assumptions invalid");
+
+  if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
     return (FATAL_EXIT_CODE);
 
-  printf ("/* Generated automatically by the program `genopinit'\n\
-from the machine description file `md'.  */\n\n");
-
-  printf ("#include \"config.h\"\n");
-  printf ("#include \"system.h\"\n");
-  printf ("#include \"coretypes.h\"\n");
-  printf ("#include \"tm.h\"\n");
-  printf ("#include \"rtl.h\"\n");
-  printf ("#include \"tm_p.h\"\n");
-  printf ("#include \"flags.h\"\n");
-  printf ("#include \"insn-config.h\"\n");
-  printf ("#include \"recog.h\"\n");
-  printf ("#include \"expr.h\"\n");
-  printf ("#include \"optabs.h\"\n");
-  printf ("#include \"reload.h\"\n\n");
-
-  printf ("void\ninit_all_optabs (void)\n{\n");
-
-  puts ("\
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\
-  int i, j;\n\
-#endif\n");
+  h_file = open_outfile (header_file_name);
+  s_file = open_outfile (source_file_name);
 
   /* Read the machine description.  */
-
   while (1)
     {
       int line_no, insn_code_number = 0;
-
-      desc = read_md_rtx (&line_no, &insn_code_number);
+      rtx desc = read_md_rtx (&line_no, &insn_code_number);
       if (desc == NULL)
 	break;
-
       if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
 	gen_insn (desc);
     }
 
-  puts ("\
-\n\
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\
-  /* This flag says the same insns that convert to a signed fixnum\n\
-     also convert validly to an unsigned one.  */\n\
-  for (i = 0; i < NUM_MACHINE_MODES; i++)\n\
-    for (j = 0; j < NUM_MACHINE_MODES; j++)\n\
-      set_convert_optab_handler\n\
- 	(ufixtrunc_optab, (enum machine_mode) i, (enum machine_mode) j,\n\
-	 convert_optab_handler (sfixtrunc_optab, (enum machine_mode) i,\n\
-						 (enum machine_mode) j));\n\
-#endif\n\
-}");
-
-  fflush (stdout);
-  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
+  /* Sort the collected patterns.  */
+  qsort (VEC_address (pattern, patterns), VEC_length (pattern, patterns),
+	 sizeof (pattern), pattern_cmp);
+
+  /* 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);
+  for (i = 0; i < n; )
+    if (optabs[i].base == NULL)
+      optabs[i] = optabs[--n];
+    else
+      ++i;
+
+  /* Sort the (real) optabs.  Better than forcing the optabs.def file to
+     remain sorted by kind.  We also scrogged any real ordering with the
+     purging of the X patterns above.  */
+  qsort (optabs, n, sizeof(optab_def), optab_kind_cmp);
+
+  /* Emit the optab enumeration for the header file.  */
+  fprintf (h_file, "enum optab_tag {\n");
+  for (i = j = 0; i < n; ++i)
+    {
+      optabs[i].op = i;
+      fprintf (h_file, "  %s,\n", optabs[i].name);
+      if (optabs[i].kind != j)
+	last_kind[j++] = i - 1;
+    }
+  fprintf (h_file, "  FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
+  fprintf (h_file, "  LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
+  fprintf (h_file, "  LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
+  fprintf (h_file, "  FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
+  fprintf (h_file, "  LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
+  fprintf (h_file, "  LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
+  fprintf (h_file, "};\n\n");
+
+  fprintf (h_file, "#define NUM_OPTABS          %u\n", n);
+  fprintf (h_file, "#define NUM_CONVLIB_OPTABS  %u\n",
+	   last_kind[1] - last_kind[0]);
+  fprintf (h_file, "#define NUM_NORMLIB_OPTABS  %u\n",
+	   last_kind[3] - last_kind[2]);
+  fprintf (h_file, "#define NUM_OPTAB_PATTERNS  %u\n",
+	   (unsigned) VEC_length (pattern, patterns));
+
+  fprintf (s_file,
+	   "#include \"config.h\"\n"
+	   "#include \"system.h\"\n"
+	   "#include \"coretypes.h\"\n"
+	   "#include \"tm.h\"\n"
+	   "#include \"rtl.h\"\n"
+	   "#include \"tm_p.h\"\n"
+	   "#include \"flags.h\"\n"
+	   "#include \"insn-config.h\"\n"
+	   "#include \"expr.h\"\n"
+	   "#include \"optabs.h\"\n"
+	   "\n"
+	   "struct optab_pat {\n"
+	   "  unsigned scode;\n"
+	   "  enum insn_code icode;\n"
+	   "};\n\n");
+
+  fprintf (s_file,
+	   "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
+  for (i = 0; VEC_iterate (pattern, patterns, i, p); ++i)
+    fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
+  fprintf (s_file, "};\n\n");
+
+  fprintf (s_file, "void\ninit_all_optabs (void)\n{\n");
+  fprintf (s_file, "  bool *ena = this_target_optabs->pat_enable;\n");
+  for (i = 0; VEC_iterate (pattern, patterns, i, p); ++i)
+    fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
+  fprintf (s_file, "}\n\n");
+
+  /* Perform a binary search on a pre-encoded optab+mode*2.  */
+  /* ??? Perhaps even better to generate a minimal perfect hash.
+     Using gperf directly is awkward since it's so geared to working
+     with strings.  Plus we have no visibility into the ordering of
+     the hash entries, which complicates the pat_enable array.  */
+  fprintf (s_file,
+	   "static int\n"
+	   "lookup_handler (unsigned scode)\n"
+	   "{\n"
+	   "  int l = 0, h = ARRAY_SIZE (pats), m;\n"
+	   "  while (h > l)\n"
+	   "    {\n"
+	   "      m = (h + l) / 2;\n"
+	   "      if (scode == pats[m].scode)\n"
+	   "        return m;\n"
+	   "      else if (scode < pats[m].scode)\n"
+	   "        h = m;\n"
+	   "      else\n"
+	   "        l = m + 1;\n"
+	   "    }\n"
+	   "  return -1;\n"
+	   "}\n\n");
+
+  fprintf (s_file,
+	   "enum insn_code\n"
+	   "raw_optab_handler (unsigned scode)\n"
+	   "{\n"
+	   "  int i = lookup_handler (scode);\n"
+	   "  return (i >= 0 && this_target_optabs->pat_enable[i]\n"
+	   "          ? pats[i].icode : CODE_FOR_nothing);\n"
+	   "}\n\n");
+
+  fprintf (s_file,
+	   "bool\n"
+	   "swap_optab_enable (optab op, enum machine_mode m, bool set)\n"
+	   "{\n"
+	   "  unsigned scode = (op << 16) | m;\n"
+	   "  int i = lookup_handler (scode);\n"
+	   "  if (i >= 0)\n"
+	   "    {\n"
+	   "      bool ret = this_target_optabs->pat_enable[i];\n"
+	   "      this_target_optabs->pat_enable[i] = set;\n"
+	   "      return ret;\n"
+	   "    }\n"
+	   "  else\n"
+	   "    {\n"
+	   "      gcc_assert (!set);\n"
+	   "      return false;\n"
+	   "    }\n"
+	   "}\n\n");
+
+  /* C++ (even G++) does not support (non-trivial) designated initializers.
+     To work around that, generate these arrays programatically rather than
+     by our traditional multiple inclusion of def files.  */
+
+  fprintf (s_file,
+	   "const struct convert_optab_libcall_d "
+	   "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
+  for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
+    fprintf (s_file, "  { %s, %s },\n", optabs[i].base, optabs[i].libcall);
+  fprintf (s_file, "};\n\n");
+
+  fprintf (s_file,
+	   "const struct optab_libcall_d "
+	   "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
+  for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
+    fprintf (s_file, "  { %s, %s, %s },\n",
+	     optabs[i].suffix, optabs[i].base, optabs[i].libcall);
+  fprintf (s_file, "};\n\n");
+
+  fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
+  for (i = 0; i < n; ++i)
+    fprintf (s_file, "  %s,\n", rtx_upname[optabs[i].fcode]);
+  fprintf (s_file, "};\n\n");
+
+  qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
+
+  fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
+  for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
+    continue;
+  for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE; ++i)
+    {
+      if (j < n && optabs[j].rcode == i)
+	fprintf (s_file, "  %s,\n", optabs[j++].name);
+      else
+	fprintf (s_file, "  unknown_optab,\n");
+    }
+  fprintf (s_file, "};\n\n");
+
+  return (fclose (h_file) == 0 && fclose (s_file) == 0
+	  ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
 }
diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h
index bac4918..75f7a69 100644
--- a/gcc/libfuncs.h
+++ b/gcc/libfuncs.h
@@ -52,7 +52,7 @@  enum libfunc_index
    for normal optabs and conversion optabs.  In the first case mode2
    is unused.  */
 struct GTY(()) libfunc_entry {
-  size_t optab;
+  optab op;
   enum machine_mode mode1, mode2;
   rtx libfunc;
 };
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 83509f9..022adfa 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -54,9 +54,6 @@  struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
 #define libfunc_hash \
   (this_target_libfuncs->x_libfunc_hash)
 
-/* Contains the optab used for each rtx code.  */
-optab code_to_optab_[NUM_RTX_CODE + 1];
-
 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
 				   enum machine_mode *);
 static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
@@ -78,9 +75,7 @@  static hashval_t
 hash_libfunc (const void *p)
 {
   const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
-
-  return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES)
-	  ^ e->optab);
+  return (((int) e->mode1 + (int) e->mode2 * NUM_MACHINE_MODES) ^ e->op);
 }
 
 /* Used for libfunc_hash.  */
@@ -90,10 +85,7 @@  eq_libfunc (const void *p, const void *q)
 {
   const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
   const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
-
-  return (e1->optab == e2->optab
-	  && e1->mode1 == e2->mode1
-	  && e1->mode2 == e2->mode2);
+  return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
 }
 
 /* Return libfunc corresponding operation defined by OPTAB converting
@@ -106,22 +98,30 @@  convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
   struct libfunc_entry e;
   struct libfunc_entry **slot;
 
-  e.optab = (size_t) (optab - &convert_optab_table[0]);
+  /* ??? This ought to be an assert, but not all of the places
+     that we expand optabs know about the optabs that got moved
+     to being direct.  */
+  if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
+    return NULL_RTX;
+
+  e.op = optab;
   e.mode1 = mode1;
   e.mode2 = mode2;
-  slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
+  slot = (struct libfunc_entry **)
+    htab_find_slot (libfunc_hash, &e, NO_INSERT);
   if (!slot)
     {
-      if (optab->libcall_gen)
-	{
-	  optab->libcall_gen (optab, optab->libcall_basename, mode1, mode2);
-          slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
-	  if (slot)
-	    return (*slot)->libfunc;
-	  else
-	    return NULL;
-	}
-      return NULL;
+      const struct convert_optab_libcall_d *d
+	= &convlib_def[optab - FIRST_CONV_OPTAB];
+
+      if (d->libcall_gen == NULL)
+	return NULL;
+
+      d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
+      slot = (struct libfunc_entry **)
+	htab_find_slot (libfunc_hash, &e, NO_INSERT);
+      if (!slot)
+	return NULL;
     }
   return (*slot)->libfunc;
 }
@@ -135,24 +135,30 @@  optab_libfunc (optab optab, enum machine_mode mode)
   struct libfunc_entry e;
   struct libfunc_entry **slot;
 
-  e.optab = (size_t) (optab - &optab_table[0]);
+  /* ??? This ought to be an assert, but not all of the places
+     that we expand optabs know about the optabs that got moved
+     to being direct.  */
+  if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
+    return NULL_RTX;
+
+  e.op = optab;
   e.mode1 = mode;
   e.mode2 = VOIDmode;
-  slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, NO_INSERT);
+  slot = (struct libfunc_entry **)
+    htab_find_slot (libfunc_hash, &e, NO_INSERT);
   if (!slot)
     {
-      if (optab->libcall_gen)
-	{
-	  optab->libcall_gen (optab, optab->libcall_basename,
-			      optab->libcall_suffix, mode);
-          slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash,
-							   &e, NO_INSERT);
-	  if (slot)
-	    return (*slot)->libfunc;
-	  else
-	    return NULL;
-	}
-      return NULL;
+      const struct optab_libcall_d *d
+	= &normlib_def[optab - FIRST_NORM_OPTAB];
+
+      if (d->libcall_gen == NULL)
+	return NULL;
+
+      d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
+      slot = (struct libfunc_entry **)
+	htab_find_slot (libfunc_hash, &e, NO_INSERT);
+      if (!slot)
+	return NULL;
     }
   return (*slot)->libfunc;
 }
@@ -2227,7 +2233,7 @@  sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
 {
   rtx temp;
   optab direct_optab = unsignedp ? uoptab : soptab;
-  struct optab_d wide_soptab;
+  bool save_enable;
 
   /* Do it without widening, if possible.  */
   temp = expand_binop (mode, direct_optab, op0, op1, target,
@@ -2235,38 +2241,38 @@  sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
   if (temp || methods == OPTAB_DIRECT)
     return temp;
 
-  /* Try widening to a signed int.  Make a fake signed optab that
-     hides any signed insn for direct use.  */
-  wide_soptab = *soptab;
-  set_optab_handler (&wide_soptab, mode, CODE_FOR_nothing);
-  /* We don't want to generate new hash table entries from this fake
-     optab.  */
-  wide_soptab.libcall_gen = NULL;
+  /* Try widening to a signed int.  Disable any direct use of any
+     signed insn in the current mode.  */
+  save_enable = swap_optab_enable (soptab, mode, false);
 
-  temp = expand_binop (mode, &wide_soptab, op0, op1, target,
+  temp = expand_binop (mode, soptab, op0, op1, target,
 		       unsignedp, OPTAB_WIDEN);
 
   /* For unsigned operands, try widening to an unsigned int.  */
-  if (temp == 0 && unsignedp)
+  if (!temp && unsignedp)
     temp = expand_binop (mode, uoptab, op0, op1, target,
 			 unsignedp, OPTAB_WIDEN);
   if (temp || methods == OPTAB_WIDEN)
-    return temp;
+    goto egress;
 
   /* Use the right width libcall if that exists.  */
-  temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
+  temp = expand_binop (mode, direct_optab, op0, op1, target,
+		       unsignedp, OPTAB_LIB);
   if (temp || methods == OPTAB_LIB)
-    return temp;
+    goto egress;
 
   /* Must widen and use a libcall, use either signed or unsigned.  */
-  temp = expand_binop (mode, &wide_soptab, op0, op1, target,
+  temp = expand_binop (mode, soptab, op0, op1, target,
 		       unsignedp, methods);
-  if (temp != 0)
-    return temp;
-  if (unsignedp)
-    return expand_binop (mode, uoptab, op0, op1, target,
+  if (!temp && unsignedp)
+    temp = expand_binop (mode, uoptab, op0, op1, target,
 			 unsignedp, methods);
-  return 0;
+
+ egress:
+  /* Undo the fiddling above.  */
+  if (save_enable)
+    swap_optab_enable (soptab, mode, true);
+  return temp;
 }
 
 /* Generate code to perform an operation specified by UNOPPTAB
@@ -5415,39 +5421,6 @@  have_insn_for (enum rtx_code code, enum machine_mode mode)
 	      != CODE_FOR_nothing));
 }
 
-/* Set all insn_code fields to CODE_FOR_nothing.  */
-
-static void
-init_insn_codes (void)
-{
-  memset (optab_table, 0, sizeof (optab_table));
-  memset (convert_optab_table, 0, sizeof (convert_optab_table));
-  memset (direct_optab_table, 0, sizeof (direct_optab_table));
-}
-
-/* Initialize OP's code to CODE, and write it into the code_to_optab table.  */
-static inline void
-init_optab (optab op, enum rtx_code code)
-{
-  op->code_ = code;
-  code_to_optab_[(int) code] = op;
-}
-
-/* Same, but fill in its code as CODE, and do _not_ write it into
-   the code_to_optab table.  */
-static inline void
-init_optabv (optab op, enum rtx_code code)
-{
-  op->code_ = code;
-}
-
-/* Conversion optabs never go in the code_to_optab table.  */
-static void
-init_convert_optab (convert_optab op, enum rtx_code code)
-{
-  op->code_ = code;
-}
-
 /* Initialize the libfunc fields of an entire group of entries in some
    optab.  Each entry is set equal to a string consisting of a leading
    pair of underscores followed by a generic operation name followed by
@@ -5463,7 +5436,8 @@  init_convert_optab (convert_optab op, enum rtx_code code)
 */
 
 static void
-gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mode)
+gen_libfunc (optab optable, const char *opname, int suffix,
+	     enum machine_mode mode)
 {
   unsigned opname_len = strlen (opname);
   const char *mname = GET_MODE_NAME (mode);
@@ -5497,7 +5471,7 @@  gen_libfunc (optab optable, const char *opname, int suffix, enum machine_mode mo
 
 /* Like gen_libfunc, but verify that integer operation is involved.  */
 
-static void
+void
 gen_int_libfunc (optab optable, const char *opname, char suffix,
 		 enum machine_mode mode)
 {
@@ -5515,7 +5489,7 @@  gen_int_libfunc (optab optable, const char *opname, char suffix,
 
 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
 
-static void
+void
 gen_fp_libfunc (optab optable, const char *opname, char suffix,
 		enum machine_mode mode)
 {
@@ -5536,7 +5510,7 @@  gen_fp_libfunc (optab optable, const char *opname, char suffix,
 
 /* Like gen_libfunc, but verify that fixed-point operation is involved.  */
 
-static void
+void
 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
 		   enum machine_mode mode)
 {
@@ -5548,7 +5522,7 @@  gen_fixed_libfunc (optab optable, const char *opname, char suffix,
 /* Like gen_libfunc, but verify that signed fixed-point operation is
    involved.  */
 
-static void
+void
 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
 			  enum machine_mode mode)
 {
@@ -5560,7 +5534,7 @@  gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
    involved.  */
 
-static void
+void
 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
 			    enum machine_mode mode)
 {
@@ -5571,7 +5545,7 @@  gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
 
 /* Like gen_libfunc, but verify that FP or INT operation is involved.  */
 
-static void
+void
 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
 		    enum machine_mode mode)
 {
@@ -5584,7 +5558,7 @@  gen_int_fp_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that FP or INT operation is involved
    and add 'v' suffix for integer operation.  */
 
-static void
+void
 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
 		     enum machine_mode mode)
 {
@@ -5604,7 +5578,7 @@  gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
    involved.  */
 
-static void
+void
 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
 			  enum machine_mode mode)
 {
@@ -5619,7 +5593,7 @@  gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
    involved.  */
 
-static void
+void
 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 				 enum machine_mode mode)
 {
@@ -5634,7 +5608,7 @@  gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that INT or FIXED operation is
    involved.  */
 
-static void
+void
 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
 		       enum machine_mode mode)
 {
@@ -5647,7 +5621,7 @@  gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
    involved.  */
 
-static void
+void
 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 			      enum machine_mode mode)
 {
@@ -5660,7 +5634,7 @@  gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
    involved.  */
 
-static void
+void
 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
 				enum machine_mode mode)
 {
@@ -5676,7 +5650,7 @@  gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
    a mode name and an operand count these functions have two mode names
    and no operand count.  */
 
-static void
+void
 gen_interclass_conv_libfunc (convert_optab tab,
 			     const char *opname,
 			     enum machine_mode tmode,
@@ -5748,7 +5722,7 @@  gen_interclass_conv_libfunc (convert_optab tab,
 /* Same as gen_interclass_conv_libfunc but verify that we are producing
    int->fp conversion.  */
 
-static void
+void
 gen_int_to_fp_conv_libfunc (convert_optab tab,
 			    const char *opname,
 			    enum machine_mode tmode,
@@ -5764,7 +5738,7 @@  gen_int_to_fp_conv_libfunc (convert_optab tab,
 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
    naming scheme.  */
 
-static void
+void
 gen_ufloat_conv_libfunc (convert_optab tab,
 			 const char *opname ATTRIBUTE_UNUSED,
 			 enum machine_mode tmode,
@@ -5779,7 +5753,7 @@  gen_ufloat_conv_libfunc (convert_optab tab,
 /* Same as gen_interclass_conv_libfunc but verify that we are producing
    fp->int conversion.  */
 
-static void
+void
 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
 			               const char *opname,
 			               enum machine_mode tmode,
@@ -5795,7 +5769,7 @@  gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
 /* Same as gen_interclass_conv_libfunc but verify that we are producing
    fp->int conversion with no decimal floating point involved.  */
 
-static void
+void
 gen_fp_to_int_conv_libfunc (convert_optab tab,
 			    const char *opname,
 			    enum machine_mode tmode,
@@ -5812,7 +5786,7 @@  gen_fp_to_int_conv_libfunc (convert_optab tab,
    The string formation rules are
    similar to the ones for init_libfunc, above.  */
 
-static void
+void
 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
 			     enum machine_mode tmode, enum machine_mode fmode)
 {
@@ -5882,7 +5856,7 @@  gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
 /* Pick proper libcall for trunc_optab.  We need to chose if we do
    truncation or extension and interclass or intraclass.  */
 
-static void
+void
 gen_trunc_conv_libfunc (convert_optab tab,
 			 const char *opname,
 			 enum machine_mode tmode,
@@ -5911,7 +5885,7 @@  gen_trunc_conv_libfunc (convert_optab tab,
 /* Pick proper libcall for extend_optab.  We need to chose if we do
    truncation or extension and interclass or intraclass.  */
 
-static void
+void
 gen_extend_conv_libfunc (convert_optab tab,
 			 const char *opname ATTRIBUTE_UNUSED,
 			 enum machine_mode tmode,
@@ -5940,7 +5914,7 @@  gen_extend_conv_libfunc (convert_optab tab,
 /* Pick proper libcall for fract_optab.  We need to chose if we do
    interclass or intraclass.  */
 
-static void
+void
 gen_fract_conv_libfunc (convert_optab tab,
 			const char *opname,
 			enum machine_mode tmode,
@@ -5959,7 +5933,7 @@  gen_fract_conv_libfunc (convert_optab tab,
 
 /* Pick proper libcall for fractuns_optab.  */
 
-static void
+void
 gen_fractuns_conv_libfunc (convert_optab tab,
 			   const char *opname,
 			   enum machine_mode tmode,
@@ -5980,7 +5954,7 @@  gen_fractuns_conv_libfunc (convert_optab tab,
 /* Pick proper libcall for satfract_optab.  We need to chose if we do
    interclass or intraclass.  */
 
-static void
+void
 gen_satfract_conv_libfunc (convert_optab tab,
 			   const char *opname,
 			   enum machine_mode tmode,
@@ -6000,7 +5974,7 @@  gen_satfract_conv_libfunc (convert_optab tab,
 
 /* Pick proper libcall for satfractuns_optab.  */
 
-static void
+void
 gen_satfractuns_conv_libfunc (convert_optab tab,
 			      const char *opname,
 			      enum machine_mode tmode,
@@ -6101,12 +6075,13 @@  set_user_assembler_libfunc (const char *name, const char *asmspec)
 /* Call this to reset the function entry for one optab (OPTABLE) in mode
    MODE to NAME, which should be either 0 or a string constant.  */
 void
-set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
+set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
 {
   rtx val;
   struct libfunc_entry e;
   struct libfunc_entry **slot;
-  e.optab = (size_t) (optable - &optab_table[0]);
+
+  e.op = op;
   e.mode1 = mode;
   e.mode2 = VOIDmode;
 
@@ -6117,7 +6092,7 @@  set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
   if (*slot == NULL)
     *slot = ggc_alloc_libfunc_entry ();
-  (*slot)->optab = (size_t) (optable - &optab_table[0]);
+  (*slot)->op = op;
   (*slot)->mode1 = mode;
   (*slot)->mode2 = VOIDmode;
   (*slot)->libfunc = val;
@@ -6127,13 +6102,14 @@  set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
    either 0 or a string constant.  */
 void
-set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
+set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
 		  enum machine_mode fmode, const char *name)
 {
   rtx val;
   struct libfunc_entry e;
   struct libfunc_entry **slot;
-  e.optab = (size_t) (optable - &convert_optab_table[0]);
+
+  e.op = optab;
   e.mode1 = tmode;
   e.mode2 = fmode;
 
@@ -6144,7 +6120,7 @@  set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
   if (*slot == NULL)
     *slot = ggc_alloc_libfunc_entry ();
-  (*slot)->optab = (size_t) (optable - &convert_optab_table[0]);
+  (*slot)->op = optab;
   (*slot)->mode1 = tmode;
   (*slot)->mode2 = fmode;
   (*slot)->libfunc = val;
@@ -6157,421 +6133,13 @@  void
 init_optabs (void)
 {
   if (libfunc_hash)
-    {
-      htab_empty (libfunc_hash);
-      /* We statically initialize the insn_codes with the equivalent of
-	 CODE_FOR_nothing.  Repeat the process if reinitialising.  */
-      init_insn_codes ();
-    }
+    htab_empty (libfunc_hash);
   else
     libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
 
-  init_optab (add_optab, PLUS);
-  init_optabv (addv_optab, PLUS);
-  init_optab (sub_optab, MINUS);
-  init_optabv (subv_optab, MINUS);
-  init_optab (ssadd_optab, SS_PLUS);
-  init_optab (usadd_optab, US_PLUS);
-  init_optab (sssub_optab, SS_MINUS);
-  init_optab (ussub_optab, US_MINUS);
-  init_optab (smul_optab, MULT);
-  init_optab (ssmul_optab, SS_MULT);
-  init_optab (usmul_optab, US_MULT);
-  init_optabv (smulv_optab, MULT);
-  init_optab (smul_highpart_optab, UNKNOWN);
-  init_optab (umul_highpart_optab, UNKNOWN);
-  init_optab (smul_widen_optab, UNKNOWN);
-  init_optab (umul_widen_optab, UNKNOWN);
-  init_optab (usmul_widen_optab, UNKNOWN);
-  init_optab (smadd_widen_optab, UNKNOWN);
-  init_optab (umadd_widen_optab, UNKNOWN);
-  init_optab (ssmadd_widen_optab, UNKNOWN);
-  init_optab (usmadd_widen_optab, UNKNOWN);
-  init_optab (smsub_widen_optab, UNKNOWN);
-  init_optab (umsub_widen_optab, UNKNOWN);
-  init_optab (ssmsub_widen_optab, UNKNOWN);
-  init_optab (usmsub_widen_optab, UNKNOWN);
-  init_optab (sdiv_optab, DIV);
-  init_optab (ssdiv_optab, SS_DIV);
-  init_optab (usdiv_optab, US_DIV);
-  init_optabv (sdivv_optab, DIV);
-  init_optab (sdivmod_optab, UNKNOWN);
-  init_optab (udiv_optab, UDIV);
-  init_optab (udivmod_optab, UNKNOWN);
-  init_optab (smod_optab, MOD);
-  init_optab (umod_optab, UMOD);
-  init_optab (fmod_optab, UNKNOWN);
-  init_optab (remainder_optab, UNKNOWN);
-  init_optab (ftrunc_optab, UNKNOWN);
-  init_optab (and_optab, AND);
-  init_optab (ior_optab, IOR);
-  init_optab (xor_optab, XOR);
-  init_optab (ashl_optab, ASHIFT);
-  init_optab (ssashl_optab, SS_ASHIFT);
-  init_optab (usashl_optab, US_ASHIFT);
-  init_optab (ashr_optab, ASHIFTRT);
-  init_optab (lshr_optab, LSHIFTRT);
-  init_optabv (vashl_optab, ASHIFT);
-  init_optabv (vashr_optab, ASHIFTRT);
-  init_optabv (vlshr_optab, LSHIFTRT);
-  init_optab (rotl_optab, ROTATE);
-  init_optab (rotr_optab, ROTATERT);
-  init_optab (smin_optab, SMIN);
-  init_optab (smax_optab, SMAX);
-  init_optab (umin_optab, UMIN);
-  init_optab (umax_optab, UMAX);
-  init_optab (pow_optab, UNKNOWN);
-  init_optab (atan2_optab, UNKNOWN);
-  init_optab (fma_optab, FMA);
-  init_optab (fms_optab, UNKNOWN);
-  init_optab (fnma_optab, UNKNOWN);
-  init_optab (fnms_optab, UNKNOWN);
-
-  /* These three have codes assigned exclusively for the sake of
-     have_insn_for.  */
-  init_optab (mov_optab, SET);
-  init_optab (movstrict_optab, STRICT_LOW_PART);
-  init_optab (cbranch_optab, COMPARE);
-
-  init_optab (cmov_optab, UNKNOWN);
-  init_optab (cstore_optab, UNKNOWN);
-  init_optab (ctrap_optab, UNKNOWN);
-
-  init_optab (storent_optab, UNKNOWN);
-
-  init_optab (cmp_optab, UNKNOWN);
-  init_optab (ucmp_optab, UNKNOWN);
-
-  init_optab (eq_optab, EQ);
-  init_optab (ne_optab, NE);
-  init_optab (gt_optab, GT);
-  init_optab (ge_optab, GE);
-  init_optab (lt_optab, LT);
-  init_optab (le_optab, LE);
-  init_optab (unord_optab, UNORDERED);
-
-  init_optab (neg_optab, NEG);
-  init_optab (ssneg_optab, SS_NEG);
-  init_optab (usneg_optab, US_NEG);
-  init_optabv (negv_optab, NEG);
-  init_optab (abs_optab, ABS);
-  init_optabv (absv_optab, ABS);
-  init_optab (addcc_optab, UNKNOWN);
-  init_optab (one_cmpl_optab, NOT);
-  init_optab (bswap_optab, BSWAP);
-  init_optab (ffs_optab, FFS);
-  init_optab (clz_optab, CLZ);
-  init_optab (ctz_optab, CTZ);
-  init_optab (clrsb_optab, CLRSB);
-  init_optab (popcount_optab, POPCOUNT);
-  init_optab (parity_optab, PARITY);
-  init_optab (sqrt_optab, SQRT);
-  init_optab (floor_optab, UNKNOWN);
-  init_optab (ceil_optab, UNKNOWN);
-  init_optab (round_optab, UNKNOWN);
-  init_optab (btrunc_optab, UNKNOWN);
-  init_optab (nearbyint_optab, UNKNOWN);
-  init_optab (rint_optab, UNKNOWN);
-  init_optab (sincos_optab, UNKNOWN);
-  init_optab (sin_optab, UNKNOWN);
-  init_optab (asin_optab, UNKNOWN);
-  init_optab (cos_optab, UNKNOWN);
-  init_optab (acos_optab, UNKNOWN);
-  init_optab (exp_optab, UNKNOWN);
-  init_optab (exp10_optab, UNKNOWN);
-  init_optab (exp2_optab, UNKNOWN);
-  init_optab (expm1_optab, UNKNOWN);
-  init_optab (ldexp_optab, UNKNOWN);
-  init_optab (scalb_optab, UNKNOWN);
-  init_optab (significand_optab, UNKNOWN);
-  init_optab (logb_optab, UNKNOWN);
-  init_optab (ilogb_optab, UNKNOWN);
-  init_optab (log_optab, UNKNOWN);
-  init_optab (log10_optab, UNKNOWN);
-  init_optab (log2_optab, UNKNOWN);
-  init_optab (log1p_optab, UNKNOWN);
-  init_optab (tan_optab, UNKNOWN);
-  init_optab (atan_optab, UNKNOWN);
-  init_optab (copysign_optab, UNKNOWN);
-  init_optab (signbit_optab, UNKNOWN);
-
-  init_optab (isinf_optab, UNKNOWN);
-
-  init_optab (strlen_optab, UNKNOWN);
-  init_optab (push_optab, UNKNOWN);
-
-  init_optab (reduc_smax_optab, UNKNOWN);
-  init_optab (reduc_umax_optab, UNKNOWN);
-  init_optab (reduc_smin_optab, UNKNOWN);
-  init_optab (reduc_umin_optab, UNKNOWN);
-  init_optab (reduc_splus_optab, UNKNOWN);
-  init_optab (reduc_uplus_optab, UNKNOWN);
-
-  init_optab (ssum_widen_optab, UNKNOWN);
-  init_optab (usum_widen_optab, UNKNOWN);
-  init_optab (sdot_prod_optab, UNKNOWN);
-  init_optab (udot_prod_optab, UNKNOWN);
-
-  init_optab (vec_extract_optab, UNKNOWN);
-  init_optab (vec_set_optab, UNKNOWN);
-  init_optab (vec_init_optab, UNKNOWN);
-  init_optab (vec_shl_optab, UNKNOWN);
-  init_optab (vec_shr_optab, UNKNOWN);
-  init_optab (vec_realign_load_optab, UNKNOWN);
-  init_optab (movmisalign_optab, UNKNOWN);
-  init_optab (vec_widen_umult_hi_optab, UNKNOWN);
-  init_optab (vec_widen_umult_lo_optab, UNKNOWN);
-  init_optab (vec_widen_smult_hi_optab, UNKNOWN);
-  init_optab (vec_widen_smult_lo_optab, UNKNOWN);
-  init_optab (vec_widen_ushiftl_hi_optab, UNKNOWN);
-  init_optab (vec_widen_ushiftl_lo_optab, UNKNOWN);
-  init_optab (vec_widen_sshiftl_hi_optab, UNKNOWN);
-  init_optab (vec_widen_sshiftl_lo_optab, UNKNOWN);
-  init_optab (vec_unpacks_hi_optab, UNKNOWN);
-  init_optab (vec_unpacks_lo_optab, UNKNOWN);
-  init_optab (vec_unpacku_hi_optab, UNKNOWN);
-  init_optab (vec_unpacku_lo_optab, UNKNOWN);
-  init_optab (vec_unpacks_float_hi_optab, UNKNOWN);
-  init_optab (vec_unpacks_float_lo_optab, UNKNOWN);
-  init_optab (vec_unpacku_float_hi_optab, UNKNOWN);
-  init_optab (vec_unpacku_float_lo_optab, UNKNOWN);
-  init_optab (vec_pack_trunc_optab, UNKNOWN);
-  init_optab (vec_pack_usat_optab, UNKNOWN);
-  init_optab (vec_pack_ssat_optab, UNKNOWN);
-  init_optab (vec_pack_ufix_trunc_optab, UNKNOWN);
-  init_optab (vec_pack_sfix_trunc_optab, UNKNOWN);
-
-  init_optab (powi_optab, UNKNOWN);
-
-  /* Conversions.  */
-  init_convert_optab (sext_optab, SIGN_EXTEND);
-  init_convert_optab (zext_optab, ZERO_EXTEND);
-  init_convert_optab (trunc_optab, TRUNCATE);
-  init_convert_optab (sfix_optab, FIX);
-  init_convert_optab (ufix_optab, UNSIGNED_FIX);
-  init_convert_optab (sfixtrunc_optab, UNKNOWN);
-  init_convert_optab (ufixtrunc_optab, UNKNOWN);
-  init_convert_optab (sfloat_optab, FLOAT);
-  init_convert_optab (ufloat_optab, UNSIGNED_FLOAT);
-  init_convert_optab (lrint_optab, UNKNOWN);
-  init_convert_optab (lround_optab, UNKNOWN);
-  init_convert_optab (lfloor_optab, UNKNOWN);
-  init_convert_optab (lceil_optab, UNKNOWN);
-
-  init_convert_optab (fract_optab, FRACT_CONVERT);
-  init_convert_optab (fractuns_optab, UNSIGNED_FRACT_CONVERT);
-  init_convert_optab (satfract_optab, SAT_FRACT);
-  init_convert_optab (satfractuns_optab, UNSIGNED_SAT_FRACT);
-
   /* Fill in the optabs with the insns we support.  */
   init_all_optabs ();
 
-  /* Initialize the optabs with the names of the library functions.  */
-  add_optab->libcall_basename = "add";
-  add_optab->libcall_suffix = '3';
-  add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
-  addv_optab->libcall_basename = "add";
-  addv_optab->libcall_suffix = '3';
-  addv_optab->libcall_gen = gen_intv_fp_libfunc;
-  ssadd_optab->libcall_basename = "ssadd";
-  ssadd_optab->libcall_suffix = '3';
-  ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
-  usadd_optab->libcall_basename = "usadd";
-  usadd_optab->libcall_suffix = '3';
-  usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  sub_optab->libcall_basename = "sub";
-  sub_optab->libcall_suffix = '3';
-  sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
-  subv_optab->libcall_basename = "sub";
-  subv_optab->libcall_suffix = '3';
-  subv_optab->libcall_gen = gen_intv_fp_libfunc;
-  sssub_optab->libcall_basename = "sssub";
-  sssub_optab->libcall_suffix = '3';
-  sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
-  ussub_optab->libcall_basename = "ussub";
-  ussub_optab->libcall_suffix = '3';
-  ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  smul_optab->libcall_basename = "mul";
-  smul_optab->libcall_suffix = '3';
-  smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
-  smulv_optab->libcall_basename = "mul";
-  smulv_optab->libcall_suffix = '3';
-  smulv_optab->libcall_gen = gen_intv_fp_libfunc;
-  ssmul_optab->libcall_basename = "ssmul";
-  ssmul_optab->libcall_suffix = '3';
-  ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
-  usmul_optab->libcall_basename = "usmul";
-  usmul_optab->libcall_suffix = '3';
-  usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  sdiv_optab->libcall_basename = "div";
-  sdiv_optab->libcall_suffix = '3';
-  sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
-  sdivv_optab->libcall_basename = "divv";
-  sdivv_optab->libcall_suffix = '3';
-  sdivv_optab->libcall_gen = gen_int_libfunc;
-  ssdiv_optab->libcall_basename = "ssdiv";
-  ssdiv_optab->libcall_suffix = '3';
-  ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
-  udiv_optab->libcall_basename = "udiv";
-  udiv_optab->libcall_suffix = '3';
-  udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
-  usdiv_optab->libcall_basename = "usdiv";
-  usdiv_optab->libcall_suffix = '3';
-  usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  sdivmod_optab->libcall_basename = "divmod";
-  sdivmod_optab->libcall_suffix = '4';
-  sdivmod_optab->libcall_gen = gen_int_libfunc;
-  udivmod_optab->libcall_basename = "udivmod";
-  udivmod_optab->libcall_suffix = '4';
-  udivmod_optab->libcall_gen = gen_int_libfunc;
-  smod_optab->libcall_basename = "mod";
-  smod_optab->libcall_suffix = '3';
-  smod_optab->libcall_gen = gen_int_libfunc;
-  umod_optab->libcall_basename = "umod";
-  umod_optab->libcall_suffix = '3';
-  umod_optab->libcall_gen = gen_int_libfunc;
-  ftrunc_optab->libcall_basename = "ftrunc";
-  ftrunc_optab->libcall_suffix = '2';
-  ftrunc_optab->libcall_gen = gen_fp_libfunc;
-  and_optab->libcall_basename = "and";
-  and_optab->libcall_suffix = '3';
-  and_optab->libcall_gen = gen_int_libfunc;
-  ior_optab->libcall_basename = "ior";
-  ior_optab->libcall_suffix = '3';
-  ior_optab->libcall_gen = gen_int_libfunc;
-  xor_optab->libcall_basename = "xor";
-  xor_optab->libcall_suffix = '3';
-  xor_optab->libcall_gen = gen_int_libfunc;
-  ashl_optab->libcall_basename = "ashl";
-  ashl_optab->libcall_suffix = '3';
-  ashl_optab->libcall_gen = gen_int_fixed_libfunc;
-  ssashl_optab->libcall_basename = "ssashl";
-  ssashl_optab->libcall_suffix = '3';
-  ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
-  usashl_optab->libcall_basename = "usashl";
-  usashl_optab->libcall_suffix = '3';
-  usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  ashr_optab->libcall_basename = "ashr";
-  ashr_optab->libcall_suffix = '3';
-  ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
-  lshr_optab->libcall_basename = "lshr";
-  lshr_optab->libcall_suffix = '3';
-  lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
-  smin_optab->libcall_basename = "min";
-  smin_optab->libcall_suffix = '3';
-  smin_optab->libcall_gen = gen_int_fp_libfunc;
-  smax_optab->libcall_basename = "max";
-  smax_optab->libcall_suffix = '3';
-  smax_optab->libcall_gen = gen_int_fp_libfunc;
-  umin_optab->libcall_basename = "umin";
-  umin_optab->libcall_suffix = '3';
-  umin_optab->libcall_gen = gen_int_libfunc;
-  umax_optab->libcall_basename = "umax";
-  umax_optab->libcall_suffix = '3';
-  umax_optab->libcall_gen = gen_int_libfunc;
-  neg_optab->libcall_basename = "neg";
-  neg_optab->libcall_suffix = '2';
-  neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
-  ssneg_optab->libcall_basename = "ssneg";
-  ssneg_optab->libcall_suffix = '2';
-  ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
-  usneg_optab->libcall_basename = "usneg";
-  usneg_optab->libcall_suffix = '2';
-  usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
-  negv_optab->libcall_basename = "neg";
-  negv_optab->libcall_suffix = '2';
-  negv_optab->libcall_gen = gen_intv_fp_libfunc;
-  one_cmpl_optab->libcall_basename = "one_cmpl";
-  one_cmpl_optab->libcall_suffix = '2';
-  one_cmpl_optab->libcall_gen = gen_int_libfunc;
-  ffs_optab->libcall_basename = "ffs";
-  ffs_optab->libcall_suffix = '2';
-  ffs_optab->libcall_gen = gen_int_libfunc;
-  clz_optab->libcall_basename = "clz";
-  clz_optab->libcall_suffix = '2';
-  clz_optab->libcall_gen = gen_int_libfunc;
-  ctz_optab->libcall_basename = "ctz";
-  ctz_optab->libcall_suffix = '2';
-  ctz_optab->libcall_gen = gen_int_libfunc;
-  clrsb_optab->libcall_basename = "clrsb";
-  clrsb_optab->libcall_suffix = '2';
-  clrsb_optab->libcall_gen = gen_int_libfunc;
-  popcount_optab->libcall_basename = "popcount";
-  popcount_optab->libcall_suffix = '2';
-  popcount_optab->libcall_gen = gen_int_libfunc;
-  parity_optab->libcall_basename = "parity";
-  parity_optab->libcall_suffix = '2';
-  parity_optab->libcall_gen = gen_int_libfunc;
-
-  /* Comparison libcalls for integers MUST come in pairs,
-     signed/unsigned.  */
-  cmp_optab->libcall_basename = "cmp";
-  cmp_optab->libcall_suffix = '2';
-  cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
-  ucmp_optab->libcall_basename = "ucmp";
-  ucmp_optab->libcall_suffix = '2';
-  ucmp_optab->libcall_gen = gen_int_libfunc;
-
-  /* EQ etc are floating point only.  */
-  eq_optab->libcall_basename = "eq";
-  eq_optab->libcall_suffix = '2';
-  eq_optab->libcall_gen = gen_fp_libfunc;
-  ne_optab->libcall_basename = "ne";
-  ne_optab->libcall_suffix = '2';
-  ne_optab->libcall_gen = gen_fp_libfunc;
-  gt_optab->libcall_basename = "gt";
-  gt_optab->libcall_suffix = '2';
-  gt_optab->libcall_gen = gen_fp_libfunc;
-  ge_optab->libcall_basename = "ge";
-  ge_optab->libcall_suffix = '2';
-  ge_optab->libcall_gen = gen_fp_libfunc;
-  lt_optab->libcall_basename = "lt";
-  lt_optab->libcall_suffix = '2';
-  lt_optab->libcall_gen = gen_fp_libfunc;
-  le_optab->libcall_basename = "le";
-  le_optab->libcall_suffix = '2';
-  le_optab->libcall_gen = gen_fp_libfunc;
-  unord_optab->libcall_basename = "unord";
-  unord_optab->libcall_suffix = '2';
-  unord_optab->libcall_gen = gen_fp_libfunc;
-
-  powi_optab->libcall_basename = "powi";
-  powi_optab->libcall_suffix = '2';
-  powi_optab->libcall_gen = gen_fp_libfunc;
-
-  /* Conversions.  */
-  sfloat_optab->libcall_basename = "float";
-  sfloat_optab->libcall_gen = gen_int_to_fp_conv_libfunc;
-  ufloat_optab->libcall_gen = gen_ufloat_conv_libfunc;
-  sfix_optab->libcall_basename = "fix";
-  sfix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
-  ufix_optab->libcall_basename = "fixuns";
-  ufix_optab->libcall_gen = gen_fp_to_int_conv_libfunc;
-  lrint_optab->libcall_basename = "lrint";
-  lrint_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
-  lround_optab->libcall_basename = "lround";
-  lround_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
-  lfloor_optab->libcall_basename = "lfloor";
-  lfloor_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
-  lceil_optab->libcall_basename = "lceil";
-  lceil_optab->libcall_gen = gen_int_to_fp_nondecimal_conv_libfunc;
-
-  /* trunc_optab is also used for FLOAT_EXTEND.  */
-  sext_optab->libcall_basename = "extend";
-  sext_optab->libcall_gen = gen_extend_conv_libfunc;
-  trunc_optab->libcall_basename = "trunc";
-  trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
-
-  /* Conversions for fixed-point modes and other modes.  */
-  fract_optab->libcall_basename = "fract";
-  fract_optab->libcall_gen = gen_fract_conv_libfunc;
-  satfract_optab->libcall_basename = "satfract";
-  satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
-  fractuns_optab->libcall_basename = "fractuns";
-  fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
-  satfractuns_optab->libcall_basename = "satfractuns";
-  satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
-
   /* The ffs function operates on `int'.  Fall back on it if we do not
      have a libgcc2 function for that width.  */
   if (INT_TYPE_SIZE < BITS_PER_WORD)
@@ -6594,7 +6162,8 @@  init_optabs (void)
   /* Use cabs for double complex abs, since systems generally have cabs.
      Don't define any libcall for float complex, so that cabs will be used.  */
   if (complex_double_type_node)
-    set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node), "cabs");
+    set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
+		       "cabs");
 
   abort_libfunc = init_one_libfunc ("abort");
   memcpy_libfunc = init_one_libfunc ("memcpy");
@@ -6686,45 +6255,35 @@  init_sync_libfuncs (int max)
 DEBUG_FUNCTION void
 debug_optab_libfuncs (void)
 {
-  int i;
-  int j;
-  int k;
+  int i, j, k;
 
   /* Dump the arithmetic optabs.  */
-  for (i = 0; i != (int) OTI_MAX; i++)
+  for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       {
-	optab o;
-	rtx l;
-
-	o = &optab_table[i];
-	l = optab_libfunc (o, (enum machine_mode) j);
+	rtx l = optab_libfunc ((optab) i, (enum machine_mode) j);
 	if (l)
 	  {
 	    gcc_assert (GET_CODE (l) == SYMBOL_REF);
 	    fprintf (stderr, "%s\t%s:\t%s\n",
-		     GET_RTX_NAME (optab_to_code (o)),
+		     GET_RTX_NAME (optab_to_code ((optab) i)),
 		     GET_MODE_NAME (j),
 		     XSTR (l, 0));
 	  }
       }
 
   /* Dump the conversion optabs.  */
-  for (i = 0; i < (int) COI_MAX; ++i)
+  for (i = FIRST_CONV_OPTAB; i <= LAST_CONVLIB_OPTAB; ++i)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       for (k = 0; k < NUM_MACHINE_MODES; ++k)
 	{
-	  convert_optab o;
-	  rtx l;
-
-	  o = &convert_optab_table[i];
-	  l = convert_optab_libfunc (o, (enum machine_mode) j,
-				     (enum machine_mode) k);
+	  rtx l = convert_optab_libfunc ((optab) i, (enum machine_mode) j,
+					 (enum machine_mode) k);
 	  if (l)
 	    {
 	      gcc_assert (GET_CODE (l) == SYMBOL_REF);
 	      fprintf (stderr, "%s\t%s\t%s:\t%s\n",
-		       GET_RTX_NAME (optab_to_code (o)),
+		       GET_RTX_NAME (optab_to_code ((optab) i)),
 		       GET_MODE_NAME (j),
 		       GET_MODE_NAME (k),
 		       XSTR (l, 0));
diff --git a/gcc/optabs.def b/gcc/optabs.def
new file mode 100644
index 0000000..bdc028b
--- /dev/null
+++ b/gcc/optabs.def
@@ -0,0 +1,289 @@ 
+/* 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 extension libcalls are used for float extension.  */
+OPTAB_CL(sext_optab, "extend$b$a2", SIGN_EXTEND, "extend", gen_extend_conv_libfunc)
+OPTAB_CL(trunc_optab, "trunc$b$a2", TRUNCATE, "trunc", gen_trunc_conv_libfunc)
+OPTAB_CL(zext_optab, "zero_extend$b$a2", ZERO_EXTEND, NULL, NULL)
+
+OPTAB_CL(sfix_optab, "fix$F$b$I$a2", FIX, "fix", gen_fp_to_int_conv_libfunc)
+OPTAB_CL(ufix_optab, "fixuns$F$b$a2", UNSIGNED_FIX, "fixuns", gen_fp_to_int_conv_libfunc)
+OPTAB_CL(sfloat_optab, "float$I$b$F$a2", FLOAT, "float", gen_int_to_fp_conv_libfunc)
+OPTAB_CL(ufloat_optab, "floatuns$I$b$F$a2", UNSIGNED_FLOAT, NULL, gen_ufloat_conv_libfunc)
+
+OPTAB_CL(lrint_optab, "lrint$F$b$I$a2", UNKNOWN, "lrint", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lround_optab, "lround$F$b$I$a2", UNKNOWN, "lround", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lfloor_optab, "lfloor$F$b$I$a2", UNKNOWN, "lfloor", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lceil_optab, "lceil$F$b$I$a2", UNKNOWN, "lceil", gen_int_to_fp_nondecimal_conv_libfunc)
+
+/* Conversions for fixed-point modes and other modes.  */
+OPTAB_CL(fract_optab, "fract$b$a2", FRACT_CONVERT, "fract", gen_fract_conv_libfunc)
+OPTAB_CL(fractuns_optab, "fractuns$I$b$Q$a2", UNSIGNED_FRACT_CONVERT, "fractuns", gen_fractuns_conv_libfunc)
+OPTAB_CX(fractuns_optab, "fractuns$Q$b$I$a2")
+OPTAB_CL(satfract_optab, "satfract$b$Q$a2", SAT_FRACT, "satfract", gen_satfract_conv_libfunc)
+OPTAB_CL(satfractuns_optab, "satfractuns$I$b$Q$a2", UNSIGNED_SAT_FRACT, "satfractuns", gen_satfractuns_conv_libfunc)
+
+OPTAB_CD(sfixtrunc_optab, "fix_trunc$F$b$I$a2")
+OPTAB_CD(ufixtrunc_optab, "fixuns_trunc$F$b$I$a2")
+
+/* Misc optabs that use two modes; model them as "conversions".  */
+OPTAB_CD(smul_widen_optab, "mul$b$a3")
+OPTAB_CD(umul_widen_optab, "umul$b$a3")
+OPTAB_CD(usmul_widen_optab, "usmul$b$a3")
+OPTAB_CD(smadd_widen_optab, "madd$b$a4")
+OPTAB_CD(umadd_widen_optab, "umadd$b$a4")
+OPTAB_CD(ssmadd_widen_optab, "ssmadd$b$a4")
+OPTAB_CD(usmadd_widen_optab, "usmadd$b$a4")
+OPTAB_CD(smsub_widen_optab, "msub$b$a4")
+OPTAB_CD(umsub_widen_optab, "umsub$b$a4")
+OPTAB_CD(ssmsub_widen_optab, "ssmsub$b$a4")
+OPTAB_CD(usmsub_widen_optab, "usmsub$a$b4")
+OPTAB_CD(vec_load_lanes_optab, "vec_load_lanes$a$b")
+OPTAB_CD(vec_store_lanes_optab, "vec_store_lanes$a$b")
+OPTAB_CD(vcond_optab, "vcond$a$b")
+OPTAB_CD(vcondu_optab, "vcondu$a$b")
+
+OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(add_optab, "add$F$a3")
+OPTAB_NX(add_optab, "add$Q$a3")
+OPTAB_VL(addv_optab, "addv$I$a3", PLUS, "add", '3', gen_intv_fp_libfunc)
+OPTAB_VX(addv_optab, "add$F$a3")
+OPTAB_NL(ssadd_optab, "ssadd$Q$a3", SS_PLUS, "ssadd", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usadd_optab, "usadd$Q$a3", US_PLUS, "usadd", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(sub_optab, "sub$P$a3", MINUS, "sub", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(sub_optab, "sub$F$a3")
+OPTAB_NX(sub_optab, "sub$Q$a3")
+OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc)
+OPTAB_VX(subv_optab, "sub$F$a3")
+OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(smul_optab, "mul$P$a3")
+OPTAB_NX(smul_optab, "mul$F$a3")
+OPTAB_VL(smulv_optab, "mulv$I$a3", MULT, "mul", '3', gen_intv_fp_libfunc)
+OPTAB_VX(smulv_optab, "mul$F$a3")
+OPTAB_NL(ssmul_optab, "ssmul$Q$a3", SS_MULT, "ssmul", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usmul_optab, "usmul$Q$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(sdiv_optab, "div$a3", DIV, "div", '3', gen_int_fp_signed_fixed_libfunc)
+OPTAB_VL(sdivv_optab, "divv$I$a3", DIV, "divv", '3', gen_int_libfunc)
+OPTAB_VX(sdivv_optab, "div$F$a3")
+OPTAB_NL(ssdiv_optab, "ssdiv$Q$a3", SS_DIV, "ssdiv", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(udiv_optab, "udiv$I$a3", UDIV, "udiv", '3', gen_int_unsigned_fixed_libfunc)
+OPTAB_NX(udiv_optab, "udiv$Q$a3")
+OPTAB_NL(usdiv_optab, "usdiv$Q$a3", US_DIV, "usdiv", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(sdivmod_optab, "divmod$a4", UNKNOWN, "divmod", '4', gen_int_libfunc)
+OPTAB_NL(udivmod_optab, "udivmod$a4", UNKNOWN, "udivmod", '4', gen_int_libfunc)
+OPTAB_NL(smod_optab, "mod$a3", MOD, "mod", '3', gen_int_libfunc)
+OPTAB_NL(umod_optab, "umod$a3", UMOD, "umod", '3', gen_int_libfunc)
+OPTAB_NL(ftrunc_optab, "ftrunc$F$a2", UNKNOWN, "ftrunc", '2', gen_fp_libfunc)
+OPTAB_NL(and_optab, "and$a3", AND, "and", '3', gen_int_libfunc)
+OPTAB_NL(ior_optab, "ior$a3", IOR, "ior", '3', gen_int_libfunc)
+OPTAB_NL(xor_optab, "xor$a3", XOR, "xor", '3', gen_int_libfunc)
+OPTAB_NL(ashl_optab, "ashl$a3", ASHIFT, "ashl", '3', gen_int_fixed_libfunc)
+OPTAB_NL(ssashl_optab, "ssashl$Q$a3", SS_ASHIFT, "ssashl", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usashl_optab, "usashl$Q$a3", US_ASHIFT, "usashl", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(ashr_optab, "ashr$a3", ASHIFTRT, "ashr", '3', gen_int_signed_fixed_libfunc)
+OPTAB_NL(lshr_optab, "lshr$a3", LSHIFTRT, "lshr", '3', gen_int_unsigned_fixed_libfunc)
+OPTAB_NC(rotl_optab, "rotl$a3", ROTATE)
+OPTAB_NC(rotr_optab, "rotr$a3", ROTATERT)
+OPTAB_VC(vashl_optab, "vashl$a3", ASHIFT)
+OPTAB_VC(vashr_optab, "vashr$a3", ASHIFTRT)
+OPTAB_VC(vlshr_optab, "vlshr$a3", LSHIFTRT)
+OPTAB_VC(vrotl_optab, "vrotl$a3", ROTATE)
+OPTAB_VC(vrotr_optab, "vrotr$a3", ROTATERT)
+OPTAB_NL(smin_optab, "smin$a3", SMIN, "min", '3', gen_int_fp_libfunc)
+OPTAB_NL(smax_optab, "smax$a3", SMAX, "max", '3', gen_int_fp_libfunc)
+OPTAB_NL(umin_optab, "umin$I$a3", UMIN, "umin", '3', gen_int_libfunc)
+OPTAB_NL(umax_optab, "umax$I$a3", UMAX, "umax", '3', gen_int_libfunc)
+
+OPTAB_NL(neg_optab, "neg$P$a2", NEG, "neg", '2', gen_int_fp_fixed_libfunc)
+OPTAB_NX(neg_optab, "neg$F$a2")
+OPTAB_NX(neg_optab, "neg$Q$a2")
+OPTAB_VL(negv_optab, "negv$I$a2", NEG, "neg", '2', gen_intv_fp_libfunc)
+OPTAB_VX(negv_optab, "neg$F$a2")
+OPTAB_NL(ssneg_optab, "ssneg$Q$a2", SS_NEG, "ssneg", '2', gen_signed_fixed_libfunc)
+OPTAB_NL(usneg_optab, "usneg$Q$a2", US_NEG, "usneg", '2', gen_unsigned_fixed_libfunc)
+OPTAB_NC(abs_optab, "abs$P$a2", ABS)
+OPTAB_NX(abs_optab, "abs$F$a2")
+OPTAB_VC(absv_optab, "absv$I$a2", ABS)
+OPTAB_VX(absv_optab, "abs$F$a2")
+OPTAB_NL(one_cmpl_optab, "one_cmpl$a2", NOT, "one_cmpl", '2', gen_int_libfunc)
+OPTAB_NC(bswap_optab, "bswap$a2", BSWAP)
+OPTAB_NL(ffs_optab, "ffs$a2", FFS, "ffs", '2', gen_int_libfunc)
+OPTAB_NL(clz_optab, "clz$a2", CLZ, "clz", '2', gen_int_libfunc)
+OPTAB_NL(ctz_optab, "ctz$a2", CTZ, "ctz", '2', gen_int_libfunc)
+OPTAB_NL(clrsb_optab, "clrsb$a2", CLRSB, "clrsb", '2', gen_int_libfunc)
+OPTAB_NL(popcount_optab, "popcount$a2", POPCOUNT, "popcount", '2', gen_int_libfunc)
+OPTAB_NL(parity_optab, "parity$a2", PARITY, "parity", '2', gen_int_libfunc)
+
+/* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
+OPTAB_NL(cmp_optab, NULL, UNKNOWN, "cmp", '2', gen_int_fp_fixed_libfunc)
+OPTAB_NL(ucmp_optab, NULL, UNKNOWN, "ucmp", '2', gen_int_libfunc)
+
+/* EQ etc are floating point comparisons.  */
+OPTAB_NL(eq_optab, NULL, EQ, "eq", '2', gen_fp_libfunc)
+OPTAB_NL(ne_optab, NULL, NE, "ne", '2', gen_fp_libfunc)
+OPTAB_NL(gt_optab, NULL, GT, "gt", '2', gen_fp_libfunc)
+OPTAB_NL(ge_optab, NULL, GE, "ge", '2', gen_fp_libfunc)
+OPTAB_NL(lt_optab, NULL, LT, "lt", '2', gen_fp_libfunc)
+OPTAB_NL(le_optab, NULL, LE, "le", '2', gen_fp_libfunc)
+OPTAB_NL(unord_optab, NULL, UNORDERED, "unord", '2', gen_fp_libfunc)
+
+OPTAB_NL(powi_optab, NULL, UNKNOWN, "powi", '2', gen_fp_libfunc)
+
+/* These are all initialized individually, on a per-host basis.  */
+OPTAB_NC(sqrt_optab, "sqrt$a2", SQRT)
+OPTAB_NC(sync_old_add_optab, "sync_old_add$I$a", UNKNOWN)
+OPTAB_NC(sync_old_sub_optab, "sync_old_sub$I$a", UNKNOWN)
+OPTAB_NC(sync_old_ior_optab, "sync_old_ior$I$a", UNKNOWN)
+OPTAB_NC(sync_old_and_optab, "sync_old_and$I$a", UNKNOWN)
+OPTAB_NC(sync_old_xor_optab, "sync_old_xor$I$a", UNKNOWN)
+OPTAB_NC(sync_old_nand_optab, "sync_old_nand$I$a", UNKNOWN)
+OPTAB_NC(sync_new_add_optab, "sync_new_add$I$a", UNKNOWN)
+OPTAB_NC(sync_new_sub_optab, "sync_new_sub$I$a", UNKNOWN)
+OPTAB_NC(sync_new_ior_optab, "sync_new_ior$I$a", UNKNOWN)
+OPTAB_NC(sync_new_and_optab, "sync_new_and$I$a", UNKNOWN)
+OPTAB_NC(sync_new_xor_optab, "sync_new_xor$I$a", UNKNOWN)
+OPTAB_NC(sync_new_nand_optab, "sync_new_nand$I$a", UNKNOWN)
+OPTAB_NC(sync_compare_and_swap_optab, "sync_compare_and_swap$I$a", UNKNOWN)
+OPTAB_NC(sync_lock_test_and_set_optab, "sync_lock_test_and_set$I$a", UNKNOWN)
+
+OPTAB_DC(mov_optab, "mov$a", SET)
+OPTAB_DC(movstrict_optab, "movstrict$a", STRICT_LOW_PART)
+OPTAB_D (movmisalign_optab, "movmisalign$a")
+OPTAB_D (storent_optab, "storent$a")
+OPTAB_D (push_optab, "push$a1")
+OPTAB_D (reload_in_optab, "reload_in$a")
+OPTAB_D (reload_out_optab, "reload_out$a")
+
+OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE)
+OPTAB_D (addcc_optab, "add$acc")
+OPTAB_D (movcc_optab, "mov$acc")
+OPTAB_D (cmov_optab, "cmov$a6")
+OPTAB_D (cstore_optab, "cstore$a4")
+OPTAB_D (ctrap_optab, "ctrap$a4")
+
+OPTAB_D (smul_highpart_optab, "smul$a3_highpart")
+OPTAB_D (umul_highpart_optab, "umul$a3_highpart")
+
+OPTAB_D (cmpmem_optab, "cmpmem$a")
+OPTAB_D (cmpstr_optab, "cmpstr$a")
+OPTAB_D (cmpstrn_optab, "cmpstrn$a")
+OPTAB_D (movmem_optab, "movmem$a")
+OPTAB_D (setmem_optab, "setmem$a")
+OPTAB_D (strlen_optab, "strlen$a")
+
+OPTAB_DC(fma_optab, "fma$a4", FMA)
+OPTAB_D (fms_optab, "fms$a4")
+OPTAB_D (fnma_optab, "fnma$a4")
+OPTAB_D (fnms_optab, "fnms$a4")
+
+OPTAB_D (rint_optab, "rint$a2")
+OPTAB_D (round_optab, "round$a2")
+OPTAB_D (floor_optab, "floor$a2")
+OPTAB_D (ceil_optab, "ceil$a2")
+OPTAB_D (btrunc_optab, "btrunc$a2")
+OPTAB_D (nearbyint_optab, "nearbyint$a2")
+
+OPTAB_D (acos_optab, "acos$a2")
+OPTAB_D (asin_optab, "asin$a2")
+OPTAB_D (atan2_optab, "atan2$a3")
+OPTAB_D (atan_optab, "atan$a2")
+OPTAB_D (copysign_optab, "copysign$F$a3")
+OPTAB_D (cos_optab, "cos$a2")
+OPTAB_D (exp10_optab, "exp10$a2")
+OPTAB_D (exp2_optab, "exp2$a2")
+OPTAB_D (exp_optab, "exp$a2")
+OPTAB_D (expm1_optab, "expm1$a2")
+OPTAB_D (fmod_optab, "fmod$a3")
+OPTAB_D (ilogb_optab, "ilogb$a2")
+OPTAB_D (isinf_optab, "isinf$a2")
+OPTAB_D (ldexp_optab, "ldexp$a3")
+OPTAB_D (log10_optab, "log10$a2")
+OPTAB_D (log1p_optab, "log1p$a2")
+OPTAB_D (log2_optab, "log2$a2")
+OPTAB_D (log_optab, "log$a2")
+OPTAB_D (logb_optab, "logb$a2")
+OPTAB_D (pow_optab, "pow$a3")
+OPTAB_D (remainder_optab, "remainder$a3")
+OPTAB_D (scalb_optab, "scalb$a3")
+OPTAB_D (signbit_optab, "signbit$F$a2")
+OPTAB_D (significand_optab, "significand$a2")
+OPTAB_D (sin_optab, "sin$a2")
+OPTAB_D (sincos_optab, "sincos$a3")
+OPTAB_D (tan_optab, "tan$a2")
+
+OPTAB_D (reduc_smax_optab, "reduc_smax_$a")
+OPTAB_D (reduc_smin_optab, "reduc_smin_$a")
+OPTAB_D (reduc_splus_optab, "reduc_splus_$a")
+OPTAB_D (reduc_umax_optab, "reduc_umax_$a")
+OPTAB_D (reduc_umin_optab, "reduc_umin_$a")
+OPTAB_D (reduc_uplus_optab, "reduc_uplus_$a")
+OPTAB_D (sdot_prod_optab, "sdot_prod$I$a")
+OPTAB_D (ssum_widen_optab, "widen_ssum$I$a3")
+OPTAB_D (udot_prod_optab, "udot_prod$I$a")
+OPTAB_D (usum_widen_optab, "widen_usum$I$a3")
+OPTAB_D (vec_extract_optab, "vec_extract$a")
+OPTAB_D (vec_init_optab, "vec_init$a")
+OPTAB_D (vec_pack_sfix_trunc_optab, "vec_pack_sfix_trunc_$a")
+OPTAB_D (vec_pack_ssat_optab, "vec_pack_ssat_$a")
+OPTAB_D (vec_pack_trunc_optab, "vec_pack_trunc_$a")
+OPTAB_D (vec_pack_ufix_trunc_optab, "vec_pack_ufix_trunc_$a")
+OPTAB_D (vec_pack_usat_optab, "vec_pack_usat_$a")
+OPTAB_D (vec_perm_const_optab, "vec_perm_const$a")
+OPTAB_D (vec_perm_optab, "vec_perm$a")
+OPTAB_D (vec_realign_load_optab, "vec_realign_load_$a")
+OPTAB_D (vec_set_optab, "vec_set$a")
+OPTAB_D (vec_shl_optab, "vec_shl_$a")
+OPTAB_D (vec_shr_optab, "vec_shr_$a")
+OPTAB_D (vec_unpacks_float_hi_optab, "vec_unpacks_float_hi_$a")
+OPTAB_D (vec_unpacks_float_lo_optab, "vec_unpacks_float_lo_$a")
+OPTAB_D (vec_unpacks_hi_optab, "vec_unpacks_hi_$a")
+OPTAB_D (vec_unpacks_lo_optab, "vec_unpacks_lo_$a")
+OPTAB_D (vec_unpacku_float_hi_optab, "vec_unpacku_float_hi_$a")
+OPTAB_D (vec_unpacku_float_lo_optab, "vec_unpacku_float_lo_$a")
+OPTAB_D (vec_unpacku_hi_optab, "vec_unpacku_hi_$a")
+OPTAB_D (vec_unpacku_lo_optab, "vec_unpacku_lo_$a")
+OPTAB_D (vec_widen_smult_even_optab, "vec_widen_smult_even_$a")
+OPTAB_D (vec_widen_smult_hi_optab, "vec_widen_smult_hi_$a")
+OPTAB_D (vec_widen_smult_lo_optab, "vec_widen_smult_lo_$a")
+OPTAB_D (vec_widen_smult_odd_optab, "vec_widen_smult_odd_$a")
+OPTAB_D (vec_widen_sshiftl_hi_optab, "vec_widen_sshiftl_hi_$a")
+OPTAB_D (vec_widen_sshiftl_lo_optab, "vec_widen_sshiftl_lo_$a")
+OPTAB_D (vec_widen_umult_even_optab, "vec_widen_umult_even_$a")
+OPTAB_D (vec_widen_umult_hi_optab, "vec_widen_umult_hi_$a")
+OPTAB_D (vec_widen_umult_lo_optab, "vec_widen_umult_lo_$a")
+OPTAB_D (vec_widen_umult_odd_optab, "vec_widen_umult_odd_$a")
+OPTAB_D (vec_widen_ushiftl_hi_optab, "vec_widen_ushiftl_hi_$a")
+OPTAB_D (vec_widen_ushiftl_lo_optab, "vec_widen_ushiftl_lo_$a")
+
+OPTAB_D (sync_add_optab, "sync_add$I$a")
+OPTAB_D (sync_and_optab, "sync_and$I$a")
+OPTAB_D (sync_ior_optab, "sync_ior$I$a")
+OPTAB_D (sync_lock_release_optab, "sync_lock_release$I$a")
+OPTAB_D (sync_nand_optab, "sync_nand$I$a")
+OPTAB_D (sync_sub_optab, "sync_sub$I$a")
+OPTAB_D (sync_xor_optab, "sync_xor$I$a")
+
+OPTAB_D (atomic_add_fetch_optab, "atomic_add_fetch$I$a")
+OPTAB_D (atomic_add_optab, "atomic_add$I$a")
+OPTAB_D (atomic_and_fetch_optab, "atomic_and_fetch$I$a")
+OPTAB_D (atomic_and_optab, "atomic_and$I$a")
+OPTAB_D (atomic_compare_and_swap_optab, "atomic_compare_and_swap$I$a")
+OPTAB_D (atomic_exchange_optab,	 "atomic_exchange$I$a")
+OPTAB_D (atomic_fetch_add_optab, "atomic_fetch_add$I$a")
+OPTAB_D (atomic_fetch_and_optab, "atomic_fetch_and$I$a")
+OPTAB_D (atomic_fetch_nand_optab, "atomic_fetch_nand$I$a")
+OPTAB_D (atomic_fetch_or_optab, "atomic_fetch_or$I$a")
+OPTAB_D (atomic_fetch_sub_optab, "atomic_fetch_sub$I$a")
+OPTAB_D (atomic_fetch_xor_optab, "atomic_fetch_xor$I$a")
+OPTAB_D (atomic_load_optab, "atomic_load$I$a")
+OPTAB_D (atomic_nand_fetch_optab, "atomic_nand_fetch$I$a")
+OPTAB_D (atomic_nand_optab, "atomic_nand$I$a")
+OPTAB_D (atomic_or_fetch_optab, "atomic_or_fetch$I$a")
+OPTAB_D (atomic_or_optab, "atomic_or$I$a")
+OPTAB_D (atomic_store_optab, "atomic_store$I$a")
+OPTAB_D (atomic_sub_fetch_optab, "atomic_sub_fetch$I$a")
+OPTAB_D (atomic_sub_optab, "atomic_sub$I$a")
+OPTAB_D (atomic_xor_fetch_optab, "atomic_xor_fetch$I$a")
+OPTAB_D (atomic_xor_optab, "atomic_xor$I$a")
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 60f83cf..e0be2ba 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -22,656 +22,34 @@  along with GCC; see the file COPYING3.  If not see
 #define GCC_OPTABS_H
 
 #include "insn-codes.h"
+#include "insn-opinit.h"
 
-/* Optabs are tables saying how to generate insn bodies
-   for various machine modes and numbers of operands.
-   Each optab applies to one operation.
+typedef enum optab_tag optab;
+typedef enum optab_tag convert_optab;
+typedef enum optab_tag direct_optab;
 
-   For example, add_optab applies to addition.
-
-   The insn_code slot is the enum insn_code that says how to
-   generate an insn for this operation on a particular machine mode.
-   It is CODE_FOR_nothing if there is no such insn on the target machine.
-
-   The `lib_call' slot is the name of the library function that
-   can be used to perform the operation.
-
-   A few optabs, such as move_optab, are used by special code.  */
-
-struct optab_handlers
-{
-  enum insn_code insn_code;
-};
-
-struct widening_optab_handlers
-{
-  struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
-};
-
-struct optab_d
+struct optab_libcall_d
 {
-  enum rtx_code code_;
   char libcall_suffix;
   const char *libcall_basename;
-  void (*libcall_gen)(struct optab_d *, const char *name, char suffix,
-		      enum machine_mode);
-  struct optab_handlers handlers[NUM_MACHINE_MODES];
-  struct widening_optab_handlers *widening;
+  void (*libcall_gen) (optab, const char *name,
+		       char suffix, enum machine_mode);
 };
-typedef struct optab_d * optab;
 
-/* A convert_optab is for some sort of conversion operation between
-   modes.  The first array index is the destination mode, the second
-   is the source mode.  */
-struct convert_optab_d
+struct convert_optab_libcall_d
 {
-  enum rtx_code code_;
   const char *libcall_basename;
-  void (*libcall_gen)(struct convert_optab_d *, const char *name,
-		      enum machine_mode,
-		      enum machine_mode);
-  struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+  void (*libcall_gen) (convert_optab, const char *name,
+		       enum machine_mode, enum machine_mode);
 };
-typedef struct convert_optab_d *convert_optab;
 
 /* Given an enum insn_code, access the function to construct
    the body of that kind of insn.  */
 #define GEN_FCN(CODE) (insn_data[CODE].genfun)
 
-/* Enumeration of valid indexes into optab_table.  */
-enum optab_index
-{
-  /* Fixed-point operators with signed/unsigned saturation */
-  OTI_ssadd,
-  OTI_usadd,
-  OTI_sssub,
-  OTI_ussub,
-  OTI_ssmul,
-  OTI_usmul,
-  OTI_ssdiv,
-  OTI_usdiv,
-  OTI_ssneg,
-  OTI_usneg,
-  OTI_ssashl,
-  OTI_usashl,
-
-  OTI_add,
-  OTI_addv,
-  OTI_sub,
-  OTI_subv,
-
-  /* Signed and fp multiply */
-  OTI_smul,
-  OTI_smulv,
-  /* Signed multiply, return high word */
-  OTI_smul_highpart,
-  OTI_umul_highpart,
-  /* Signed multiply with result one machine mode wider than args */
-  OTI_smul_widen,
-  OTI_umul_widen,
-  /* Widening multiply of one unsigned and one signed operand.  */
-  OTI_usmul_widen,
-  /* Signed multiply and add with the result and addend one machine mode
-     wider than the multiplicand and multiplier.  */
-  OTI_smadd_widen,
-  /* Unsigned multiply and add with the result and addend one machine mode
-     wider than the multiplicand and multiplier.  */
-  OTI_umadd_widen,
-  /* Signed multiply and add with the result and addend one machine mode
-     wider than the multiplicand and multiplier.
-     All involved operations are saturating.  */
-  OTI_ssmadd_widen,
-  /* Unsigned multiply and add with the result and addend one machine mode
-     wider than the multiplicand and multiplier.
-     All involved operations are saturating.  */
-  OTI_usmadd_widen,
-  /* Signed multiply and subtract the result and minuend one machine mode
-     wider than the multiplicand and multiplier.  */
-  OTI_smsub_widen,
-  /* Unsigned multiply and subtract the result and minuend one machine mode
-     wider than the multiplicand and multiplier.  */
-  OTI_umsub_widen,
-  /* Signed multiply and subtract the result and minuend one machine mode
-     wider than the multiplicand and multiplier.
-     All involved operations are saturating.  */
-  OTI_ssmsub_widen,
-  /* Unsigned multiply and subtract the result and minuend one machine mode
-     wider than the multiplicand and multiplier.
-     All involved operations are saturating.  */
-  OTI_usmsub_widen,
-
-  /* Signed divide */
-  OTI_sdiv,
-  OTI_sdivv,
-  /* Signed divide-and-remainder in one */
-  OTI_sdivmod,
-  OTI_udiv,
-  OTI_udivmod,
-  /* Signed remainder */
-  OTI_smod,
-  OTI_umod,
-  /* Floating point remainder functions */
-  OTI_fmod,
-  OTI_remainder,
-  /* Convert float to integer in float fmt */
-  OTI_ftrunc,
-
-  /* Logical and */
-  OTI_and,
-  /* Logical or */
-  OTI_ior,
-  /* Logical xor */
-  OTI_xor,
-
-  /* Arithmetic shift left */
-  OTI_ashl,
-  /* Logical shift right */
-  OTI_lshr,
-  /* Arithmetic shift right */
-  OTI_ashr,
-  /* Rotate left */
-  OTI_rotl,
-  /* Rotate right */
-  OTI_rotr,
-
-  /* Arithmetic shift left of vector by vector */
-  OTI_vashl,
-  /* Logical shift right of vector by vector */
-  OTI_vlshr,
-  /* Arithmetic shift right of vector by vector */
-  OTI_vashr,
-  /* Rotate left of vector by vector */
-  OTI_vrotl,
-  /* Rotate right of vector by vector */
-  OTI_vrotr,
-
-  /* Signed and floating-point minimum value */
-  OTI_smin,
-  /* Signed and floating-point maximum value */
-  OTI_smax,
-  /* Unsigned minimum value */
-  OTI_umin,
-  /* Unsigned maximum value */
-  OTI_umax,
-  /* Power */
-  OTI_pow,
-  /* Arc tangent of y/x */
-  OTI_atan2,
-  /* Floating multiply/add */
-  OTI_fma,
-  OTI_fms,
-  OTI_fnma,
-  OTI_fnms,
-
-  /* Move instruction.  */
-  OTI_mov,
-  /* Move, preserving high part of register.  */
-  OTI_movstrict,
-  /* Move, with a misaligned memory.  */
-  OTI_movmisalign,
-  /* Nontemporal store.  */
-  OTI_storent,
-
-  /* Unary operations */
-  /* Negation */
-  OTI_neg,
-  OTI_negv,
-  /* Abs value */
-  OTI_abs,
-  OTI_absv,
-  /* Byteswap */
-  OTI_bswap,
-  /* Bitwise not */
-  OTI_one_cmpl,
-  /* Bit scanning and counting */
-  OTI_ffs,
-  OTI_clz,
-  OTI_ctz,
-  OTI_clrsb,
-  OTI_popcount,
-  OTI_parity,
-  /* Square root */
-  OTI_sqrt,
-  /* Sine-Cosine */
-  OTI_sincos,
-  /* Sine */
-  OTI_sin,
-  /* Inverse sine */
-  OTI_asin,
-  /* Cosine */
-  OTI_cos,
-  /* Inverse cosine */
-  OTI_acos,
-  /* Exponential */
-  OTI_exp,
-  /* Base-10 Exponential */
-  OTI_exp10,
-  /* Base-2 Exponential */
-  OTI_exp2,
-  /* Exponential - 1*/
-  OTI_expm1,
-  /* Load exponent of a floating point number */
-  OTI_ldexp,
-  /* Multiply floating-point number by integral power of radix */
-  OTI_scalb,
-  /* Mantissa of a floating-point number */
-  OTI_significand,
-  /* Radix-independent exponent */
-  OTI_logb,
-  OTI_ilogb,
-  /* Natural Logarithm */
-  OTI_log,
-  /* Base-10 Logarithm */
-  OTI_log10,
-  /* Base-2 Logarithm */
-  OTI_log2,
-  /* logarithm of 1 plus argument */
-  OTI_log1p,
-  /* Rounding functions */
-  OTI_floor,
-  OTI_ceil,
-  OTI_btrunc,
-  OTI_round,
-  OTI_nearbyint,
-  OTI_rint,
-  /* Tangent */
-  OTI_tan,
-  /* Inverse tangent */
-  OTI_atan,
-  /* Copy sign */
-  OTI_copysign,
-  /* Signbit */
-  OTI_signbit,
-  /* Test for infinite value */
-  OTI_isinf,
-
-  /* Compare insn; two operands.  Used only for libcalls.  */
-  OTI_cmp,
-  OTI_ucmp,
-
-  /* Floating point comparison optabs - used primarily for libfuncs */
-  OTI_eq,
-  OTI_ne,
-  OTI_gt,
-  OTI_ge,
-  OTI_lt,
-  OTI_le,
-  OTI_unord,
-
-  /* String length */
-  OTI_strlen,
-
-  /* Combined compare & jump/move/store flags/trap operations.  */
-  OTI_cbranch,
-  OTI_cmov,
-  OTI_cstore,
-  OTI_ctrap,
-
-  /* Push instruction.  */
-  OTI_push,
-
-  /* Conditional add instruction.  */
-  OTI_addcc,
-
-  /* Reduction operations on a vector operand.  */
-  OTI_reduc_smax,
-  OTI_reduc_umax,
-  OTI_reduc_smin,
-  OTI_reduc_umin,
-  OTI_reduc_splus,
-  OTI_reduc_uplus,
-
-  /* Summation, with result machine mode one or more wider than args.  */
-  OTI_ssum_widen,
-  OTI_usum_widen,
-
-  /* Dot product, with result machine mode one or more wider than args.  */
-  OTI_sdot_prod,
-  OTI_udot_prod,
-
-  /* Set specified field of vector operand.  */
-  OTI_vec_set,
-  /* Extract specified field of vector operand.  */
-  OTI_vec_extract,
-  /* Initialize vector operand.  */
-  OTI_vec_init,
-  /* Whole vector shift. The shift amount is in bits.  */
-  OTI_vec_shl,
-  OTI_vec_shr,
-  /* Extract specified elements from vectors, for vector load.  */
-  OTI_vec_realign_load,
-  /* Widening multiplication.  The high/low/even/odd part of the
-     resulting vector of products is returned.  */
-  OTI_vec_widen_umult_hi,
-  OTI_vec_widen_umult_lo,
-  OTI_vec_widen_smult_hi,
-  OTI_vec_widen_smult_lo,
-  OTI_vec_widen_umult_even,
-  OTI_vec_widen_umult_odd,
-  OTI_vec_widen_smult_even,
-  OTI_vec_widen_smult_odd,
-  /* Widening shift left.
-     The high/low part of the resulting vector is returned.  */
-  OTI_vec_widen_ushiftl_hi,
-  OTI_vec_widen_ushiftl_lo,
-  OTI_vec_widen_sshiftl_hi,
-  OTI_vec_widen_sshiftl_lo,
-  /* Extract and widen the high/low part of a vector of signed or
-     floating point elements.  */
-  OTI_vec_unpacks_hi,
-  OTI_vec_unpacks_lo,
-  /* Extract and widen the high/low part of a vector of unsigned
-     elements.  */
-  OTI_vec_unpacku_hi,
-  OTI_vec_unpacku_lo,
-
-  /* Extract, convert to floating point and widen the high/low part of
-     a vector of signed or unsigned integer elements.  */
-  OTI_vec_unpacks_float_hi,
-  OTI_vec_unpacks_float_lo,
-  OTI_vec_unpacku_float_hi,
-  OTI_vec_unpacku_float_lo,
-
-  /* Narrow (demote) and merge the elements of two vectors.  */
-  OTI_vec_pack_trunc,
-  OTI_vec_pack_usat,
-  OTI_vec_pack_ssat,
-
-  /* Convert to signed/unsigned integer, narrow and merge elements
-     of two vectors of floating point elements.  */
-  OTI_vec_pack_sfix_trunc,
-  OTI_vec_pack_ufix_trunc,
-
-  /* Perform a raise to the power of integer.  */
-  OTI_powi,
-
-  /* Atomic compare and swap.  */
-  OTI_sync_compare_and_swap,
-
-  /* Atomic exchange with acquire semantics.  */
-  OTI_sync_lock_test_and_set,
-
-  /* This second set is atomic operations in which we return the value
-     that existed in memory before the operation.  */
-  OTI_sync_old_add,
-  OTI_sync_old_sub,
-  OTI_sync_old_ior,
-  OTI_sync_old_and,
-  OTI_sync_old_xor,
-  OTI_sync_old_nand,
-
-  /* This third set is atomic operations in which we return the value
-     that resulted after performing the operation.  */
-  OTI_sync_new_add,
-  OTI_sync_new_sub,
-  OTI_sync_new_ior,
-  OTI_sync_new_and,
-  OTI_sync_new_xor,
-  OTI_sync_new_nand,
-
-  OTI_MAX
-};
-
-#define unknown_optab NULL
-
-#define ssadd_optab (&optab_table[OTI_ssadd])
-#define usadd_optab (&optab_table[OTI_usadd])
-#define sssub_optab (&optab_table[OTI_sssub])
-#define ussub_optab (&optab_table[OTI_ussub])
-#define ssmul_optab (&optab_table[OTI_ssmul])
-#define usmul_optab (&optab_table[OTI_usmul])
-#define ssdiv_optab (&optab_table[OTI_ssdiv])
-#define usdiv_optab (&optab_table[OTI_usdiv])
-#define ssneg_optab (&optab_table[OTI_ssneg])
-#define usneg_optab (&optab_table[OTI_usneg])
-#define ssashl_optab (&optab_table[OTI_ssashl])
-#define usashl_optab (&optab_table[OTI_usashl])
-
-#define add_optab (&optab_table[OTI_add])
-#define sub_optab (&optab_table[OTI_sub])
-#define smul_optab (&optab_table[OTI_smul])
-#define addv_optab (&optab_table[OTI_addv])
-#define subv_optab (&optab_table[OTI_subv])
-#define smul_highpart_optab (&optab_table[OTI_smul_highpart])
-#define umul_highpart_optab (&optab_table[OTI_umul_highpart])
-#define smul_widen_optab (&optab_table[OTI_smul_widen])
-#define umul_widen_optab (&optab_table[OTI_umul_widen])
-#define usmul_widen_optab (&optab_table[OTI_usmul_widen])
-#define smadd_widen_optab (&optab_table[OTI_smadd_widen])
-#define umadd_widen_optab (&optab_table[OTI_umadd_widen])
-#define ssmadd_widen_optab (&optab_table[OTI_ssmadd_widen])
-#define usmadd_widen_optab (&optab_table[OTI_usmadd_widen])
-#define smsub_widen_optab (&optab_table[OTI_smsub_widen])
-#define umsub_widen_optab (&optab_table[OTI_umsub_widen])
-#define ssmsub_widen_optab (&optab_table[OTI_ssmsub_widen])
-#define usmsub_widen_optab (&optab_table[OTI_usmsub_widen])
-#define sdiv_optab (&optab_table[OTI_sdiv])
-#define smulv_optab (&optab_table[OTI_smulv])
-#define sdivv_optab (&optab_table[OTI_sdivv])
-#define sdivmod_optab (&optab_table[OTI_sdivmod])
-#define udiv_optab (&optab_table[OTI_udiv])
-#define udivmod_optab (&optab_table[OTI_udivmod])
-#define smod_optab (&optab_table[OTI_smod])
-#define umod_optab (&optab_table[OTI_umod])
-#define fmod_optab (&optab_table[OTI_fmod])
-#define remainder_optab (&optab_table[OTI_remainder])
-#define ftrunc_optab (&optab_table[OTI_ftrunc])
-#define and_optab (&optab_table[OTI_and])
-#define ior_optab (&optab_table[OTI_ior])
-#define xor_optab (&optab_table[OTI_xor])
-#define ashl_optab (&optab_table[OTI_ashl])
-#define lshr_optab (&optab_table[OTI_lshr])
-#define ashr_optab (&optab_table[OTI_ashr])
-#define rotl_optab (&optab_table[OTI_rotl])
-#define rotr_optab (&optab_table[OTI_rotr])
-#define vashl_optab (&optab_table[OTI_vashl])
-#define vlshr_optab (&optab_table[OTI_vlshr])
-#define vashr_optab (&optab_table[OTI_vashr])
-#define vrotl_optab (&optab_table[OTI_vrotl])
-#define vrotr_optab (&optab_table[OTI_vrotr])
-#define smin_optab (&optab_table[OTI_smin])
-#define smax_optab (&optab_table[OTI_smax])
-#define umin_optab (&optab_table[OTI_umin])
-#define umax_optab (&optab_table[OTI_umax])
-#define pow_optab (&optab_table[OTI_pow])
-#define atan2_optab (&optab_table[OTI_atan2])
-#define fma_optab (&optab_table[OTI_fma])
-#define fms_optab (&optab_table[OTI_fms])
-#define fnma_optab (&optab_table[OTI_fnma])
-#define fnms_optab (&optab_table[OTI_fnms])
-
-#define mov_optab (&optab_table[OTI_mov])
-#define movstrict_optab (&optab_table[OTI_movstrict])
-#define movmisalign_optab (&optab_table[OTI_movmisalign])
-#define storent_optab (&optab_table[OTI_storent])
-
-#define neg_optab (&optab_table[OTI_neg])
-#define negv_optab (&optab_table[OTI_negv])
-#define abs_optab (&optab_table[OTI_abs])
-#define absv_optab (&optab_table[OTI_absv])
-#define one_cmpl_optab (&optab_table[OTI_one_cmpl])
-#define bswap_optab (&optab_table[OTI_bswap])
-#define ffs_optab (&optab_table[OTI_ffs])
-#define clz_optab (&optab_table[OTI_clz])
-#define ctz_optab (&optab_table[OTI_ctz])
-#define clrsb_optab (&optab_table[OTI_clrsb])
-#define popcount_optab (&optab_table[OTI_popcount])
-#define parity_optab (&optab_table[OTI_parity])
-#define sqrt_optab (&optab_table[OTI_sqrt])
-#define sincos_optab (&optab_table[OTI_sincos])
-#define sin_optab (&optab_table[OTI_sin])
-#define asin_optab (&optab_table[OTI_asin])
-#define cos_optab (&optab_table[OTI_cos])
-#define acos_optab (&optab_table[OTI_acos])
-#define exp_optab (&optab_table[OTI_exp])
-#define exp10_optab (&optab_table[OTI_exp10])
-#define exp2_optab (&optab_table[OTI_exp2])
-#define expm1_optab (&optab_table[OTI_expm1])
-#define ldexp_optab (&optab_table[OTI_ldexp])
-#define scalb_optab (&optab_table[OTI_scalb])
-#define significand_optab (&optab_table[OTI_significand])
-#define logb_optab (&optab_table[OTI_logb])
-#define ilogb_optab (&optab_table[OTI_ilogb])
-#define log_optab (&optab_table[OTI_log])
-#define log10_optab (&optab_table[OTI_log10])
-#define log2_optab (&optab_table[OTI_log2])
-#define log1p_optab (&optab_table[OTI_log1p])
-#define floor_optab (&optab_table[OTI_floor])
-#define ceil_optab (&optab_table[OTI_ceil])
-#define btrunc_optab (&optab_table[OTI_btrunc])
-#define round_optab (&optab_table[OTI_round])
-#define nearbyint_optab (&optab_table[OTI_nearbyint])
-#define rint_optab (&optab_table[OTI_rint])
-#define tan_optab (&optab_table[OTI_tan])
-#define atan_optab (&optab_table[OTI_atan])
-#define copysign_optab (&optab_table[OTI_copysign])
-#define signbit_optab (&optab_table[OTI_signbit])
-#define isinf_optab (&optab_table[OTI_isinf])
-
-#define cmp_optab (&optab_table[OTI_cmp])
-#define ucmp_optab (&optab_table[OTI_ucmp])
-
-#define eq_optab (&optab_table[OTI_eq])
-#define ne_optab (&optab_table[OTI_ne])
-#define gt_optab (&optab_table[OTI_gt])
-#define ge_optab (&optab_table[OTI_ge])
-#define lt_optab (&optab_table[OTI_lt])
-#define le_optab (&optab_table[OTI_le])
-#define unord_optab (&optab_table[OTI_unord])
-
-#define strlen_optab (&optab_table[OTI_strlen])
-
-#define cbranch_optab (&optab_table[OTI_cbranch])
-#define cmov_optab (&optab_table[OTI_cmov])
-#define cstore_optab (&optab_table[OTI_cstore])
-#define ctrap_optab (&optab_table[OTI_ctrap])
-
-#define push_optab (&optab_table[OTI_push])
-#define addcc_optab (&optab_table[OTI_addcc])
-
-#define reduc_smax_optab (&optab_table[OTI_reduc_smax])
-#define reduc_umax_optab (&optab_table[OTI_reduc_umax])
-#define reduc_smin_optab (&optab_table[OTI_reduc_smin])
-#define reduc_umin_optab (&optab_table[OTI_reduc_umin])
-#define reduc_splus_optab (&optab_table[OTI_reduc_splus])
-#define reduc_uplus_optab (&optab_table[OTI_reduc_uplus])
-
-#define ssum_widen_optab (&optab_table[OTI_ssum_widen])
-#define usum_widen_optab (&optab_table[OTI_usum_widen])
-#define sdot_prod_optab (&optab_table[OTI_sdot_prod])
-#define udot_prod_optab (&optab_table[OTI_udot_prod])
-
-#define vec_set_optab (&optab_table[OTI_vec_set])
-#define vec_extract_optab (&optab_table[OTI_vec_extract])
-#define vec_init_optab (&optab_table[OTI_vec_init])
-#define vec_shl_optab (&optab_table[OTI_vec_shl])
-#define vec_shr_optab (&optab_table[OTI_vec_shr])
-#define vec_realign_load_optab (&optab_table[OTI_vec_realign_load])
-#define vec_widen_umult_hi_optab (&optab_table[OTI_vec_widen_umult_hi])
-#define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
-#define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
-#define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
-#define vec_widen_umult_even_optab (&optab_table[OTI_vec_widen_umult_even])
-#define vec_widen_umult_odd_optab (&optab_table[OTI_vec_widen_umult_odd])
-#define vec_widen_smult_even_optab (&optab_table[OTI_vec_widen_smult_even])
-#define vec_widen_smult_odd_optab (&optab_table[OTI_vec_widen_smult_odd])
-#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
-#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
-#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])
-#define vec_widen_sshiftl_lo_optab (&optab_table[OTI_vec_widen_sshiftl_lo])
-#define vec_unpacks_hi_optab (&optab_table[OTI_vec_unpacks_hi])
-#define vec_unpacks_lo_optab (&optab_table[OTI_vec_unpacks_lo])
-#define vec_unpacku_hi_optab (&optab_table[OTI_vec_unpacku_hi])
-#define vec_unpacku_lo_optab (&optab_table[OTI_vec_unpacku_lo])
-#define vec_unpacks_float_hi_optab (&optab_table[OTI_vec_unpacks_float_hi])
-#define vec_unpacks_float_lo_optab (&optab_table[OTI_vec_unpacks_float_lo])
-#define vec_unpacku_float_hi_optab (&optab_table[OTI_vec_unpacku_float_hi])
-#define vec_unpacku_float_lo_optab (&optab_table[OTI_vec_unpacku_float_lo])
-#define vec_pack_trunc_optab (&optab_table[OTI_vec_pack_trunc])
-#define vec_pack_ssat_optab (&optab_table[OTI_vec_pack_ssat])
-#define vec_pack_usat_optab (&optab_table[OTI_vec_pack_usat])
-#define vec_pack_sfix_trunc_optab (&optab_table[OTI_vec_pack_sfix_trunc])
-#define vec_pack_ufix_trunc_optab (&optab_table[OTI_vec_pack_ufix_trunc])
-
-#define powi_optab (&optab_table[OTI_powi])
-
-#define sync_compare_and_swap_optab \
-  (&optab_table[(int) OTI_sync_compare_and_swap])
-#define sync_lock_test_and_set_optab \
-  (&optab_table[(int) OTI_sync_lock_test_and_set])
-#define sync_old_add_optab (&optab_table[(int) OTI_sync_old_add])
-#define sync_old_sub_optab (&optab_table[(int) OTI_sync_old_sub])
-#define sync_old_ior_optab (&optab_table[(int) OTI_sync_old_ior])
-#define sync_old_and_optab (&optab_table[(int) OTI_sync_old_and])
-#define sync_old_xor_optab (&optab_table[(int) OTI_sync_old_xor])
-#define sync_old_nand_optab (&optab_table[(int) OTI_sync_old_nand])
-#define sync_new_add_optab (&optab_table[(int) OTI_sync_new_add])
-#define sync_new_sub_optab (&optab_table[(int) OTI_sync_new_sub])
-#define sync_new_ior_optab (&optab_table[(int) OTI_sync_new_ior])
-#define sync_new_and_optab (&optab_table[(int) OTI_sync_new_and])
-#define sync_new_xor_optab (&optab_table[(int) OTI_sync_new_xor])
-#define sync_new_nand_optab (&optab_table[(int) OTI_sync_new_nand])
-
-/* Conversion optabs have their own table and indexes.  */
-enum convert_optab_index
-{
-  COI_sext,
-  COI_zext,
-  COI_trunc,
-
-  COI_sfix,
-  COI_ufix,
-
-  COI_sfixtrunc,
-  COI_ufixtrunc,
-
-  COI_sfloat,
-  COI_ufloat,
-
-  COI_lrint,
-  COI_lround,
-  COI_lfloor,
-  COI_lceil,
-
-  COI_fract,
-  COI_fractuns,
-  COI_satfract,
-  COI_satfractuns,
-
-  COI_vec_load_lanes,
-  COI_vec_store_lanes,
-
-  /* Vector conditional operations.  */
-  COI_vcond,
-  COI_vcondu,
-
-  COI_MAX
-};
-
-#define sext_optab (&convert_optab_table[COI_sext])
-#define zext_optab (&convert_optab_table[COI_zext])
-#define trunc_optab (&convert_optab_table[COI_trunc])
-#define sfix_optab (&convert_optab_table[COI_sfix])
-#define ufix_optab (&convert_optab_table[COI_ufix])
-#define sfixtrunc_optab (&convert_optab_table[COI_sfixtrunc])
-#define ufixtrunc_optab (&convert_optab_table[COI_ufixtrunc])
-#define sfloat_optab (&convert_optab_table[COI_sfloat])
-#define ufloat_optab (&convert_optab_table[COI_ufloat])
-#define lrint_optab (&convert_optab_table[COI_lrint])
-#define lround_optab (&convert_optab_table[COI_lround])
-#define lfloor_optab (&convert_optab_table[COI_lfloor])
-#define lceil_optab (&convert_optab_table[COI_lceil])
-#define fract_optab (&convert_optab_table[COI_fract])
-#define fractuns_optab (&convert_optab_table[COI_fractuns])
-#define satfract_optab (&convert_optab_table[COI_satfract])
-#define satfractuns_optab (&convert_optab_table[COI_satfractuns])
-#define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
-#define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
-#define vcond_optab (&convert_optab_table[(int) COI_vcond])
-#define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
-
-/* Contains the optab used for each rtx code.  */
-extern optab code_to_optab_[NUM_RTX_CODE + 1];
+/* Contains the optab used for each rtx code, and vice-versa.  */
+extern const optab code_to_optab_[NUM_RTX_CODE];
+extern const enum rtx_code optab_to_code_[NUM_OPTABS];
 
 static inline optab
 code_to_optab (enum rtx_code code)
@@ -679,176 +57,23 @@  code_to_optab (enum rtx_code code)
   return code_to_optab_[code];
 }
 
-#define optab_to_code(op)	((op)->code_)
-
-
-typedef rtx (*rtxfun) (rtx);
-
-/* Enumerates operations that have a named .md pattern associated
-   with them, but which are not implemented as library functions.  */
-enum direct_optab_index
+static inline enum rtx_code
+optab_to_code (optab op)
 {
-#ifdef HAVE_conditional_move
-  /* Conditional move operations.  */
-  DOI_movcc,
-#endif
+  return optab_to_code_[op];
+}
 
-  /* Operations that use a scratch register to perform input and output
-     reloads of special objects.  */
-  DOI_reload_in,
-  DOI_reload_out,
-
-  /* Block move operation.  */
-  DOI_movmem,
-
-  /* Block set operation.  */
-  DOI_setmem,
-
-  /* Various types of block compare operation.  */
-  DOI_cmpstr,
-  DOI_cmpstrn,
-  DOI_cmpmem,
-
-  /* Atomic clear with release semantics.  */
-  DOI_sync_lock_release,
-
-  /* Atomic operation with no resulting value.  */
-  DOI_sync_add,
-  DOI_sync_sub,
-  DOI_sync_ior,
-  DOI_sync_and,
-  DOI_sync_xor,
-  DOI_sync_nand,
-
-  /* Atomic operations with memory model parameters. */
-  DOI_atomic_exchange,
-  DOI_atomic_compare_and_swap,
-  DOI_atomic_load,
-  DOI_atomic_store,
-  DOI_atomic_add_fetch,
-  DOI_atomic_sub_fetch,
-  DOI_atomic_and_fetch,
-  DOI_atomic_nand_fetch,
-  DOI_atomic_xor_fetch,
-  DOI_atomic_or_fetch,
-  DOI_atomic_fetch_add,
-  DOI_atomic_fetch_sub,
-  DOI_atomic_fetch_and,
-  DOI_atomic_fetch_nand,
-  DOI_atomic_fetch_xor,
-  DOI_atomic_fetch_or,
-  DOI_atomic_add,
-  DOI_atomic_sub,
-  DOI_atomic_and,
-  DOI_atomic_nand,
-  DOI_atomic_xor,
-  DOI_atomic_or,
-  DOI_atomic_always_lock_free,
-  DOI_atomic_is_lock_free,
-  DOI_atomic_thread_fence,
-  DOI_atomic_signal_fence,
-
-  /* Vector permutation.  */
-  DOI_vec_perm,
-  DOI_vec_perm_const,
-
-  DOI_MAX
-};
+extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];
+extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];
 
-/* A structure that says which insn should be used to perform an operation
-   in a particular mode.  */
-struct direct_optab_d
-{
-  struct optab_handlers handlers[NUM_MACHINE_MODES];
-};
-typedef struct direct_optab_d *direct_optab;
+/* Returns the active icode for the given (encoded) optab.  */
+extern enum insn_code raw_optab_handler (unsigned);
+extern bool swap_optab_enable (optab, enum machine_mode, bool);
 
-#ifdef HAVE_conditional_move
-#define movcc_optab (&direct_optab_table[(int) DOI_movcc])
-#endif
-#define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
-#define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
-#define movmem_optab (&direct_optab_table[(int) DOI_movmem])
-#define setmem_optab (&direct_optab_table[(int) DOI_setmem])
-#define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
-#define cmpstrn_optab (&direct_optab_table[(int) DOI_cmpstrn])
-#define cmpmem_optab (&direct_optab_table[(int) DOI_cmpmem])
-#define sync_lock_release_optab \
-  (&direct_optab_table[(int) DOI_sync_lock_release])
-#define sync_add_optab (&direct_optab_table[(int) DOI_sync_add])
-#define sync_sub_optab (&direct_optab_table[(int) DOI_sync_sub])
-#define sync_ior_optab (&direct_optab_table[(int) DOI_sync_ior])
-#define sync_and_optab (&direct_optab_table[(int) DOI_sync_and])
-#define sync_xor_optab (&direct_optab_table[(int) DOI_sync_xor])
-#define sync_nand_optab (&direct_optab_table[(int) DOI_sync_nand])
-
-#define atomic_exchange_optab \
-  (&direct_optab_table[(int) DOI_atomic_exchange])
-#define atomic_compare_and_swap_optab \
-  (&direct_optab_table[(int) DOI_atomic_compare_and_swap])
-#define atomic_load_optab \
-  (&direct_optab_table[(int) DOI_atomic_load])
-#define atomic_store_optab \
-  (&direct_optab_table[(int) DOI_atomic_store])
-#define atomic_add_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_add_fetch])
-#define atomic_sub_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_sub_fetch])
-#define atomic_and_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_and_fetch])
-#define atomic_nand_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_nand_fetch])
-#define atomic_xor_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_xor_fetch])
-#define atomic_or_fetch_optab \
-  (&direct_optab_table[(int) DOI_atomic_or_fetch])
-#define atomic_fetch_add_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_add])
-#define atomic_fetch_sub_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_sub])
-#define atomic_fetch_and_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_and])
-#define atomic_fetch_nand_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_nand])
-#define atomic_fetch_xor_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_xor])
-#define atomic_fetch_or_optab \
-  (&direct_optab_table[(int) DOI_atomic_fetch_or])
-#define atomic_add_optab \
-  (&direct_optab_table[(int) DOI_atomic_add])
-#define atomic_sub_optab \
-  (&direct_optab_table[(int) DOI_atomic_sub])
-#define atomic_and_optab \
-  (&direct_optab_table[(int) DOI_atomic_and])
-#define atomic_nand_optab \
-  (&direct_optab_table[(int) DOI_atomic_nand])
-#define atomic_xor_optab \
-  (&direct_optab_table[(int) DOI_atomic_xor])
-#define atomic_or_optab \
-  (&direct_optab_table[(int) DOI_atomic_or])
-#define atomic_always_lock_free_optab \
-  (&direct_optab_table[(int) DOI_atomic_always_lock_free])
-#define atomic_is_lock_free_optab \
-  (&direct_optab_table[(int) DOI_atomic_is_lock_free])
-#define atomic_thread_fence_optab \
-  (&direct_optab_table[(int) DOI_atomic_thread_fence])
-#define atomic_signal_fence_optab \
-  (&direct_optab_table[(int) DOI_atomic_signal_fence])
-
-#define vec_perm_optab (&direct_optab_table[DOI_vec_perm])
-#define vec_perm_const_optab (&direct_optab_table[(int) DOI_vec_perm_const])
-
 /* Target-dependent globals.  */
 struct target_optabs {
-  /* Tables of patterns that may have an associated libcall.  */
-  struct optab_d x_optab_table[(int) OTI_MAX];
-
-  /* Tables of patterns for converting one mode to another.  */
-  struct convert_optab_d x_convert_optab_table[(int) COI_MAX];
-
-  /* Tables of patterns for direct optabs (i.e. those which cannot be
-     implemented using a libcall).  */
-  struct direct_optab_d x_direct_optab_table[(int) DOI_MAX];
+  /* Patterns that are used by optabs that are enabled for this target.  */
+  bool pat_enable[NUM_OPTAB_PATTERNS];
 };
 
 extern struct target_optabs default_target_optabs;
@@ -857,13 +82,6 @@  extern struct target_optabs *this_target_optabs;
 #else
 #define this_target_optabs (&default_target_optabs)
 #endif
-
-#define optab_table \
-  (this_target_optabs->x_optab_table)
-#define convert_optab_table \
-  (this_target_optabs->x_convert_optab_table)
-#define direct_optab_table \
-  (this_target_optabs->x_direct_optab_table)
 
 /* Define functions given in optabs.c.  */
 
@@ -1036,49 +254,9 @@  extern rtx expand_mult_highpart (enum machine_mode, rtx, rtx, rtx, bool);
 static inline enum insn_code
 optab_handler (optab op, enum machine_mode mode)
 {
-  return op->handlers[(int) mode].insn_code;
-}
-
-/* Like optab_handler, but for widening_operations that have a TO_MODE and
-  a FROM_MODE.  */
-
-static inline enum insn_code
-widening_optab_handler (optab op, enum machine_mode to_mode,
-			enum machine_mode from_mode)
-{
-  if (to_mode == from_mode || from_mode == VOIDmode)
-    return optab_handler (op, to_mode);
-
-  if (op->widening)
-    return op->widening->handlers[(int) to_mode][(int) from_mode].insn_code;
-
-  return CODE_FOR_nothing;
-}
-
-/* Record that insn CODE should be used to implement mode MODE of OP.  */
-
-static inline void
-set_optab_handler (optab op, enum machine_mode mode, enum insn_code code)
-{
-  op->handlers[(int) mode].insn_code = code;
-}
-
-/* Like set_optab_handler, but for widening operations that have a TO_MODE
-   and a FROM_MODE.  */
-
-static inline void
-set_widening_optab_handler (optab op, enum machine_mode to_mode,
-			    enum machine_mode from_mode, enum insn_code code)
-{
-  if (to_mode == from_mode)
-    set_optab_handler (op, to_mode, code);
-  else
-    {
-      if (op->widening == NULL)
-	op->widening = XCNEW (struct widening_optab_handlers);
-
-      op->widening->handlers[(int) to_mode][(int) from_mode].insn_code = code;
-    }
+  unsigned scode = (op << 16) | mode;
+  gcc_assert (op > LAST_CONV_OPTAB);
+  return raw_optab_handler (scode);
 }
 
 /* Return the insn used to perform conversion OP from mode FROM_MODE
@@ -1089,17 +267,28 @@  static inline enum insn_code
 convert_optab_handler (convert_optab op, enum machine_mode to_mode,
 		       enum machine_mode from_mode)
 {
-  return op->handlers[(int) to_mode][(int) from_mode].insn_code;
+  unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
+  gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
+  return raw_optab_handler (scode);
 }
 
-/* Record that insn CODE should be used to perform conversion OP
-   from mode FROM_MODE to mode TO_MODE.  */
+/* Like optab_handler, but for widening_operations that have a
+   TO_MODE and a FROM_MODE.  */
 
-static inline void
-set_convert_optab_handler (convert_optab op, enum machine_mode to_mode,
-			   enum machine_mode from_mode, enum insn_code code)
+static inline enum insn_code
+widening_optab_handler (optab op, enum machine_mode to_mode,
+			enum machine_mode from_mode)
 {
-  op->handlers[(int) to_mode][(int) from_mode].insn_code = code;
+  unsigned scode = (op << 16) | to_mode;
+  if (to_mode != from_mode && from_mode != VOIDmode)
+    {
+      /* ??? Why does find_widening_optab_handler_and_mode attempt to
+	 widen things that can't be widened?  E.g. add_optab... */
+      if (op > LAST_CONV_OPTAB)
+	return CODE_FOR_nothing;
+      scode |= from_mode << 8;
+    }
+  return raw_optab_handler (scode);
 }
 
 /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
@@ -1108,16 +297,7 @@  set_convert_optab_handler (convert_optab op, enum machine_mode to_mode,
 static inline enum insn_code
 direct_optab_handler (direct_optab op, enum machine_mode mode)
 {
-  return op->handlers[(int) mode].insn_code;
-}
-
-/* Record that insn CODE should be used to implement mode MODE of OP.  */
-
-static inline void
-set_direct_optab_handler (direct_optab op, enum machine_mode mode,
-			  enum insn_code code)
-{
-  op->handlers[(int) mode].insn_code = code;
+  return optab_handler (op, mode);
 }
 
 /* Return true if UNOPTAB is for a trapping-on-overflow operation.  */
@@ -1292,4 +472,52 @@  extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
 extern rtx prepare_operand (enum insn_code, rtx, int, enum machine_mode,
 			    enum machine_mode, int);
 
+extern void gen_int_libfunc (optab, const char *, char, enum machine_mode);
+extern void gen_fp_libfunc (optab, const char *, char, enum machine_mode);
+extern void gen_fixed_libfunc (optab, const char *, char, enum machine_mode);
+extern void gen_signed_fixed_libfunc (optab, const char *, char,
+				      enum machine_mode);
+extern void gen_unsigned_fixed_libfunc (optab, const char *, char,
+					enum machine_mode);
+extern void gen_int_fp_libfunc (optab, const char *, char, enum machine_mode);
+extern void gen_intv_fp_libfunc (optab, const char *, char, enum machine_mode);
+extern void gen_int_fp_fixed_libfunc (optab, const char *, char,
+				      enum machine_mode);
+extern void gen_int_fp_signed_fixed_libfunc (optab, const char *, char,
+					     enum machine_mode);
+extern void gen_int_fixed_libfunc (optab, const char *, char,
+				   enum machine_mode);
+extern void gen_int_signed_fixed_libfunc (optab, const char *, char,
+					  enum machine_mode);
+extern void gen_int_unsigned_fixed_libfunc (optab, const char *, char,
+					    enum machine_mode);
+
+extern void gen_interclass_conv_libfunc (convert_optab, const char *,
+					 enum machine_mode, enum machine_mode);
+extern void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
+					enum machine_mode, enum machine_mode);
+extern void gen_ufloat_conv_libfunc (convert_optab, const char *,
+				     enum machine_mode, enum machine_mode);
+extern void gen_int_to_fp_nondecimal_conv_libfunc  (convert_optab,
+						    const char *,
+						    enum machine_mode,
+						    enum machine_mode);
+extern void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
+					enum machine_mode, enum machine_mode);
+extern void gen_intraclass_conv_libfunc (convert_optab, const char *,
+					 enum machine_mode, enum machine_mode);
+extern void gen_trunc_conv_libfunc (convert_optab, const char *,
+				    enum machine_mode, enum machine_mode);
+extern void gen_extend_conv_libfunc (convert_optab, const char *,
+				     enum machine_mode, enum machine_mode);
+extern void gen_fract_conv_libfunc (convert_optab, const char *,
+				    enum machine_mode, enum machine_mode);
+extern void gen_fractuns_conv_libfunc (convert_optab, const char *,
+				       enum machine_mode, enum machine_mode);
+extern void gen_satfract_conv_libfunc (convert_optab, const char *,
+				       enum machine_mode, enum machine_mode);
+extern void gen_satfractuns_conv_libfunc (convert_optab, const char *,
+					  enum machine_mode,
+					  enum machine_mode);
+
 #endif /* GCC_OPTABS_H */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 1b13659..f942c59 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -55,8 +55,13 @@  enum rtx_code  {
 				   NUM_RTX_CODE.
 				   Assumes default enum value assignment.  */
 
+/* The cast here, saves many elsewhere.  */
 #define NUM_RTX_CODE ((int) LAST_AND_UNUSED_RTX_CODE)
-				/* The cast here, saves many elsewhere.  */
+
+/* Similar, but since generator files get more entries... */
+#ifdef GENERATOR_FILE
+# define NON_GENERATOR_NUM_RTX_CODE ((int) MATCH_OPERAND)
+#endif
 
 /* Register Transfer Language EXPRESSIONS CODE CLASSES */