public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/4] Tidy some include usage + dependencies
  2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
@ 2012-07-19 18:24 ` Richard Henderson
  2012-07-19 18:24 ` [PATCH 3/4] Introduce and use code_to_optab and optab_to_code functions Richard Henderson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-19 18:24 UTC (permalink / raw)
  To: gcc-patches

The dwarf2out.c and lto-streamer-in.c files didn't need
libfuncs.h in the first place.  The libfuncs.h file will
grow a use of an optab enumeration and thus will require
including optabs.h.
---
 gcc/Makefile.in       |   16 ++++++++--------
 gcc/dwarf2out.c       |    1 -
 gcc/libfuncs.h        |    1 +
 gcc/lto-streamer-in.c |    1 -
 4 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d48c696..06b8179 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -971,7 +971,7 @@ GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h plugin.def \
 		$(CONFIG_H) $(SYSTEM_H) $(HASHTAB_H)
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
-LIBFUNCS_H = libfuncs.h $(HASHTAB_H)
+LIBFUNCS_H = libfuncs.h $(HASHTAB_H) $(OPTABS_H)
 
 #\f
 # Now figure out from those variables how to compile and link.
@@ -2158,9 +2158,9 @@ lto-cgraph.o: lto-cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h   \
    $(EXCEPT_H) $(TIMEVAR_H) pointer-set.h $(LTO_STREAMER_H) \
    $(GCOV_IO_H) $(DATA_STREAMER_H) $(TREE_STREAMER_H)
 lto-streamer-in.o: lto-streamer-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
-   $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) \
-   $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(LIBFUNCS_H) $(EXCEPT_H) debug.h \
+   $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) \
+   input.h $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) \
+   $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(EXCEPT_H) debug.h \
    $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h \
    $(DATA_STREAMER_H) $(GIMPLE_STREAMER_H) $(TREE_STREAMER_H)
 lto-streamer-out.o : lto-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
@@ -2794,10 +2794,10 @@ sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) debug.h \
    $(TREE_H) $(GGC_H) $(RTL_H) $(REGS_H) $(FLAGS_H) insn-config.h \
    output.h $(DIAGNOSTIC_CORE_H) $(TM_P_H) gsyms.h langhooks.h $(TARGET_H) sdbout.h \
    gt-sdbout.h reload.h
-dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H) \
-   $(TREE_H) version.h $(RTL_H) $(DWARF2_H) debug.h $(FLAGS_H) insn-config.h \
-   output.h $(DIAGNOSTIC_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
-   $(LIBFUNCS_H) toplev.h $(DIAGNOSTIC_CORE_H) $(DWARF2OUT_H) reload.h \
+dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
+   $(TM_H) $(TREE_H) version.h $(RTL_H) $(DWARF2_H) debug.h $(FLAGS_H) \
+   insn-config.h output.h $(DIAGNOSTIC_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
+   toplev.h $(DIAGNOSTIC_CORE_H) $(DWARF2OUT_H) reload.h \
    $(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) \
    gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) $(MD5_H) $(INPUT_H) $(FUNCTION_H) \
    $(GIMPLE_H) $(TREE_FLOW_H) \
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index d4b6831..b60c4ce 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -72,7 +72,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "output.h"
 #include "expr.h"
-#include "libfuncs.h"
 #include "except.h"
 #include "dwarf2.h"
 #include "dwarf2out.h"
diff --git a/gcc/libfuncs.h b/gcc/libfuncs.h
index b01aed3..bac4918 100644
--- a/gcc/libfuncs.h
+++ b/gcc/libfuncs.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_LIBFUNCS_H
 
 #include "hashtab.h"
+#include "optabs.h"
 
 /* Enumeration of indexes into libfunc_table.  */
 enum libfunc_index
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 07ae2b3..89e337c 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "function.h"
 #include "ggc.h"
 #include "diagnostic.h"
-#include "libfuncs.h"
 #include "except.h"
 #include "debug.h"
 #include "vec.h"
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] Introduce and use unknown_optab
  2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
  2012-07-19 18:24 ` [PATCH 2/4] Tidy some include usage + dependencies Richard Henderson
  2012-07-19 18:24 ` [PATCH 3/4] Introduce and use code_to_optab and optab_to_code functions Richard Henderson
@ 2012-07-19 18:24 ` Richard Henderson
  2012-07-19 18:25 ` [PATCH 4/4] Reduce the size of optabs representation Richard Henderson
  2012-07-20  8:40 ` [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Guenther
  4 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-19 18:24 UTC (permalink / raw)
  To: gcc-patches

Prep for a later patch where this becomes an enum value.
---
 gcc/builtins.c           |    2 +-
 gcc/dojump.c             |   13 +++++--------
 gcc/optabs.c             |    6 +++---
 gcc/optabs.h             |    2 ++
 gcc/tree-vect-generic.c  |   30 +++++++++++++++---------------
 gcc/tree-vect-patterns.c |    2 +-
 gcc/tree-vect-stmts.c    |    2 +-
 7 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 4fb3d53..23c7437 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2352,7 +2352,7 @@ static enum insn_code
 interclass_mathfn_icode (tree arg, tree fndecl)
 {
   bool errno_set = false;
-  optab builtin_optab = 0;
+  optab builtin_optab = unknown_optab;
   enum machine_mode mode;
 
   switch (DECL_FUNCTION_CODE (fndecl))
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 06b8d04..24eed63 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -1028,19 +1028,16 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 	  op0 = op1;
 	  op1 = tmp;
 	}
-
       else if (SCALAR_FLOAT_MODE_P (mode)
 	       && ! can_compare_p (code, mode, ccp_jump)
-
-	       /* Never split ORDERED and UNORDERED.  These must be implemented.  */
+	       /* Never split ORDERED and UNORDERED.
+		  These must be implemented.  */
 	       && (code != ORDERED && code != UNORDERED)
-
-               /* Split a floating-point comparison if we can jump on other
-	          conditions...  */
+               /* Split a floating-point comparison if
+		  we can jump on other conditions...  */
 	       && (have_insn_for (COMPARE, mode)
-
 	           /* ... or if there is no libcall for it.  */
-	           || code_to_optab[code] == NULL))
+	           || code_to_optab[code] == unknown_optab))
         {
 	  enum rtx_code first_code;
 	  bool and_them = split_comparison (code, mode, &first_code, &code);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index e1ecc65..f30a20d 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -390,7 +390,7 @@ optab_for_tree_code (enum tree_code code, const_tree type,
       if (TREE_CODE (type) == VECTOR_TYPE)
 	{
 	  if (subtype == optab_vector)
-	    return TYPE_SATURATING (type) ? NULL : vashl_optab;
+	    return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
 
 	  gcc_assert (subtype == optab_scalar);
 	}
@@ -560,7 +560,7 @@ optab_for_tree_code (enum tree_code code, const_tree type,
       return trapv ? absv_optab : abs_optab;
 
     default:
-      return NULL;
+      return unknown_optab;
     }
 }
 \f
@@ -1580,7 +1580,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
      shift by a vector.  If so, broadcast the scalar into a vector.  */
   if (mclass == MODE_VECTOR_INT)
     {
-      optab otheroptab = NULL;
+      optab otheroptab = unknown_optab;
 
       if (binoptab == ashl_optab)
 	otheroptab = vashl_optab;
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 816fc29..c502766 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -412,6 +412,8 @@ enum optab_index
   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])
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index b0f41d1..9c8a70e 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -414,14 +414,14 @@ add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
   if (scalar_shift)
     {
       op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
-      if (op != NULL
+      if (op != unknown_optab
 	  && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
 	return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
 				build_int_cst (NULL_TREE, shiftcnts[0]));
     }
 
   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
-  if (op != NULL
+  if (op != unknown_optab
       && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
     {
       tree *vec = XALLOCAVEC (tree, nunits);
@@ -462,7 +462,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
     return NULL_TREE;
 
   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
-  if (op == NULL
+  if (op == unknown_optab
       || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
     has_vector_shift = false;
 
@@ -689,7 +689,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 	      /* t1 = op0 + addend;
 		 q = t1 >> shift;  */
 	      op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
-	      if (op != NULL
+	      if (op != unknown_optab
 		  && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
 		{
 		  cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
@@ -708,7 +708,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 				     << shifts[i]) - 1);
 	  mask = build_vector (type, vec);
 	  op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
-	  if (op != NULL
+	  if (op != unknown_optab
 	      && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
 	    {
 	      if (unsignedp)
@@ -720,7 +720,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 		     t2 = t1 & mask;
 		     r = t2 - addend;  */
 		  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
-		  if (op != NULL
+		  if (op != unknown_optab
 		      && optab_handler (op, TYPE_MODE (type))
 			 != CODE_FOR_nothing)
 		    {
@@ -730,7 +730,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 						cur_op, mask);
 		      op = optab_for_tree_code (MINUS_EXPR, type,
 						optab_default);
-		      if (op != NULL
+		      if (op != unknown_optab
 			  && optab_handler (op, TYPE_MODE (type))
 			     != CODE_FOR_nothing)
 			return gimplify_build2 (gsi, MINUS_EXPR, type,
@@ -801,13 +801,13 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
 	 t4 = t1 + t3;
 	 q = t4 >> (post_shift - 1);  */
       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
-      if (op == NULL
+      if (op == unknown_optab
 	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
 	return NULL_TREE;
       tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
       tem = add_rshift (gsi, type, tem, shift_temps);
       op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
-      if (op == NULL
+      if (op == unknown_optab
 	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
 	return NULL_TREE;
       tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
@@ -829,7 +829,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
       if ((mode & 2) == 0)
 	{
 	  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
-	  if (op == NULL
+	  if (op == unknown_optab
 	      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
 	    return NULL_TREE;
 	  cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
@@ -841,7 +841,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
       if (tem == NULL_TREE)
 	return NULL_TREE;
       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
-      if (op == NULL
+      if (op == unknown_optab
 	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
 	return NULL_TREE;
       if ((mode & 1) == 0)
@@ -860,12 +860,12 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
      t1 = q * oprnd1;
      r = oprnd0 - t1;  */
   op = optab_for_tree_code (MULT_EXPR, type, optab_default);
-  if (op == NULL
+  if (op == unknown_optab
       || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
     return NULL_TREE;
   tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
   op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
-  if (op == NULL
+  if (op == unknown_optab
       || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
     return NULL_TREE;
   return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
@@ -1235,7 +1235,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   tree lhs, rhs1, rhs2 = NULL, type, compute_type;
   enum tree_code code;
   enum machine_mode compute_mode;
-  optab op = NULL;
+  optab op = unknown_optab;
   enum gimple_rhs_class rhs_class;
   tree new_rhs;
 
@@ -1344,7 +1344,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   /* Optabs will try converting a negation into a subtraction, so
      look for it as well.  TODO: negation of floating-point vectors
      might be turned into an exclusive OR toggling the sign bit.  */
-  if (op == NULL
+  if (op == unknown_optab
       && code == NEGATE_EXPR
       && INTEGRAL_TYPE_P (TREE_TYPE (type)))
     op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 05202a8..420a4f4 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1675,7 +1675,7 @@ vect_recog_divmod_pattern (VEC (gimple, heap) **stmts,
   /* If the target can handle vectorized division or modulo natively,
      don't attempt to optimize this.  */
   optab = optab_for_tree_code (rhs_code, vectype, optab_default);
-  if (optab != NULL)
+  if (optab != unknown_optab)
     {
       enum machine_mode vec_mode = TYPE_MODE (vectype);
       int icode = (int) optab_handler (optab, vec_mode);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index fb05063..9d137e8 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6545,7 +6545,7 @@ supportable_narrowing_operation (enum tree_code code,
 	= lang_hooks.types.type_for_mode (TYPE_MODE (vectype_out), 0);
       interm_optab
 	= optab_for_tree_code (c1, intermediate_type, optab_default);
-      if (interm_optab != NULL
+      if (interm_optab != unknown_optab
 	  && (icode2 = optab_handler (optab1, vec_mode)) != CODE_FOR_nothing
 	  && insn_data[icode1].operand[0].mode
 	     == insn_data[icode2].operand[0].mode)
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/4] Introduce and use code_to_optab and optab_to_code functions
  2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
  2012-07-19 18:24 ` [PATCH 2/4] Tidy some include usage + dependencies Richard Henderson
@ 2012-07-19 18:24 ` Richard Henderson
  2012-07-19 18:24 ` [PATCH 1/4] Introduce and use unknown_optab Richard Henderson
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-19 18:24 UTC (permalink / raw)
  To: gcc-patches

Removes all the direct uses of op->code so that we can change
the representation of "optab".  The code_to_optab change is
simply for uniformity (and better type checking).
---
 gcc/dojump.c |    2 +-
 gcc/ifcvt.c  |    4 +-
 gcc/optabs.c |   64 +++++++++++++++++++++++++++++----------------------------
 gcc/optabs.h |   14 ++++++++++--
 4 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/gcc/dojump.c b/gcc/dojump.c
index 24eed63..ea6620d 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -1037,7 +1037,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
 		  we can jump on other conditions...  */
 	       && (have_insn_for (COMPARE, mode)
 	           /* ... or if there is no libcall for it.  */
-	           || code_to_optab[code] == unknown_optab))
+	           || code_to_optab (code) == unknown_optab))
         {
 	  enum rtx_code first_code;
 	  bool and_them = split_comparison (code, mode, &first_code, &code);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 08a9755..31fa665 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -902,7 +902,7 @@ noce_emit_move_insn (rtx x, rtx y)
 	  switch (GET_RTX_CLASS (GET_CODE (y)))
 	    {
 	    case RTX_UNARY:
-	      ot = code_to_optab[GET_CODE (y)];
+	      ot = code_to_optab (GET_CODE (y));
 	      if (ot)
 		{
 		  start_sequence ();
@@ -919,7 +919,7 @@ noce_emit_move_insn (rtx x, rtx y)
 
 	    case RTX_BIN_ARITH:
 	    case RTX_COMM_ARITH:
-	      ot = code_to_optab[GET_CODE (y)];
+	      ot = code_to_optab (GET_CODE (y));
 	      if (ot)
 		{
 		  start_sequence ();
diff --git a/gcc/optabs.c b/gcc/optabs.c
index f30a20d..83509f9 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -55,7 +55,7 @@ struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
   (this_target_libfuncs->x_libfunc_hash)
 
 /* Contains the optab used for each rtx code.  */
-optab code_to_optab[NUM_RTX_CODE + 1];
+optab code_to_optab_[NUM_RTX_CODE + 1];
 
 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
 				   enum machine_mode *);
@@ -678,8 +678,8 @@ simplify_expand_binop (enum machine_mode mode, optab binoptab,
 {
   if (CONSTANT_P (op0) && CONSTANT_P (op1))
     {
-      rtx x = simplify_binary_operation (binoptab->code, mode, op0, op1);
-
+      rtx x = simplify_binary_operation (optab_to_code (binoptab),
+					 mode, op0, op1);
       if (x)
 	return x;
     }
@@ -1266,7 +1266,7 @@ expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
 		     rtx op1, rtx target, int unsignedp,
 		     enum optab_methods methods)
 {
-  optab binop = code_to_optab[(int) code];
+  optab binop = code_to_optab (code);
   gcc_assert (binop);
 
   return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
@@ -1300,7 +1300,7 @@ swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
 static bool
 shift_optab_p (optab binoptab)
 {
-  switch (binoptab->code)
+  switch (optab_to_code (binoptab))
     {
     case ASHIFT:
     case SS_ASHIFT:
@@ -1321,7 +1321,7 @@ shift_optab_p (optab binoptab)
 static bool
 commutative_optab_p (optab binoptab)
 {
-  return (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
+  return (GET_RTX_CLASS (optab_to_code (binoptab)) == RTX_COMM_ARITH
 	  || binoptab == smul_widen_optab
 	  || binoptab == umul_widen_optab
 	  || binoptab == smul_highpart_optab
@@ -1342,7 +1342,8 @@ avoid_expensive_constant (enum machine_mode mode, optab binoptab,
   if (mode != VOIDmode
       && optimize
       && CONSTANT_P (x)
-      && rtx_cost (x, binoptab->code, opn, speed) > set_src_cost (x, speed))
+      && (rtx_cost (x, optab_to_code (binoptab), opn, speed)
+	  > set_src_cost (x, speed)))
     {
       if (CONST_INT_P (x))
 	{
@@ -1458,7 +1459,7 @@ expand_binop_directly (enum machine_mode mode, optab binoptab,
 	 REG_EQUAL note to it.  If we can't because TEMP conflicts with an
 	 operand, call expand_binop again, this time without a target.  */
       if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-	  && ! add_equal_note (pat, ops[0].value, binoptab->code,
+	  && ! add_equal_note (pat, ops[0].value, optab_to_code (binoptab),
 			       ops[1].value, ops[2].value))
 	{
 	  delete_insns_since (last);
@@ -2029,8 +2030,8 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	      rtx temp = emit_move_insn (target, xtarget);
 
 	      set_dst_reg_note (temp, REG_EQUAL,
-				gen_rtx_fmt_ee (binoptab->code, mode,
-						copy_rtx (xop0),
+				gen_rtx_fmt_ee (optab_to_code (binoptab),
+						mode, copy_rtx (xop0),
 						copy_rtx (xop1)),
 				target);
 	    }
@@ -2128,7 +2129,8 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       target = gen_reg_rtx (mode);
       emit_libcall_block_1 (insns, target, value,
-			    gen_rtx_fmt_ee (binoptab->code, mode, op0, op1),
+			    gen_rtx_fmt_ee (optab_to_code (binoptab),
+					    mode, op0, op1),
 			    trapv_binoptab_p (binoptab));
 
       return target;
@@ -2481,7 +2483,7 @@ rtx
 expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
 		    rtx target, int unsignedp)
 {
-  optab unop = code_to_optab[(int) code];
+  optab unop = code_to_optab (code);
   gcc_assert (unop);
 
   return expand_unop (mode, unop, op0, target, unsignedp);
@@ -2971,7 +2973,7 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       if (pat)
 	{
 	  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-	      && ! add_equal_note (pat, ops[0].value, unoptab->code,
+	      && ! add_equal_note (pat, ops[0].value, optab_to_code (unoptab),
 				   ops[1].value, NULL_RTX))
 	    {
 	      delete_insns_since (last);
@@ -3170,7 +3172,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       return target;
     }
 
-  if (unoptab->code == NEG)
+  if (optab_to_code (unoptab) == NEG)
     {
       /* Try negating floating point values by flipping the sign bit.  */
       if (SCALAR_FLOAT_MODE_P (mode))
@@ -3246,7 +3248,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       end_sequence ();
 
       target = gen_reg_rtx (outmode);
-      eq_value = gen_rtx_fmt_e (unoptab->code, mode, op0);
+      eq_value = gen_rtx_fmt_e (optab_to_code (unoptab), mode, op0);
       if (GET_MODE_SIZE (outmode) < GET_MODE_SIZE (mode))
 	eq_value = simplify_gen_unary (TRUNCATE, outmode, eq_value, mode);
       else if (GET_MODE_SIZE (outmode) > GET_MODE_SIZE (mode))
@@ -3326,7 +3328,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
 
   /* One final attempt at implementing negation via subtraction,
      this time allowing widening of the operand.  */
-  if (unoptab->code == NEG && !HONOR_SIGNED_ZEROS (mode))
+  if (optab_to_code (unoptab) == NEG && !HONOR_SIGNED_ZEROS (mode))
     {
       rtx temp;
       temp = expand_binop (mode,
@@ -4325,12 +4327,12 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
-      if (code_to_optab[comparison]
-	  && (libfunc = optab_libfunc (code_to_optab[comparison], mode)))
+      if (code_to_optab (comparison)
+	  && (libfunc = optab_libfunc (code_to_optab (comparison), mode)))
 	break;
 
-      if (code_to_optab[swapped]
-	  && (libfunc = optab_libfunc (code_to_optab[swapped], mode)))
+      if (code_to_optab (swapped)
+	  && (libfunc = optab_libfunc (code_to_optab (swapped), mode)))
 	{
 	  rtx tmp;
 	  tmp = x; x = y; y = tmp;
@@ -4338,8 +4340,8 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
 	  break;
 	}
 
-      if (code_to_optab[reversed]
-	  && (libfunc = optab_libfunc (code_to_optab[reversed], mode)))
+      if (code_to_optab (reversed)
+	  && (libfunc = optab_libfunc (code_to_optab (reversed), mode)))
 	{
 	  comparison = reversed;
 	  reversed_p = true;
@@ -5355,7 +5357,7 @@ expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
   end_sequence ();
 
   emit_libcall_block (insns, to, value,
-		      gen_rtx_fmt_e (tab->code, to_mode, from));
+		      gen_rtx_fmt_e (optab_to_code (tab), to_mode, from));
 }
 
 /* Generate code to convert FROM to fixed point and store in TO.  FROM
@@ -5408,8 +5410,8 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab)
 int
 have_insn_for (enum rtx_code code, enum machine_mode mode)
 {
-  return (code_to_optab[(int) code] != 0
-	  && (optab_handler (code_to_optab[(int) code], mode)
+  return (code_to_optab (code)
+	  && (optab_handler (code_to_optab (code), mode)
 	      != CODE_FOR_nothing));
 }
 
@@ -5427,8 +5429,8 @@ init_insn_codes (void)
 static inline void
 init_optab (optab op, enum rtx_code code)
 {
-  op->code = code;
-  code_to_optab[(int) code] = op;
+  op->code_ = code;
+  code_to_optab_[(int) code] = op;
 }
 
 /* Same, but fill in its code as CODE, and do _not_ write it into
@@ -5436,14 +5438,14 @@ init_optab (optab op, enum rtx_code code)
 static inline void
 init_optabv (optab op, enum rtx_code code)
 {
-  op->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;
+  op->code_ = code;
 }
 
 /* Initialize the libfunc fields of an entire group of entries in some
@@ -6701,7 +6703,7 @@ debug_optab_libfuncs (void)
 	  {
 	    gcc_assert (GET_CODE (l) == SYMBOL_REF);
 	    fprintf (stderr, "%s\t%s:\t%s\n",
-		     GET_RTX_NAME (o->code),
+		     GET_RTX_NAME (optab_to_code (o)),
 		     GET_MODE_NAME (j),
 		     XSTR (l, 0));
 	  }
@@ -6722,7 +6724,7 @@ debug_optab_libfuncs (void)
 	    {
 	      gcc_assert (GET_CODE (l) == SYMBOL_REF);
 	      fprintf (stderr, "%s\t%s\t%s:\t%s\n",
-		       GET_RTX_NAME (o->code),
+		       GET_RTX_NAME (optab_to_code (o)),
 		       GET_MODE_NAME (j),
 		       GET_MODE_NAME (k),
 		       XSTR (l, 0));
diff --git a/gcc/optabs.h b/gcc/optabs.h
index c502766..60f83cf 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -50,7 +50,7 @@ struct widening_optab_handlers
 
 struct optab_d
 {
-  enum rtx_code code;
+  enum rtx_code code_;
   char libcall_suffix;
   const char *libcall_basename;
   void (*libcall_gen)(struct optab_d *, const char *name, char suffix,
@@ -65,7 +65,7 @@ typedef struct optab_d * optab;
    is the source mode.  */
 struct convert_optab_d
 {
-  enum rtx_code code;
+  enum rtx_code code_;
   const char *libcall_basename;
   void (*libcall_gen)(struct convert_optab_d *, const char *name,
 		      enum machine_mode,
@@ -671,7 +671,15 @@ enum convert_optab_index
 #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];
+extern optab code_to_optab_[NUM_RTX_CODE + 1];
+
+static inline optab
+code_to_optab (enum rtx_code code)
+{
+  return code_to_optab_[code];
+}
+
+#define optab_to_code(op)	((op)->code_)
 
 \f
 typedef rtx (*rtxfun) (rtx);
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 0/4] [RFC] Reduce the representation size of optabs
@ 2012-07-19 18:24 Richard Henderson
  2012-07-19 18:24 ` [PATCH 2/4] Tidy some include usage + dependencies Richard Henderson
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-19 18:24 UTC (permalink / raw)
  To: gcc-patches

While adding multiple new optabs over the past week or three, it
occurred to me that (1) there are lots of places to update all in
sync and (2) the representation size of optabs is huge.

The first issue is somewhat trivially accomplished by moving all
optabs knowledge into an optabs.def file.  This could have been
staged differently to prove no errors in the transcription, but
I'm simply going to ask for help reviewing and testing for that.

The second issue is addressed by recognizing that the contents of
the md file, and thus the set of named patterns, does not change
between sub-targets.  The only thing that changes is the value of
HAVE_foo for any pattern foo.

We currently have a very sparse pattern[max_mode] arrays for the
optabs.  Changing that to a dense mapping of known patterns to a
unified pattern array can reduce the dynamic memory requirements
by a factor of 10.  Splitting away the truely unchanging portions
to rodata can reduce the non-sharable data by another factor of 10.

I initially thought of using a minimal perfect hash for the dense
mapping, but gperf turns out to be irritatingly string oriented
and re-implementing a perfect hash algorithm was more than I wanted
to do while I didn't know how much memory I could save.  So at the
moment my "hash function" is a binary search over a table.

Some statistics:

old sizeof(struct target_optabs):
alpha:  225472
ppc64:	396088
i386:   721240

new sizeof(struct target_optabs) + new .rodata
alpha:  210 + 3232
ppc64:	502 + 5568
i386:   1009 + 9624

i386 cc1     old:	new:
.text        9381620	9373204
.rodata      3017472	3031040
.bss         1499552	 778144

I've not yet speed tested this, only completed bootstrap + test
runs for both x86_64 and ppc64.  I've done sanity cross compiles
to alpha and mips (the only SWITCHABLE_TARGET).

I'll be offline til Tuesday, so I won't commit this until then at
least.  Hopefully there will be some good feedback on my return.

FYI, the patchset is available at

  git://repo.or.cz/gcc/rth.git rth/opinit


r~


Richard Henderson (4):
  Introduce and use unknown_optab
  Tidy some include usage + dependencies
  Introduce and use code_to_optab and optab_to_code functions
  Reduce the size of optabs representation

 gcc/Makefile.in          |   35 +-
 gcc/builtins.c           |    2 +-
 gcc/dojump.c             |   13 +-
 gcc/dwarf2out.c          |    1 -
 gcc/genopinit.c          |  932 +++++++++++++++++++++-----------------------
 gcc/ifcvt.c              |    4 +-
 gcc/libfuncs.h           |    3 +-
 gcc/lto-streamer-in.c    |    1 -
 gcc/optabs.c             |  709 +++++++---------------------------
 gcc/optabs.def           |  289 ++++++++++++++
 gcc/optabs.h             |  958 +++++-----------------------------------------
 gcc/rtl.h                |    7 +-
 gcc/tree-vect-generic.c  |   30 +-
 gcc/tree-vect-patterns.c |    2 +-
 gcc/tree-vect-stmts.c    |    2 +-
 15 files changed, 1020 insertions(+), 1968 deletions(-)
 create mode 100644 gcc/optabs.def

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/4] Reduce the size of optabs representation
  2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
                   ` (2 preceding siblings ...)
  2012-07-19 18:24 ` [PATCH 1/4] Introduce and use unknown_optab Richard Henderson
@ 2012-07-19 18:25 ` Richard Henderson
  2012-07-19 20:24   ` Jakub Jelinek
  2012-08-22  3:00   ` Mike Stump
  2012-07-20  8:40 ` [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Guenther
  4 siblings, 2 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-19 18:25 UTC (permalink / raw)
  To: gcc-patches

---
 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

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;
 }
 \f
 /* 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_)
-
-\f
-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])
-\f
 /* 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)
 \f
 /* 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 */
 
-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] Reduce the size of optabs representation
  2012-07-19 18:25 ` [PATCH 4/4] Reduce the size of optabs representation Richard Henderson
@ 2012-07-19 20:24   ` Jakub Jelinek
  2012-08-22  3:00   ` Mike Stump
  1 sibling, 0 replies; 9+ messages in thread
From: Jakub Jelinek @ 2012-07-19 20:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] [RFC] Reduce the representation size of optabs
  2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
                   ` (3 preceding siblings ...)
  2012-07-19 18:25 ` [PATCH 4/4] Reduce the size of optabs representation Richard Henderson
@ 2012-07-20  8:40 ` Richard Guenther
  2012-07-24 16:52   ` Richard Henderson
  4 siblings, 1 reply; 9+ messages in thread
From: Richard Guenther @ 2012-07-20  8:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

On Thu, Jul 19, 2012 at 8:24 PM, Richard Henderson <rth@redhat.com> wrote:
> While adding multiple new optabs over the past week or three, it
> occurred to me that (1) there are lots of places to update all in
> sync and (2) the representation size of optabs is huge.
>
> The first issue is somewhat trivially accomplished by moving all
> optabs knowledge into an optabs.def file.  This could have been
> staged differently to prove no errors in the transcription, but
> I'm simply going to ask for help reviewing and testing for that.
>
> The second issue is addressed by recognizing that the contents of
> the md file, and thus the set of named patterns, does not change
> between sub-targets.  The only thing that changes is the value of
> HAVE_foo for any pattern foo.
>
> We currently have a very sparse pattern[max_mode] arrays for the
> optabs.  Changing that to a dense mapping of known patterns to a
> unified pattern array can reduce the dynamic memory requirements
> by a factor of 10.  Splitting away the truely unchanging portions
> to rodata can reduce the non-sharable data by another factor of 10.
>
> I initially thought of using a minimal perfect hash for the dense
> mapping, but gperf turns out to be irritatingly string oriented
> and re-implementing a perfect hash algorithm was more than I wanted
> to do while I didn't know how much memory I could save.  So at the
> moment my "hash function" is a binary search over a table.
>
> Some statistics:
>
> old sizeof(struct target_optabs):
> alpha:  225472
> ppc64:  396088
> i386:   721240
>
> new sizeof(struct target_optabs) + new .rodata
> alpha:  210 + 3232
> ppc64:  502 + 5568
> i386:   1009 + 9624
>
> i386 cc1     old:       new:
> .text        9381620    9373204
> .rodata      3017472    3031040
> .bss         1499552     778144
>
> I've not yet speed tested this, only completed bootstrap + test
> runs for both x86_64 and ppc64.  I've done sanity cross compiles
> to alpha and mips (the only SWITCHABLE_TARGET).

It would be interesting to see startup-time effects of this patch (thus,
compile-time of an empty CU).

Richard.

> I'll be offline til Tuesday, so I won't commit this until then at
> least.  Hopefully there will be some good feedback on my return.
>
> FYI, the patchset is available at
>
>   git://repo.or.cz/gcc/rth.git rth/opinit
>
>
> r~
>
>
> Richard Henderson (4):
>   Introduce and use unknown_optab
>   Tidy some include usage + dependencies
>   Introduce and use code_to_optab and optab_to_code functions
>   Reduce the size of optabs representation
>
>  gcc/Makefile.in          |   35 +-
>  gcc/builtins.c           |    2 +-
>  gcc/dojump.c             |   13 +-
>  gcc/dwarf2out.c          |    1 -
>  gcc/genopinit.c          |  932 +++++++++++++++++++++-----------------------
>  gcc/ifcvt.c              |    4 +-
>  gcc/libfuncs.h           |    3 +-
>  gcc/lto-streamer-in.c    |    1 -
>  gcc/optabs.c             |  709 +++++++---------------------------
>  gcc/optabs.def           |  289 ++++++++++++++
>  gcc/optabs.h             |  958 +++++-----------------------------------------
>  gcc/rtl.h                |    7 +-
>  gcc/tree-vect-generic.c  |   30 +-
>  gcc/tree-vect-patterns.c |    2 +-
>  gcc/tree-vect-stmts.c    |    2 +-
>  15 files changed, 1020 insertions(+), 1968 deletions(-)
>  create mode 100644 gcc/optabs.def
>
> --
> 1.7.7.6
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/4] [RFC] Reduce the representation size of optabs
  2012-07-20  8:40 ` [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Guenther
@ 2012-07-24 16:52   ` Richard Henderson
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2012-07-24 16:52 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On 07/20/2012 01:39 AM, Richard Guenther wrote:
>> > I've not yet speed tested this, only completed bootstrap + test
>> > runs for both x86_64 and ppc64.  I've done sanity cross compiles
>> > to alpha and mips (the only SWITCHABLE_TARGET).
> It would be interesting to see startup-time effects of this patch (thus,
> compile-time of an empty CU).

I've now done some speed testing on x86_64.  Best I can figure, everything is
within measurement error.  I tried both standalone compilations of combine.ii
and bootstraps.  I had to loop executions of cc1[*] to even measure the startup
time as requested, in which the only effect seems to be a narrowing of stddev.

I did some gperf profiles of the combine.ii compilation.  There, the cumulative
time in raw_optab_handler just barely makes it to 0.01 sec with 76k invocations.
So while we could make that unmeasurable with a minimal perfect hash, we probably
wouldn't actually be able to notice its effect on compilation as a whole.

So I guess we're down to theoretical improvement in memory usage and startup,
and a real improvement in maintainability due to the consolidation of the places
that must be modified to add or edit an optab.

No other comments over the weekend, really?


r~


[*]:
#include <unistd.h>
#include <sys/fcntl.h>
#include <stdlib.h>

int main(int ac, char **av)
{
  int i, count = atoi(av[1] ? av[1] : "100");

  close (0);
  close (1);
  open ("/dev/null", O_RDONLY);
  open ("/dev/null", O_WRONLY);

  for (i = 0; i < count; ++i)
    {
      int f = vfork();
      if (f == -1)
	return 1;
      if (f == 0)
	{
	  execl ("./cc1", "./cc1", "-quiet", "-o", "-", NULL);
	  _exit (1);
	}
      wait(NULL);
    }
  return 0;
}

time loop 1000:

NEW	real	user	sys		OLD	real	user	sys
 	11.344	7.765	2.962			11.456	7.770	3.033
 	11.296	7.786	2.862			11.286	7.787	2.843
 	11.312	7.776	2.897			11.323	7.740	2.942
 	11.367	7.820	2.917			11.355	7.800	2.916
 	11.275	7.777	2.852			11.354	7.708	2.974
avg	11.319	7.785	2.898			11.355	7.761	2.942
stddev	 0.033	0.019	0.040			 0.057	0.033	0.063

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] Reduce the size of optabs representation
  2012-07-19 18:25 ` [PATCH 4/4] Reduce the size of optabs representation Richard Henderson
  2012-07-19 20:24   ` Jakub Jelinek
@ 2012-08-22  3:00   ` Mike Stump
  1 sibling, 0 replies; 9+ messages in thread
From: Mike Stump @ 2012-08-22  3:00 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 532 bytes --]

On Jul 19, 2012, at 11:24 AM, Richard Henderson wrote:
> +# 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

Breaks my port without the attached patch...


[-- Attachment #2: opinit.diffs.txt --]
[-- Type: text/plain, Size: 675 bytes --]

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 67f1d66..bd31c9b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3484,7 +3484,7 @@ s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
 # 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) \
+	$(RUN_GEN) build/genopinit$(build_exeext) $(MD_INCS) $(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

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-08-22  3:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-19 18:24 [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Henderson
2012-07-19 18:24 ` [PATCH 2/4] Tidy some include usage + dependencies Richard Henderson
2012-07-19 18:24 ` [PATCH 3/4] Introduce and use code_to_optab and optab_to_code functions Richard Henderson
2012-07-19 18:24 ` [PATCH 1/4] Introduce and use unknown_optab Richard Henderson
2012-07-19 18:25 ` [PATCH 4/4] Reduce the size of optabs representation Richard Henderson
2012-07-19 20:24   ` Jakub Jelinek
2012-08-22  3:00   ` Mike Stump
2012-07-20  8:40 ` [PATCH 0/4] [RFC] Reduce the representation size of optabs Richard Guenther
2012-07-24 16:52   ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).