diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b495bd2..806188f 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1350,6 +1350,9 @@ OBJS = \
 	modulo-sched.o \
 	omp-low.o \
 	optabs.o \
+	optabs-libfuncs.o \
+	optabs-query.o \
+	optabs-tree.o \
 	options-save.o \
 	opts-global.o \
 	passes.o \
@@ -2330,7 +2333,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/expr.h \
   $(srcdir)/function.c $(srcdir)/except.c \
   $(srcdir)/gcse.c $(srcdir)/godump.c \
-  $(srcdir)/lists.c $(srcdir)/optabs.c \
+  $(srcdir)/lists.c $(srcdir)/optabs-libfuncs.c \
   $(srcdir)/profile.c $(srcdir)/mcf.c \
   $(srcdir)/reg-stack.c $(srcdir)/cfgrtl.c \
   $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c
index d8340b2..62acc18 100644
--- a/gcc/cilk-common.c
+++ b/gcc/cilk-common.c
@@ -44,7 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
 #include "recog.h"
 #include "tree-iterator.h"
 #include "gimplify.h"
diff --git a/gcc/expr.c b/gcc/expr.c
index cf28f44..165b016 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
 #include "expr.h"
 #include "insn-codes.h"
+#include "optabs-tree.h"
 #include "optabs.h"
 #include "libfuncs.h"
 #include "recog.h"
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e9366e2..aafea16 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -76,7 +76,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "cgraph.h"
 #include "generic-match.h"
-#include "optabs.h"
+#include "optabs-query.h"
 
 #ifndef LOAD_EXTEND_OP
 #define LOAD_EXTEND_OP(M) UNKNOWN
diff --git a/gcc/function.c b/gcc/function.c
index 2c5a6d4..bf584be 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
+#include "optabs-tree.h"
 #include "optabs.h"
 #include "libfuncs.h"
 #include "regs.h"
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 77e81f5..167815d 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -377,6 +377,9 @@ main (int argc, char **argv)
      purging of the X patterns above.  */
   qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
 
+  fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
+  fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
+
   /* Emit the optab enumeration for the header file.  */
   fprintf (h_file, "enum optab_tag {\n");
   for (i = j = 0; i < n; ++i)
@@ -426,6 +429,7 @@ main (int argc, char **argv)
 	   "   the body of that kind of insn.  */\n"
 	   "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
 	   "\n"
+	   "#ifdef NUM_RTX_CODE\n"
 	   "/* Contains the optab used for each rtx code, and vice-versa.  */\n"
 	   "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
 	   "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
@@ -441,6 +445,7 @@ main (int argc, char **argv)
 	   "{\n"
 	   "  return optab_to_code_[op];\n"
 	   "}\n"
+	   "#endif\n"
 	   "\n"
 	   "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
 	   "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
@@ -594,6 +599,7 @@ main (int argc, char **argv)
     }
   fprintf (s_file, "};\n\n");
 
+  fprintf (h_file, "#endif\n");
   return (fclose (h_file) == 0 && fclose (s_file) == 0
 	  ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
 }
diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
new file mode 100644
index 0000000..bace520
--- /dev/null
+++ b/gcc/optabs-libfuncs.c
@@ -0,0 +1,974 @@
+/* Mapping from optabs to underlying library functions
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "insn-codes.h"
+#include "optabs-libfuncs.h"
+#include "libfuncs.h"
+#include "optabs-query.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "varasm.h"
+#include "stor-layout.h"
+#include "rtl.h"
+
+struct target_libfuncs default_target_libfuncs;
+#if SWITCHABLE_TARGET
+struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
+#endif
+
+#define libfunc_hash \
+  (this_target_libfuncs->x_libfunc_hash)
+
+/* Prefixes for the current version of decimal floating point (BID vs. DPD) */
+#if ENABLE_DECIMAL_BID_FORMAT
+#define DECIMAL_PREFIX "bid_"
+#else
+#define DECIMAL_PREFIX "dpd_"
+#endif
+
+/* Used for libfunc_hash.  */
+
+hashval_t
+libfunc_hasher::hash (libfunc_entry *e)
+{
+  return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
+}
+
+/* Used for libfunc_hash.  */
+
+bool
+libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
+{
+  return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
+}
+
+/* Return libfunc corresponding operation defined by OPTAB converting
+   from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
+   if no libfunc is available.  */
+rtx
+convert_optab_libfunc (convert_optab optab, machine_mode mode1,
+		       machine_mode mode2)
+{
+  struct libfunc_entry e;
+  struct libfunc_entry **slot;
+
+  /* ??? 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 = libfunc_hash->find_slot (&e, NO_INSERT);
+  if (!slot)
+    {
+      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 = libfunc_hash->find_slot (&e, NO_INSERT);
+      if (!slot)
+	return NULL;
+    }
+  return (*slot)->libfunc;
+}
+
+/* Return libfunc corresponding operation defined by OPTAB in MODE.
+   Trigger lazy initialization if needed, return NULL if no libfunc is
+   available.  */
+rtx
+optab_libfunc (optab optab, machine_mode mode)
+{
+  struct libfunc_entry e;
+  struct libfunc_entry **slot;
+
+  /* ??? 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 = libfunc_hash->find_slot (&e, NO_INSERT);
+  if (!slot)
+    {
+      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 = libfunc_hash->find_slot (&e, NO_INSERT);
+      if (!slot)
+	return NULL;
+    }
+  return (*slot)->libfunc;
+}
+
+/* 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
+   a mode name (downshifted to lowercase) followed by a single character
+   representing the number of operands for the given operation (which is
+   usually one of the characters '2', '3', or '4').
+
+   OPTABLE is the table in which libfunc fields are to be initialized.
+   OPNAME is the generic (string) name of the operation.
+   SUFFIX is the character which specifies the number of operands for
+     the given generic operation.
+   MODE is the mode to generate for.  */
+
+static void
+gen_libfunc (optab optable, const char *opname, int suffix,
+	     machine_mode mode)
+{
+  unsigned opname_len = strlen (opname);
+  const char *mname = GET_MODE_NAME (mode);
+  unsigned mname_len = strlen (mname);
+  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
+  int len = prefix_len + opname_len + mname_len + 1 + 1;
+  char *libfunc_name = XALLOCAVEC (char, len);
+  char *p;
+  const char *q;
+
+  p = libfunc_name;
+  *p++ = '_';
+  *p++ = '_';
+  if (targetm.libfunc_gnu_prefix)
+    {
+      *p++ = 'g';
+      *p++ = 'n';
+      *p++ = 'u';
+      *p++ = '_';
+    }
+  for (q = opname; *q;)
+    *p++ = *q++;
+  for (q = mname; *q; q++)
+    *p++ = TOLOWER (*q);
+  *p++ = suffix;
+  *p = '\0';
+
+  set_optab_libfunc (optable, mode,
+		     ggc_alloc_string (libfunc_name, p - libfunc_name));
+}
+
+/* Like gen_libfunc, but verify that integer operation is involved.  */
+
+void
+gen_int_libfunc (optab optable, const char *opname, char suffix,
+		 machine_mode mode)
+{
+  int maxsize = 2 * BITS_PER_WORD;
+  int minsize = BITS_PER_WORD;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return;
+  if (maxsize < LONG_LONG_TYPE_SIZE)
+    maxsize = LONG_LONG_TYPE_SIZE;
+  if (minsize > INT_TYPE_SIZE
+      && (trapv_binoptab_p (optable)
+	  || trapv_unoptab_p (optable)))
+    minsize = INT_TYPE_SIZE;
+  if (GET_MODE_BITSIZE (mode) < minsize
+      || GET_MODE_BITSIZE (mode) > maxsize)
+    return;
+  gen_libfunc (optable, opname, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
+
+void
+gen_fp_libfunc (optab optable, const char *opname, char suffix,
+		machine_mode mode)
+{
+  char *dec_opname;
+
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    gen_libfunc (optable, opname, suffix, mode);
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    {
+      dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
+      /* For BID support, change the name to have either a bid_ or dpd_ prefix
+	 depending on the low level floating format used.  */
+      memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
+      strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
+      gen_libfunc (optable, dec_opname, suffix, mode);
+    }
+}
+
+/* Like gen_libfunc, but verify that fixed-point operation is involved.  */
+
+void
+gen_fixed_libfunc (optab optable, const char *opname, char suffix,
+		   machine_mode mode)
+{
+  if (!ALL_FIXED_POINT_MODE_P (mode))
+    return;
+  gen_libfunc (optable, opname, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that signed fixed-point operation is
+   involved.  */
+
+void
+gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
+			  machine_mode mode)
+{
+  if (!SIGNED_FIXED_POINT_MODE_P (mode))
+    return;
+  gen_libfunc (optable, opname, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that unsigned fixed-point operation is
+   involved.  */
+
+void
+gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
+			    machine_mode mode)
+{
+  if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
+    return;
+  gen_libfunc (optable, opname, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that FP or INT operation is involved.  */
+
+void
+gen_int_fp_libfunc (optab optable, const char *name, char suffix,
+		    machine_mode mode)
+{
+  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
+    gen_fp_libfunc (optable, name, suffix, mode);
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that FP or INT operation is involved
+   and add 'v' suffix for integer operation.  */
+
+void
+gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
+		     machine_mode mode)
+{
+  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
+    gen_fp_libfunc (optable, name, suffix, mode);
+  if (GET_MODE_CLASS (mode) == MODE_INT)
+    {
+      int len = strlen (name);
+      char *v_name = XALLOCAVEC (char, len + 2);
+      strcpy (v_name, name);
+      v_name[len] = 'v';
+      v_name[len + 1] = 0;
+      gen_int_libfunc (optable, v_name, suffix, mode);
+    }
+}
+
+/* Like gen_libfunc, but verify that FP or INT or FIXED operation is
+   involved.  */
+
+void
+gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
+			  machine_mode mode)
+{
+  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
+    gen_fp_libfunc (optable, name, suffix, mode);
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+  if (ALL_FIXED_POINT_MODE_P (mode))
+    gen_fixed_libfunc (optable, name, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
+   involved.  */
+
+void
+gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
+				 machine_mode mode)
+{
+  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
+    gen_fp_libfunc (optable, name, suffix, mode);
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+  if (SIGNED_FIXED_POINT_MODE_P (mode))
+    gen_signed_fixed_libfunc (optable, name, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that INT or FIXED operation is
+   involved.  */
+
+void
+gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
+		       machine_mode mode)
+{
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+  if (ALL_FIXED_POINT_MODE_P (mode))
+    gen_fixed_libfunc (optable, name, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that INT or signed FIXED operation is
+   involved.  */
+
+void
+gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
+			      machine_mode mode)
+{
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+  if (SIGNED_FIXED_POINT_MODE_P (mode))
+    gen_signed_fixed_libfunc (optable, name, suffix, mode);
+}
+
+/* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
+   involved.  */
+
+void
+gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
+				machine_mode mode)
+{
+  if (INTEGRAL_MODE_P (mode))
+    gen_int_libfunc (optable, name, suffix, mode);
+  if (UNSIGNED_FIXED_POINT_MODE_P (mode))
+    gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
+}
+
+/* Initialize the libfunc fields of an entire group of entries of an
+   inter-mode-class conversion optab.  The string formation rules are
+   similar to the ones for init_libfuncs, above, but instead of having
+   a mode name and an operand count these functions have two mode names
+   and no operand count.  */
+
+void
+gen_interclass_conv_libfunc (convert_optab tab,
+			     const char *opname,
+			     machine_mode tmode,
+			     machine_mode fmode)
+{
+  size_t opname_len = strlen (opname);
+  size_t mname_len = 0;
+
+  const char *fname, *tname;
+  const char *q;
+  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
+  char *libfunc_name, *suffix;
+  char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
+  char *p;
+
+  /* If this is a decimal conversion, add the current BID vs. DPD prefix that
+     depends on which underlying decimal floating point format is used.  */
+  const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
+
+  mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
+
+  nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
+  nondec_name[0] = '_';
+  nondec_name[1] = '_';
+  if (targetm.libfunc_gnu_prefix)
+    {
+      nondec_name[2] = 'g';
+      nondec_name[3] = 'n';
+      nondec_name[4] = 'u';
+      nondec_name[5] = '_';
+    }
+
+  memcpy (&nondec_name[prefix_len], opname, opname_len);
+  nondec_suffix = nondec_name + opname_len + prefix_len;
+
+  dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
+  dec_name[0] = '_';
+  dec_name[1] = '_';
+  memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
+  memcpy (&dec_name[2+dec_len], opname, opname_len);
+  dec_suffix = dec_name + dec_len + opname_len + 2;
+
+  fname = GET_MODE_NAME (fmode);
+  tname = GET_MODE_NAME (tmode);
+
+  if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
+    {
+      libfunc_name = dec_name;
+      suffix = dec_suffix;
+    }
+  else
+    {
+      libfunc_name = nondec_name;
+      suffix = nondec_suffix;
+    }
+
+  p = suffix;
+  for (q = fname; *q; p++, q++)
+    *p = TOLOWER (*q);
+  for (q = tname; *q; p++, q++)
+    *p = TOLOWER (*q);
+
+  *p = '\0';
+
+  set_conv_libfunc (tab, tmode, fmode,
+		    ggc_alloc_string (libfunc_name, p - libfunc_name));
+}
+
+/* Same as gen_interclass_conv_libfunc but verify that we are producing
+   int->fp conversion.  */
+
+void
+gen_int_to_fp_conv_libfunc (convert_optab tab,
+			    const char *opname,
+			    machine_mode tmode,
+			    machine_mode fmode)
+{
+  if (GET_MODE_CLASS (fmode) != MODE_INT)
+    return;
+  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
+    return;
+  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* ufloat_optab is special by using floatun for FP and floatuns decimal fp
+   naming scheme.  */
+
+void
+gen_ufloat_conv_libfunc (convert_optab tab,
+			 const char *opname ATTRIBUTE_UNUSED,
+			 machine_mode tmode,
+			 machine_mode fmode)
+{
+  if (DECIMAL_FLOAT_MODE_P (tmode))
+    gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
+  else
+    gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
+}
+
+/* Same as gen_interclass_conv_libfunc but verify that we are producing
+   fp->int conversion.  */
+
+void
+gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
+				       const char *opname,
+				       machine_mode tmode,
+				       machine_mode fmode)
+{
+  if (GET_MODE_CLASS (fmode) != MODE_INT)
+    return;
+  if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
+    return;
+  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Same as gen_interclass_conv_libfunc but verify that we are producing
+   fp->int conversion with no decimal floating point involved.  */
+
+void
+gen_fp_to_int_conv_libfunc (convert_optab tab,
+			    const char *opname,
+			    machine_mode tmode,
+			    machine_mode fmode)
+{
+  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
+    return;
+  if (GET_MODE_CLASS (tmode) != MODE_INT)
+    return;
+  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
+   The string formation rules are
+   similar to the ones for init_libfunc, above.  */
+
+void
+gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
+			     machine_mode tmode, machine_mode fmode)
+{
+  size_t opname_len = strlen (opname);
+  size_t mname_len = 0;
+
+  const char *fname, *tname;
+  const char *q;
+  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
+  char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
+  char *libfunc_name, *suffix;
+  char *p;
+
+  /* If this is a decimal conversion, add the current BID vs. DPD prefix that
+     depends on which underlying decimal floating point format is used.  */
+  const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
+
+  mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
+
+  nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
+  nondec_name[0] = '_';
+  nondec_name[1] = '_';
+  if (targetm.libfunc_gnu_prefix)
+    {
+      nondec_name[2] = 'g';
+      nondec_name[3] = 'n';
+      nondec_name[4] = 'u';
+      nondec_name[5] = '_';
+    }
+  memcpy (&nondec_name[prefix_len], opname, opname_len);
+  nondec_suffix = nondec_name + opname_len + prefix_len;
+
+  dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
+  dec_name[0] = '_';
+  dec_name[1] = '_';
+  memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
+  memcpy (&dec_name[2 + dec_len], opname, opname_len);
+  dec_suffix = dec_name + dec_len + opname_len + 2;
+
+  fname = GET_MODE_NAME (fmode);
+  tname = GET_MODE_NAME (tmode);
+
+  if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
+    {
+      libfunc_name = dec_name;
+      suffix = dec_suffix;
+    }
+  else
+    {
+      libfunc_name = nondec_name;
+      suffix = nondec_suffix;
+    }
+
+  p = suffix;
+  for (q = fname; *q; p++, q++)
+    *p = TOLOWER (*q);
+  for (q = tname; *q; p++, q++)
+    *p = TOLOWER (*q);
+
+  *p++ = '2';
+  *p = '\0';
+
+  set_conv_libfunc (tab, tmode, fmode,
+		    ggc_alloc_string (libfunc_name, p - libfunc_name));
+}
+
+/* Pick proper libcall for trunc_optab.  We need to chose if we do
+   truncation or extension and interclass or intraclass.  */
+
+void
+gen_trunc_conv_libfunc (convert_optab tab,
+			const char *opname,
+			machine_mode tmode,
+			machine_mode fmode)
+{
+  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
+    return;
+  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
+    return;
+  if (tmode == fmode)
+    return;
+
+  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
+      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
+     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+
+  if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
+    return;
+
+  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
+       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
+      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
+    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Pick proper libcall for extend_optab.  We need to chose if we do
+   truncation or extension and interclass or intraclass.  */
+
+void
+gen_extend_conv_libfunc (convert_optab tab,
+			 const char *opname ATTRIBUTE_UNUSED,
+			 machine_mode tmode,
+			 machine_mode fmode)
+{
+  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
+    return;
+  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
+    return;
+  if (tmode == fmode)
+    return;
+
+  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
+      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
+     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+
+  if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
+    return;
+
+  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
+       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
+      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
+    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Pick proper libcall for fract_optab.  We need to chose if we do
+   interclass or intraclass.  */
+
+void
+gen_fract_conv_libfunc (convert_optab tab,
+			const char *opname,
+			machine_mode tmode,
+			machine_mode fmode)
+{
+  if (tmode == fmode)
+    return;
+  if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
+    return;
+
+  if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
+    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
+  else
+    gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Pick proper libcall for fractuns_optab.  */
+
+void
+gen_fractuns_conv_libfunc (convert_optab tab,
+			   const char *opname,
+			   machine_mode tmode,
+			   machine_mode fmode)
+{
+  if (tmode == fmode)
+    return;
+  /* One mode must be a fixed-point mode, and the other must be an integer
+     mode.  */
+  if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
+	|| (ALL_FIXED_POINT_MODE_P (fmode)
+	    && GET_MODE_CLASS (tmode) == MODE_INT)))
+    return;
+
+  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Pick proper libcall for satfract_optab.  We need to chose if we do
+   interclass or intraclass.  */
+
+void
+gen_satfract_conv_libfunc (convert_optab tab,
+			   const char *opname,
+			   machine_mode tmode,
+			   machine_mode fmode)
+{
+  if (tmode == fmode)
+    return;
+  /* TMODE must be a fixed-point mode.  */
+  if (!ALL_FIXED_POINT_MODE_P (tmode))
+    return;
+
+  if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
+    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
+  else
+    gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Pick proper libcall for satfractuns_optab.  */
+
+void
+gen_satfractuns_conv_libfunc (convert_optab tab,
+			      const char *opname,
+			      machine_mode tmode,
+			      machine_mode fmode)
+{
+  if (tmode == fmode)
+    return;
+  /* TMODE must be a fixed-point mode, and FMODE must be an integer mode.  */
+  if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
+    return;
+
+  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+}
+
+/* Hashtable callbacks for libfunc_decls.  */
+
+struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
+{
+  static hashval_t
+  hash (tree entry)
+  {
+    return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
+  }
+
+  static bool
+  equal (tree decl, tree name)
+  {
+    return DECL_NAME (decl) == name;
+  }
+};
+
+/* A table of previously-created libfuncs, hashed by name.  */
+static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
+
+/* Build a decl for a libfunc named NAME.  */
+
+tree
+build_libfunc_function (const char *name)
+{
+  tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
+			  get_identifier (name),
+			  build_function_type (integer_type_node, NULL_TREE));
+  /* ??? We don't have any type information except for this is
+     a function.  Pretend this is "int foo ()".  */
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  gcc_assert (DECL_ASSEMBLER_NAME (decl));
+
+  /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
+     are the flags assigned by targetm.encode_section_info.  */
+  SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
+
+  return decl;
+}
+
+/* Return a libfunc for NAME, creating one if we don't already have one.
+   The returned rtx is a SYMBOL_REF.  */
+
+rtx
+init_one_libfunc (const char *name)
+{
+  tree id, decl;
+  hashval_t hash;
+
+  if (libfunc_decls == NULL)
+    libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
+
+  /* See if we have already created a libfunc decl for this function.  */
+  id = get_identifier (name);
+  hash = IDENTIFIER_HASH_VALUE (id);
+  tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
+  decl = *slot;
+  if (decl == NULL)
+    {
+      /* Create a new decl, so that it can be passed to
+	 targetm.encode_section_info.  */
+      decl = build_libfunc_function (name);
+      *slot = decl;
+    }
+  return XEXP (DECL_RTL (decl), 0);
+}
+
+/* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
+
+rtx
+set_user_assembler_libfunc (const char *name, const char *asmspec)
+{
+  tree id, decl;
+  hashval_t hash;
+
+  id = get_identifier (name);
+  hash = IDENTIFIER_HASH_VALUE (id);
+  tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
+  gcc_assert (slot);
+  decl = (tree) *slot;
+  set_user_assembler_name (decl, asmspec);
+  return XEXP (DECL_RTL (decl), 0);
+}
+
+/* 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 op, machine_mode mode, const char *name)
+{
+  rtx val;
+  struct libfunc_entry e;
+  struct libfunc_entry **slot;
+
+  e.op = op;
+  e.mode1 = mode;
+  e.mode2 = VOIDmode;
+
+  if (name)
+    val = init_one_libfunc (name);
+  else
+    val = 0;
+  slot = libfunc_hash->find_slot (&e, INSERT);
+  if (*slot == NULL)
+    *slot = ggc_alloc<libfunc_entry> ();
+  (*slot)->op = op;
+  (*slot)->mode1 = mode;
+  (*slot)->mode2 = VOIDmode;
+  (*slot)->libfunc = val;
+}
+
+/* Call this to reset the function entry for one conversion optab
+   (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
+   either 0 or a string constant.  */
+
+void
+set_conv_libfunc (convert_optab optab, machine_mode tmode,
+		  machine_mode fmode, const char *name)
+{
+  rtx val;
+  struct libfunc_entry e;
+  struct libfunc_entry **slot;
+
+  e.op = optab;
+  e.mode1 = tmode;
+  e.mode2 = fmode;
+
+  if (name)
+    val = init_one_libfunc (name);
+  else
+    val = 0;
+  slot = libfunc_hash->find_slot (&e, INSERT);
+  if (*slot == NULL)
+    *slot = ggc_alloc<libfunc_entry> ();
+  (*slot)->op = optab;
+  (*slot)->mode1 = tmode;
+  (*slot)->mode2 = fmode;
+  (*slot)->libfunc = val;
+}
+
+/* Call this to initialize the contents of the optabs
+   appropriately for the current target machine.  */
+
+void
+init_optabs (void)
+{
+  if (libfunc_hash)
+    libfunc_hash->empty ();
+  else
+    libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
+
+  /* Fill in the optabs with the insns we support.  */
+  init_all_optabs (this_fn_optabs);
+
+  /* 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)
+    set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
+		       "ffs");
+
+  /* Explicitly initialize the bswap libfuncs since we need them to be
+     valid for things other than word_mode.  */
+  if (targetm.libfunc_gnu_prefix)
+    {
+      set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
+      set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
+    }
+  else
+    {
+      set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
+      set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
+    }
+
+  /* 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");
+
+  abort_libfunc = init_one_libfunc ("abort");
+  memcpy_libfunc = init_one_libfunc ("memcpy");
+  memmove_libfunc = init_one_libfunc ("memmove");
+  memcmp_libfunc = init_one_libfunc ("memcmp");
+  memset_libfunc = init_one_libfunc ("memset");
+  setbits_libfunc = init_one_libfunc ("__setbits");
+
+#ifndef DONT_USE_BUILTIN_SETJMP
+  setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
+  longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
+#else
+  setjmp_libfunc = init_one_libfunc ("setjmp");
+  longjmp_libfunc = init_one_libfunc ("longjmp");
+#endif
+  unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
+  unwind_sjlj_unregister_libfunc
+    = init_one_libfunc ("_Unwind_SjLj_Unregister");
+
+  /* For function entry/exit instrumentation.  */
+  profile_function_entry_libfunc
+    = init_one_libfunc ("__cyg_profile_func_enter");
+  profile_function_exit_libfunc
+    = init_one_libfunc ("__cyg_profile_func_exit");
+
+  gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
+
+  /* Allow the target to add more libcalls or rename some, etc.  */
+  targetm.init_libfuncs ();
+}
+
+/* A helper function for init_sync_libfuncs.  Using the basename BASE,
+   install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
+
+static void
+init_sync_libfuncs_1 (optab tab, const char *base, int max)
+{
+  machine_mode mode;
+  char buf[64];
+  size_t len = strlen (base);
+  int i;
+
+  gcc_assert (max <= 8);
+  gcc_assert (len + 3 < sizeof (buf));
+
+  memcpy (buf, base, len);
+  buf[len] = '_';
+  buf[len + 1] = '0';
+  buf[len + 2] = '\0';
+
+  mode = QImode;
+  for (i = 1; i <= max; i *= 2)
+    {
+      buf[len + 1] = '0' + i;
+      set_optab_libfunc (tab, mode, buf);
+      mode = GET_MODE_2XWIDER_MODE (mode);
+    }
+}
+
+void
+init_sync_libfuncs (int max)
+{
+  if (!flag_sync_libcalls)
+    return;
+
+  init_sync_libfuncs_1 (sync_compare_and_swap_optab,
+			"__sync_val_compare_and_swap", max);
+  init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
+			"__sync_lock_test_and_set", max);
+
+  init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
+  init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
+  init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
+  init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
+  init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
+  init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
+
+  init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
+  init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
+}
+
+#include "gt-optabs-libfuncs.h"
diff --git a/gcc/optabs-libfuncs.h b/gcc/optabs-libfuncs.h
new file mode 100644
index 0000000..4e43c80
--- /dev/null
+++ b/gcc/optabs-libfuncs.h
@@ -0,0 +1,77 @@
+/* Mapping from optabs to underlying library functions
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OPTABS_LIBFUNCS_H
+#define GCC_OPTABS_LIBFUNCS_H
+
+#include "insn-opinit.h"
+
+rtx convert_optab_libfunc (convert_optab, machine_mode, machine_mode);
+rtx optab_libfunc (optab, machine_mode);
+
+void gen_int_libfunc (optab, const char *, char, machine_mode);
+void gen_fp_libfunc (optab, const char *, char, machine_mode);
+void gen_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_signed_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_unsigned_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_int_fp_libfunc (optab, const char *, char, machine_mode);
+void gen_intv_fp_libfunc (optab, const char *, char, machine_mode);
+void gen_int_fp_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_int_fp_signed_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_int_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_int_signed_fixed_libfunc (optab, const char *, char, machine_mode);
+void gen_int_unsigned_fixed_libfunc (optab, const char *, char, machine_mode);
+
+void gen_interclass_conv_libfunc (convert_optab, const char *,
+				  machine_mode, machine_mode);
+void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
+				 machine_mode, machine_mode);
+void gen_ufloat_conv_libfunc (convert_optab, const char *,
+			      machine_mode, machine_mode);
+void gen_int_to_fp_nondecimal_conv_libfunc (convert_optab, const char *,
+					    machine_mode, machine_mode);
+void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
+				 machine_mode, machine_mode);
+void gen_intraclass_conv_libfunc (convert_optab, const char *,
+				  machine_mode, machine_mode);
+void gen_trunc_conv_libfunc (convert_optab, const char *,
+			     machine_mode, machine_mode);
+void gen_extend_conv_libfunc (convert_optab, const char *,
+			      machine_mode, machine_mode);
+void gen_fract_conv_libfunc (convert_optab, const char *,
+			     machine_mode, machine_mode);
+void gen_fractuns_conv_libfunc (convert_optab, const char *,
+				machine_mode, machine_mode);
+void gen_satfract_conv_libfunc (convert_optab, const char *,
+				machine_mode, machine_mode);
+void gen_satfractuns_conv_libfunc (convert_optab, const char *,
+				   machine_mode, machine_mode);
+
+tree build_libfunc_function (const char *);
+rtx init_one_libfunc (const char *);
+rtx set_user_assembler_libfunc (const char *, const char *);
+
+void set_optab_libfunc (optab, machine_mode, const char *);
+void set_conv_libfunc (convert_optab, machine_mode,
+		       machine_mode, const char *);
+
+void init_optabs (void);
+void init_sync_libfuncs (int max);
+
+#endif
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
new file mode 100644
index 0000000..254089f
--- /dev/null
+++ b/gcc/optabs-query.c
@@ -0,0 +1,573 @@
+/* IR-agnostic target query functions relating to optabs
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "insn-codes.h"
+#include "optabs-query.h"
+#include "optabs-libfuncs.h"
+#include "insn-config.h"
+#include "rtl.h"
+#include "recog.h"
+
+struct target_optabs default_target_optabs;
+struct target_optabs *this_fn_optabs = &default_target_optabs;
+#if SWITCHABLE_TARGET
+struct target_optabs *this_target_optabs = &default_target_optabs;
+#endif
+
+/* Enumerates the possible types of structure operand to an
+   extraction_insn.  */
+enum extraction_type { ET_unaligned_mem, ET_reg };
+
+/* Check whether insv, extv or extzv pattern ICODE can be used for an
+   insertion or extraction of type TYPE on a structure of mode MODE.
+   Return true if so and fill in *INSN accordingly.  STRUCT_OP is the
+   operand number of the structure (the first sign_extract or zero_extract
+   operand) and FIELD_OP is the operand number of the field (the other
+   side of the set from the sign_extract or zero_extract).  */
+
+static bool
+get_traditional_extraction_insn (extraction_insn *insn,
+				 enum extraction_type type,
+				 machine_mode mode,
+				 enum insn_code icode,
+				 int struct_op, int field_op)
+{
+  const struct insn_data_d *data = &insn_data[icode];
+
+  machine_mode struct_mode = data->operand[struct_op].mode;
+  if (struct_mode == VOIDmode)
+    struct_mode = word_mode;
+  if (mode != struct_mode)
+    return false;
+
+  machine_mode field_mode = data->operand[field_op].mode;
+  if (field_mode == VOIDmode)
+    field_mode = word_mode;
+
+  machine_mode pos_mode = data->operand[struct_op + 2].mode;
+  if (pos_mode == VOIDmode)
+    pos_mode = word_mode;
+
+  insn->icode = icode;
+  insn->field_mode = field_mode;
+  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
+  insn->pos_mode = pos_mode;
+  return true;
+}
+
+/* Return true if an optab exists to perform an insertion or extraction
+   of type TYPE in mode MODE.  Describe the instruction in *INSN if so.
+
+   REG_OPTAB is the optab to use for register structures and
+   MISALIGN_OPTAB is the optab to use for misaligned memory structures.
+   POS_OP is the operand number of the bit position.  */
+
+static bool
+get_optab_extraction_insn (struct extraction_insn *insn,
+			   enum extraction_type type,
+			   machine_mode mode, direct_optab reg_optab,
+			   direct_optab misalign_optab, int pos_op)
+{
+  direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
+  enum insn_code icode = direct_optab_handler (optab, mode);
+  if (icode == CODE_FOR_nothing)
+    return false;
+
+  const struct insn_data_d *data = &insn_data[icode];
+
+  insn->icode = icode;
+  insn->field_mode = mode;
+  insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
+  insn->pos_mode = data->operand[pos_op].mode;
+  if (insn->pos_mode == VOIDmode)
+    insn->pos_mode = word_mode;
+  return true;
+}
+
+/* Return true if an instruction exists to perform an insertion or
+   extraction (PATTERN says which) of type TYPE in mode MODE.
+   Describe the instruction in *INSN if so.  */
+
+static bool
+get_extraction_insn (extraction_insn *insn,
+		     enum extraction_pattern pattern,
+		     enum extraction_type type,
+		     machine_mode mode)
+{
+  switch (pattern)
+    {
+    case EP_insv:
+      if (targetm.have_insv ()
+	  && get_traditional_extraction_insn (insn, type, mode,
+					      targetm.code_for_insv, 0, 3))
+	return true;
+      return get_optab_extraction_insn (insn, type, mode, insv_optab,
+					insvmisalign_optab, 2);
+
+    case EP_extv:
+      if (targetm.have_extv ()
+	  && get_traditional_extraction_insn (insn, type, mode,
+					      targetm.code_for_extv, 1, 0))
+	return true;
+      return get_optab_extraction_insn (insn, type, mode, extv_optab,
+					extvmisalign_optab, 3);
+
+    case EP_extzv:
+      if (targetm.have_extzv ()
+	  && get_traditional_extraction_insn (insn, type, mode,
+					      targetm.code_for_extzv, 1, 0))
+	return true;
+      return get_optab_extraction_insn (insn, type, mode, extzv_optab,
+					extzvmisalign_optab, 3);
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return true if an instruction exists to access a field of mode
+   FIELDMODE in a structure that has STRUCT_BITS significant bits.
+   Describe the "best" such instruction in *INSN if so.  PATTERN and
+   TYPE describe the type of insertion or extraction we want to perform.
+
+   For an insertion, the number of significant structure bits includes
+   all bits of the target.  For an extraction, it need only include the
+   most significant bit of the field.  Larger widths are acceptable
+   in both cases.  */
+
+static bool
+get_best_extraction_insn (extraction_insn *insn,
+			  enum extraction_pattern pattern,
+			  enum extraction_type type,
+			  unsigned HOST_WIDE_INT struct_bits,
+			  machine_mode field_mode)
+{
+  machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
+  while (mode != VOIDmode)
+    {
+      if (get_extraction_insn (insn, pattern, type, mode))
+	{
+	  while (mode != VOIDmode
+		 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
+		 && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
+						    field_mode))
+	    {
+	      get_extraction_insn (insn, pattern, type, mode);
+	      mode = GET_MODE_WIDER_MODE (mode);
+	    }
+	  return true;
+	}
+      mode = GET_MODE_WIDER_MODE (mode);
+    }
+  return false;
+}
+
+/* Return true if an instruction exists to access a field of mode
+   FIELDMODE in a register structure that has STRUCT_BITS significant bits.
+   Describe the "best" such instruction in *INSN if so.  PATTERN describes
+   the type of insertion or extraction we want to perform.
+
+   For an insertion, the number of significant structure bits includes
+   all bits of the target.  For an extraction, it need only include the
+   most significant bit of the field.  Larger widths are acceptable
+   in both cases.  */
+
+bool
+get_best_reg_extraction_insn (extraction_insn *insn,
+			      enum extraction_pattern pattern,
+			      unsigned HOST_WIDE_INT struct_bits,
+			      machine_mode field_mode)
+{
+  return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
+				   field_mode);
+}
+
+/* Return true if an instruction exists to access a field of BITSIZE
+   bits starting BITNUM bits into a memory structure.  Describe the
+   "best" such instruction in *INSN if so.  PATTERN describes the type
+   of insertion or extraction we want to perform and FIELDMODE is the
+   natural mode of the extracted field.
+
+   The instructions considered here only access bytes that overlap
+   the bitfield; they do not touch any surrounding bytes.  */
+
+bool
+get_best_mem_extraction_insn (extraction_insn *insn,
+			      enum extraction_pattern pattern,
+			      HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
+			      machine_mode field_mode)
+{
+  unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
+					+ bitsize
+					+ BITS_PER_UNIT - 1);
+  struct_bits -= struct_bits % BITS_PER_UNIT;
+  return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
+				   struct_bits, field_mode);
+}
+
+/* Return the insn code used to extend FROM_MODE to TO_MODE.
+   UNSIGNEDP specifies zero-extension instead of sign-extension.  If
+   no such operation exists, CODE_FOR_nothing will be returned.  */
+
+enum insn_code
+can_extend_p (machine_mode to_mode, machine_mode from_mode,
+	      int unsignedp)
+{
+  if (unsignedp < 0 && targetm.have_ptr_extend ())
+    return targetm.code_for_ptr_extend;
+
+  convert_optab tab = unsignedp ? zext_optab : sext_optab;
+  return convert_optab_handler (tab, to_mode, from_mode);
+}
+
+/* Return the insn code to convert fixed-point mode FIXMODE to floating-point
+   mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
+   UNSIGNEDP specifies whether FIXMODE is unsigned.  */
+
+enum insn_code
+can_float_p (machine_mode fltmode, machine_mode fixmode,
+	     int unsignedp)
+{
+  convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
+  return convert_optab_handler (tab, fltmode, fixmode);
+}
+
+/* Return the insn code to convert floating-point mode FLTMODE to fixed-point
+   mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
+   UNSIGNEDP specifies whether FIXMODE is unsigned.
+
+   On a successful return, set *TRUNCP_PTR to true if it is necessary to
+   output an explicit FTRUNC before the instruction.  */
+
+enum insn_code
+can_fix_p (machine_mode fixmode, machine_mode fltmode,
+	   int unsignedp, bool *truncp_ptr)
+{
+  convert_optab tab;
+  enum insn_code icode;
+
+  tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
+  icode = convert_optab_handler (tab, fixmode, fltmode);
+  if (icode != CODE_FOR_nothing)
+    {
+      *truncp_ptr = false;
+      return icode;
+    }
+
+  /* FIXME: This requires a port to define both FIX and FTRUNC pattern
+     for this to work.  We need to rework the fix* and ftrunc* patterns
+     and documentation.  */
+  tab = unsignedp ? ufix_optab : sfix_optab;
+  icode = convert_optab_handler (tab, fixmode, fltmode);
+  if (icode != CODE_FOR_nothing
+      && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
+    {
+      *truncp_ptr = true;
+      return icode;
+    }
+
+  return CODE_FOR_nothing;
+}
+
+/* Return nonzero if a conditional move of mode MODE is supported.
+
+   This function is for combine so it can tell whether an insn that looks
+   like a conditional move is actually supported by the hardware.  If we
+   guess wrong we lose a bit on optimization, but that's it.  */
+/* ??? sparc64 supports conditionally moving integers values based on fp
+   comparisons, and vice versa.  How do we handle them?  */
+
+bool
+can_conditionally_move_p (machine_mode mode)
+{
+  return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
+}
+
+/* Return true if VEC_PERM_EXPR of arbitrary input vectors can be
+   expanded using SIMD extensions of the CPU.  SEL may be NULL, which
+   stands for an unknown constant.  Note that additional permutations
+   representing whole-vector shifts may also be handled via the vec_shr
+   optab, but only where the second input vector is entirely constant
+   zeroes; this case is not dealt with here.  */
+
+bool
+can_vec_perm_p (machine_mode mode, bool variable,
+		const unsigned char *sel)
+{
+  machine_mode qimode;
+
+  /* If the target doesn't implement a vector mode for the vector type,
+     then no operations are supported.  */
+  if (!VECTOR_MODE_P (mode))
+    return false;
+
+  if (!variable)
+    {
+      if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
+	  && (sel == NULL
+	      || targetm.vectorize.vec_perm_const_ok == NULL
+	      || targetm.vectorize.vec_perm_const_ok (mode, sel)))
+	return true;
+    }
+
+  if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
+    return true;
+
+  /* We allow fallback to a QI vector mode, and adjust the mask.  */
+  if (GET_MODE_INNER (mode) == QImode)
+    return false;
+  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
+  if (!VECTOR_MODE_P (qimode))
+    return false;
+
+  /* ??? For completeness, we ought to check the QImode version of
+      vec_perm_const_optab.  But all users of this implicit lowering
+      feature implement the variable vec_perm_optab.  */
+  if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
+    return false;
+
+  /* In order to support the lowering of variable permutations,
+     we need to support shifts and adds.  */
+  if (variable)
+    {
+      if (GET_MODE_UNIT_SIZE (mode) > 2
+	  && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
+	  && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
+	return false;
+      if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
+	return false;
+    }
+
+  return true;
+}
+
+/* Like optab_handler, but for widening_operations that have a
+   TO_MODE and a FROM_MODE.  */
+
+enum insn_code
+widening_optab_handler (optab op, machine_mode to_mode,
+			machine_mode from_mode)
+{
+  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);
+}
+
+/* Find a widening optab even if it doesn't widen as much as we want.
+   E.g. if from_mode is HImode, and to_mode is DImode, and there is no
+   direct HI->SI insn, then return SI->DI, if that exists.
+   If PERMIT_NON_WIDENING is non-zero then this can be used with
+   non-widening optabs also.  */
+
+enum insn_code
+find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
+				      machine_mode from_mode,
+				      int permit_non_widening,
+				      machine_mode *found_mode)
+{
+  for (; (permit_non_widening || from_mode != to_mode)
+	 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
+	 && from_mode != VOIDmode;
+       from_mode = GET_MODE_WIDER_MODE (from_mode))
+    {
+      enum insn_code handler = widening_optab_handler (op, to_mode,
+						       from_mode);
+
+      if (handler != CODE_FOR_nothing)
+	{
+	  if (found_mode)
+	    *found_mode = from_mode;
+	  return handler;
+	}
+    }
+
+  return CODE_FOR_nothing;
+}
+
+/* Return non-zero if a highpart multiply is supported of can be synthisized.
+   For the benefit of expand_mult_highpart, the return value is 1 for direct,
+   2 for even/odd widening, and 3 for hi/lo widening.  */
+
+int
+can_mult_highpart_p (machine_mode mode, bool uns_p)
+{
+  optab op;
+  unsigned char *sel;
+  unsigned i, nunits;
+
+  op = uns_p ? umul_highpart_optab : smul_highpart_optab;
+  if (optab_handler (op, mode) != CODE_FOR_nothing)
+    return 1;
+
+  /* If the mode is an integral vector, synth from widening operations.  */
+  if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+    return 0;
+
+  nunits = GET_MODE_NUNITS (mode);
+  sel = XALLOCAVEC (unsigned char, nunits);
+
+  op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
+  if (optab_handler (op, mode) != CODE_FOR_nothing)
+    {
+      op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
+      if (optab_handler (op, mode) != CODE_FOR_nothing)
+	{
+	  for (i = 0; i < nunits; ++i)
+	    sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
+	  if (can_vec_perm_p (mode, false, sel))
+	    return 2;
+	}
+    }
+
+  op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
+  if (optab_handler (op, mode) != CODE_FOR_nothing)
+    {
+      op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
+      if (optab_handler (op, mode) != CODE_FOR_nothing)
+	{
+	  for (i = 0; i < nunits; ++i)
+	    sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
+	  if (can_vec_perm_p (mode, false, sel))
+	    return 3;
+	}
+    }
+
+  return 0;
+}
+
+/* Return true if target supports vector masked load/store for mode.  */
+
+bool
+can_vec_mask_load_store_p (machine_mode mode, bool is_load)
+{
+  optab op = is_load ? maskload_optab : maskstore_optab;
+  machine_mode vmode;
+  unsigned int vector_sizes;
+
+  /* If mode is vector mode, check it directly.  */
+  if (VECTOR_MODE_P (mode))
+    return optab_handler (op, mode) != CODE_FOR_nothing;
+
+  /* Otherwise, return true if there is some vector mode with
+     the mask load/store supported.  */
+
+  /* See if there is any chance the mask load or store might be
+     vectorized.  If not, punt.  */
+  vmode = targetm.vectorize.preferred_simd_mode (mode);
+  if (!VECTOR_MODE_P (vmode))
+    return false;
+
+  if (optab_handler (op, vmode) != CODE_FOR_nothing)
+    return true;
+
+  vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
+  while (vector_sizes != 0)
+    {
+      unsigned int cur = 1 << floor_log2 (vector_sizes);
+      vector_sizes &= ~cur;
+      if (cur <= GET_MODE_SIZE (mode))
+	continue;
+      vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
+      if (VECTOR_MODE_P (vmode)
+	  && optab_handler (op, vmode) != CODE_FOR_nothing)
+	return true;
+    }
+  return false;
+}
+
+/* Return true if there is a compare_and_swap pattern.  */
+
+bool
+can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
+{
+  enum insn_code icode;
+
+  /* Check for __atomic_compare_and_swap.  */
+  icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
+  if (icode != CODE_FOR_nothing)
+    return true;
+
+  /* Check for __sync_compare_and_swap.  */
+  icode = optab_handler (sync_compare_and_swap_optab, mode);
+  if (icode != CODE_FOR_nothing)
+    return true;
+  if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
+    return true;
+
+  /* No inline compare and swap.  */
+  return false;
+}
+
+/* Return true if an atomic exchange can be performed.  */
+
+bool
+can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
+{
+  enum insn_code icode;
+
+  /* Check for __atomic_exchange.  */
+  icode = direct_optab_handler (atomic_exchange_optab, mode);
+  if (icode != CODE_FOR_nothing)
+    return true;
+
+  /* Don't check __sync_test_and_set, as on some platforms that
+     has reduced functionality.  Targets that really do support
+     a proper exchange should simply be updated to the __atomics.  */
+
+  return can_compare_and_swap_p (mode, allow_libcall);
+}
+
+/* Determine whether "1 << x" is relatively cheap in word_mode.  */
+
+bool
+lshift_cheap_p (bool speed_p)
+{
+  /* FIXME: This should be made target dependent via this "this_target"
+     mechanism, similar to e.g. can_copy_init_p in gcse.c.  */
+  static bool init[2] = { false, false };
+  static bool cheap[2] = { true, true };
+
+  /* If the targer has no lshift in word_mode, the operation will most
+     probably not be cheap.  ??? Does GCC even work for such targets?  */
+  if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
+    return false;
+
+  if (!init[speed_p])
+    {
+      rtx reg = gen_raw_REG (word_mode, 10000);
+      int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
+			       word_mode, speed_p);
+      cheap[speed_p] = cost < COSTS_N_INSNS (3);
+      init[speed_p] = true;
+    }
+
+  return cheap[speed_p];
+}
diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
new file mode 100644
index 0000000..73f2729
--- /dev/null
+++ b/gcc/optabs-query.h
@@ -0,0 +1,138 @@
+/* IR-agnostic target query functions relating to optabs
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OPTABS_QUERY_H
+#define GCC_OPTABS_QUERY_H
+
+#include "insn-opinit.h"
+
+/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
+   if the target does not have such an insn.  */
+
+inline enum insn_code
+optab_handler (optab op, machine_mode mode)
+{
+  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
+   to mode TO_MODE; return CODE_FOR_nothing if the target does not have
+   such an insn.  */
+
+inline enum insn_code
+convert_optab_handler (convert_optab op, machine_mode to_mode,
+		       machine_mode from_mode)
+{
+  unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
+  gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
+  return raw_optab_handler (scode);
+}
+
+/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
+   if the target does not have such an insn.  */
+
+inline enum insn_code
+direct_optab_handler (direct_optab op, machine_mode mode)
+{
+  return optab_handler (op, mode);
+}
+
+/* Return true if UNOPTAB is for a trapping-on-overflow operation.  */
+
+inline bool
+trapv_unoptab_p (optab unoptab)
+{
+  return (unoptab == negv_optab
+	  || unoptab == absv_optab);
+}
+
+/* Return true if BINOPTAB is for a trapping-on-overflow operation.  */
+
+inline bool
+trapv_binoptab_p (optab binoptab)
+{
+  return (binoptab == addv_optab
+	  || binoptab == subv_optab
+	  || binoptab == smulv_optab);
+}
+
+/* Return insn code for a conditional operator with a comparison in
+   mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
+
+inline enum insn_code
+get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
+{
+  enum insn_code icode = CODE_FOR_nothing;
+  if (uns)
+    icode = convert_optab_handler (vcondu_optab, vmode, cmode);
+  else
+    icode = convert_optab_handler (vcond_optab, vmode, cmode);
+  return icode;
+}
+
+/* Enumerates the possible extraction_insn operations.  */
+enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
+
+/* Describes an instruction that inserts or extracts a bitfield.  */
+struct extraction_insn
+{
+  /* The code of the instruction.  */
+  enum insn_code icode;
+
+  /* The mode that the structure operand should have.  This is byte_mode
+     when using the legacy insv, extv and extzv patterns to access memory.  */
+  machine_mode struct_mode;
+
+  /* The mode of the field to be inserted or extracted, and by extension
+     the mode of the insertion or extraction itself.  */
+  machine_mode field_mode;
+
+  /* The mode of the field's bit position.  This is only important
+     when the position is variable rather than constant.  */
+  machine_mode pos_mode;
+};
+
+bool get_best_reg_extraction_insn (extraction_insn *,
+				   enum extraction_pattern,
+				   unsigned HOST_WIDE_INT, machine_mode);
+bool get_best_mem_extraction_insn (extraction_insn *,
+				   enum extraction_pattern,
+				   HOST_WIDE_INT, HOST_WIDE_INT, machine_mode);
+
+enum insn_code can_extend_p (machine_mode, machine_mode, int);
+enum insn_code can_float_p (machine_mode, machine_mode, int);
+enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *);
+bool can_conditionally_move_p (machine_mode mode);
+bool can_vec_perm_p (machine_mode, bool, const unsigned char *);
+enum insn_code widening_optab_handler (optab, machine_mode, machine_mode);
+/* Find a widening optab even if it doesn't widen as much as we want.  */
+#define find_widening_optab_handler(A,B,C,D) \
+  find_widening_optab_handler_and_mode (A, B, C, D, NULL)
+enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode,
+						     machine_mode, int,
+						     machine_mode *);
+int can_mult_highpart_p (machine_mode, bool);
+bool can_vec_mask_load_store_p (machine_mode, bool);
+bool can_compare_and_swap_p (machine_mode, bool);
+bool can_atomic_exchange_p (machine_mode, bool);
+bool lshift_cheap_p (bool);
+
+#endif
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
new file mode 100644
index 0000000..3b03338
--- /dev/null
+++ b/gcc/optabs-tree.c
@@ -0,0 +1,370 @@
+/* Tree-based target query functions relating to optabs
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "insn-codes.h"
+#include "tree.h"
+#include "optabs-tree.h"
+#include "stor-layout.h"
+
+/* Return the optab used for computing the operation given by the tree code,
+   CODE and the tree EXP.  This function is not always usable (for example, it
+   cannot give complete results for multiplication or division) but probably
+   ought to be relied on more widely throughout the expander.  */
+optab
+optab_for_tree_code (enum tree_code code, const_tree type,
+		     enum optab_subtype subtype)
+{
+  bool trapv;
+  switch (code)
+    {
+    case BIT_AND_EXPR:
+      return and_optab;
+
+    case BIT_IOR_EXPR:
+      return ior_optab;
+
+    case BIT_NOT_EXPR:
+      return one_cmpl_optab;
+
+    case BIT_XOR_EXPR:
+      return xor_optab;
+
+    case MULT_HIGHPART_EXPR:
+      return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
+
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+      return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
+
+    case RDIV_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case EXACT_DIV_EXPR:
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
+      return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
+
+    case LSHIFT_EXPR:
+      if (TREE_CODE (type) == VECTOR_TYPE)
+	{
+	  if (subtype == optab_vector)
+	    return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
+
+	  gcc_assert (subtype == optab_scalar);
+	}
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
+      return ashl_optab;
+
+    case RSHIFT_EXPR:
+      if (TREE_CODE (type) == VECTOR_TYPE)
+	{
+	  if (subtype == optab_vector)
+	    return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
+
+	  gcc_assert (subtype == optab_scalar);
+	}
+      return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
+
+    case LROTATE_EXPR:
+      if (TREE_CODE (type) == VECTOR_TYPE)
+	{
+	  if (subtype == optab_vector)
+	    return vrotl_optab;
+
+	  gcc_assert (subtype == optab_scalar);
+	}
+      return rotl_optab;
+
+    case RROTATE_EXPR:
+      if (TREE_CODE (type) == VECTOR_TYPE)
+	{
+	  if (subtype == optab_vector)
+	    return vrotr_optab;
+
+	  gcc_assert (subtype == optab_scalar);
+	}
+      return rotr_optab;
+
+    case MAX_EXPR:
+      return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
+
+    case MIN_EXPR:
+      return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
+
+    case REALIGN_LOAD_EXPR:
+      return vec_realign_load_optab;
+
+    case WIDEN_SUM_EXPR:
+      return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
+
+    case DOT_PROD_EXPR:
+      return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
+
+    case SAD_EXPR:
+      return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
+
+    case WIDEN_MULT_PLUS_EXPR:
+      return (TYPE_UNSIGNED (type)
+	      ? (TYPE_SATURATING (type)
+		 ? usmadd_widen_optab : umadd_widen_optab)
+	      : (TYPE_SATURATING (type)
+		 ? ssmadd_widen_optab : smadd_widen_optab));
+
+    case WIDEN_MULT_MINUS_EXPR:
+      return (TYPE_UNSIGNED (type)
+	      ? (TYPE_SATURATING (type)
+		 ? usmsub_widen_optab : umsub_widen_optab)
+	      : (TYPE_SATURATING (type)
+		 ? ssmsub_widen_optab : smsub_widen_optab));
+
+    case FMA_EXPR:
+      return fma_optab;
+
+    case REDUC_MAX_EXPR:
+      return TYPE_UNSIGNED (type)
+	     ? reduc_umax_scal_optab : reduc_smax_scal_optab;
+
+    case REDUC_MIN_EXPR:
+      return TYPE_UNSIGNED (type)
+	     ? reduc_umin_scal_optab : reduc_smin_scal_optab;
+
+    case REDUC_PLUS_EXPR:
+      return reduc_plus_scal_optab;
+
+    case VEC_WIDEN_MULT_HI_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
+
+    case VEC_WIDEN_MULT_LO_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
+
+    case VEC_WIDEN_MULT_EVEN_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_umult_even_optab : vec_widen_smult_even_optab;
+
+    case VEC_WIDEN_MULT_ODD_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
+
+    case VEC_WIDEN_LSHIFT_HI_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
+
+    case VEC_WIDEN_LSHIFT_LO_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
+
+    case VEC_UNPACK_HI_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_unpacku_hi_optab : vec_unpacks_hi_optab;
+
+    case VEC_UNPACK_LO_EXPR:
+      return TYPE_UNSIGNED (type) ?
+	vec_unpacku_lo_optab : vec_unpacks_lo_optab;
+
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ?
+	vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
+
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ?
+	vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
+
+    case VEC_PACK_TRUNC_EXPR:
+      return vec_pack_trunc_optab;
+
+    case VEC_PACK_SAT_EXPR:
+      return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
+
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      /* The signedness is determined from output operand.  */
+      return TYPE_UNSIGNED (type) ?
+	vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
+
+    default:
+      break;
+    }
+
+  trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
+  switch (code)
+    {
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
+      return trapv ? addv_optab : add_optab;
+
+    case MINUS_EXPR:
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
+      return trapv ? subv_optab : sub_optab;
+
+    case MULT_EXPR:
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
+      return trapv ? smulv_optab : smul_optab;
+
+    case NEGATE_EXPR:
+      if (TYPE_SATURATING (type))
+	return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
+      return trapv ? negv_optab : neg_optab;
+
+    case ABS_EXPR:
+      return trapv ? absv_optab : abs_optab;
+
+    default:
+      return unknown_optab;
+    }
+}
+
+/* Given optab UNOPTAB that reduces a vector to a scalar, find instead the old
+   optab that produces a vector with the reduction result in one element,
+   for a tree with type TYPE.  */
+
+optab
+scalar_reduc_to_vector (optab unoptab, const_tree type)
+{
+  switch (unoptab)
+    {
+    case reduc_plus_scal_optab:
+      return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
+
+    case reduc_smin_scal_optab: return reduc_smin_optab;
+    case reduc_umin_scal_optab: return reduc_umin_optab;
+    case reduc_smax_scal_optab: return reduc_smax_optab;
+    case reduc_umax_scal_optab: return reduc_umax_optab;
+    default: return unknown_optab;
+    }
+}
+
+/* Function supportable_convert_operation
+
+   Check whether an operation represented by the code CODE is a
+   convert operation that is supported by the target platform in
+   vector form (i.e., when operating on arguments of type VECTYPE_IN
+   producing a result of type VECTYPE_OUT).
+
+   Convert operations we currently support directly are FIX_TRUNC and FLOAT.
+   This function checks if these operations are supported
+   by the target platform either directly (via vector tree-codes), or via
+   target builtins.
+
+   Output:
+   - CODE1 is code of vector operation to be used when
+   vectorizing the operation, if available.
+   - DECL is decl of target builtin functions to be used
+   when vectorizing the operation, if available.  In this case,
+   CODE1 is CALL_EXPR.  */
+
+bool
+supportable_convert_operation (enum tree_code code,
+			       tree vectype_out, tree vectype_in,
+			       tree *decl, enum tree_code *code1)
+{
+  machine_mode m1,m2;
+  bool truncp;
+
+  m1 = TYPE_MODE (vectype_out);
+  m2 = TYPE_MODE (vectype_in);
+
+  /* First check if we can done conversion directly.  */
+  if ((code == FIX_TRUNC_EXPR
+       && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
+	  != CODE_FOR_nothing)
+      || (code == FLOAT_EXPR
+	  && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
+	     != CODE_FOR_nothing))
+    {
+      *code1 = code;
+      return true;
+    }
+
+  /* Now check for builtin.  */
+  if (targetm.vectorize.builtin_conversion
+      && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
+    {
+      *code1 = CALL_EXPR;
+      *decl = targetm.vectorize.builtin_conversion (code, vectype_out,
+						    vectype_in);
+      return true;
+    }
+  return false;
+}
+
+/* Return TRUE iff, appropriate vector insns are available
+   for vector cond expr with vector type VALUE_TYPE and a comparison
+   with operand vector types in CMP_OP_TYPE.  */
+
+bool
+expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
+{
+  machine_mode value_mode = TYPE_MODE (value_type);
+  machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
+  if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
+      || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
+      || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
+			  TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
+    return false;
+  return true;
+}
+
+/* Use the current target and options to initialize
+   TREE_OPTIMIZATION_OPTABS (OPTNODE).  */
+
+void
+init_tree_optimization_optabs (tree optnode)
+{
+  /* Quick exit if we have already computed optabs for this target.  */
+  if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
+    return;
+
+  /* Forget any previous information and set up for the current target.  */
+  TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
+  struct target_optabs *tmp_optabs = (struct target_optabs *)
+    TREE_OPTIMIZATION_OPTABS (optnode);
+  if (tmp_optabs)
+    memset (tmp_optabs, 0, sizeof (struct target_optabs));
+  else
+    tmp_optabs = ggc_alloc<target_optabs> ();
+
+  /* Generate a new set of optabs into tmp_optabs.  */
+  init_all_optabs (tmp_optabs);
+
+  /* If the optabs changed, record it.  */
+  if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
+    TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
+  else
+    {
+      TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
+      ggc_free (tmp_optabs);
+    }
+}
diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h
new file mode 100644
index 0000000..bf6c9e3
--- /dev/null
+++ b/gcc/optabs-tree.h
@@ -0,0 +1,45 @@
+/* Tree-based target query functions relating to optabs
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OPTABS_TREE_H
+#define GCC_OPTABS_TREE_H
+
+#include "optabs-query.h"
+
+/* An extra flag to control optab_for_tree_code's behavior.  This is needed to
+   distinguish between machines with a vector shift that takes a scalar for the
+   shift amount vs. machines that take a vector for the shift amount.  */
+enum optab_subtype
+{
+  optab_default,
+  optab_scalar,
+  optab_vector
+};
+
+/* Return the optab used for computing the given operation on the type given by
+   the second argument.  The third argument distinguishes between the types of
+   vector shifts and rotates.  */
+optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
+optab scalar_reduc_to_vector (optab, const_tree);
+bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
+				    enum tree_code *);
+bool expand_vec_cond_expr_p (tree, tree);
+void init_tree_optimization_optabs (tree);
+
+#endif
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 79c6f06..b7857a5 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -33,8 +33,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "tree-hasher.h"
 #include "stor-layout.h"
-#include "stringpool.h"
-#include "varasm.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "except.h"
@@ -47,22 +45,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "insn-codes.h"
 #include "optabs.h"
+#include "optabs-tree.h"
 #include "libfuncs.h"
 #include "recog.h"
 #include "reload.h"
 #include "target.h"
 
-struct target_optabs default_target_optabs;
-struct target_libfuncs default_target_libfuncs;
-struct target_optabs *this_fn_optabs = &default_target_optabs;
-#if SWITCHABLE_TARGET
-struct target_optabs *this_target_optabs = &default_target_optabs;
-struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
-#endif
-
-#define libfunc_hash \
-  (this_target_libfuncs->x_libfunc_hash)
-
 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
 				   machine_mode *);
 static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int);
@@ -70,101 +58,6 @@ static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool);
 
 /* Debug facility for use in GDB.  */
 void debug_optab_libfuncs (void);
-
-/* Prefixes for the current version of decimal floating point (BID vs. DPD) */
-#if ENABLE_DECIMAL_BID_FORMAT
-#define DECIMAL_PREFIX "bid_"
-#else
-#define DECIMAL_PREFIX "dpd_"
-#endif
-
-/* Used for libfunc_hash.  */
-
-hashval_t
-libfunc_hasher::hash (libfunc_entry *e)
-{
-  return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
-}
-
-/* Used for libfunc_hash.  */
-
-bool
-libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
-{
-  return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
-}
-
-/* Return libfunc corresponding operation defined by OPTAB converting
-   from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
-   if no libfunc is available.  */
-rtx
-convert_optab_libfunc (convert_optab optab, machine_mode mode1,
-		       machine_mode mode2)
-{
-  struct libfunc_entry e;
-  struct libfunc_entry **slot;
-
-  /* ??? 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 = libfunc_hash->find_slot (&e, NO_INSERT);
-  if (!slot)
-    {
-      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 = libfunc_hash->find_slot (&e, NO_INSERT);
-      if (!slot)
-	return NULL;
-    }
-  return (*slot)->libfunc;
-}
-
-/* Return libfunc corresponding operation defined by OPTAB in MODE.
-   Trigger lazy initialization if needed, return NULL if no libfunc is
-   available.  */
-rtx
-optab_libfunc (optab optab, machine_mode mode)
-{
-  struct libfunc_entry e;
-  struct libfunc_entry **slot;
-
-  /* ??? 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 = libfunc_hash->find_slot (&e, NO_INSERT);
-  if (!slot)
-    {
-      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 = libfunc_hash->find_slot (&e, NO_INSERT);
-      if (!slot)
-	return NULL;
-    }
-  return (*slot)->libfunc;
-}
-
 
 /* Add a REG_EQUAL note to the last insn in INSNS.  TARGET is being set to
    the result of operation CODE applied to OP0 (and OP1 if it is a binary
@@ -298,56 +191,6 @@ widened_mode (machine_mode to_mode, rtx op0, rtx op1)
   return result;
 }
 
-/* Like optab_handler, but for widening_operations that have a
-   TO_MODE and a FROM_MODE.  */
-
-enum insn_code
-widening_optab_handler (optab op, machine_mode to_mode,
-			machine_mode from_mode)
-{
-  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);
-}
-
-/* Find a widening optab even if it doesn't widen as much as we want.
-   E.g. if from_mode is HImode, and to_mode is DImode, and there is no
-   direct HI->SI insn, then return SI->DI, if that exists.
-   If PERMIT_NON_WIDENING is non-zero then this can be used with
-   non-widening optabs also.  */
-
-enum insn_code
-find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
-				      machine_mode from_mode,
-				      int permit_non_widening,
-				      machine_mode *found_mode)
-{
-  for (; (permit_non_widening || from_mode != to_mode)
-	 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
-	 && from_mode != VOIDmode;
-       from_mode = GET_MODE_WIDER_MODE (from_mode))
-    {
-      enum insn_code handler = widening_optab_handler (op, to_mode,
-						       from_mode);
-
-      if (handler != CODE_FOR_nothing)
-	{
-	  if (found_mode)
-	    *found_mode = from_mode;
-	  return handler;
-	}
-    }
-
-  return CODE_FOR_nothing;
-}
-
 /* Widen OP to MODE and return the rtx for the widened operand.  UNSIGNEDP
    says whether OP is signed or unsigned.  NO_EXTEND is nonzero if we need
    not actually do a sign-extend or zero-extend, but can leave the
@@ -386,245 +229,6 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
   return result;
 }
 
-/* Return the optab used for computing the operation given by the tree code,
-   CODE and the tree EXP.  This function is not always usable (for example, it
-   cannot give complete results for multiplication or division) but probably
-   ought to be relied on more widely throughout the expander.  */
-optab
-optab_for_tree_code (enum tree_code code, const_tree type,
-		     enum optab_subtype subtype)
-{
-  bool trapv;
-  switch (code)
-    {
-    case BIT_AND_EXPR:
-      return and_optab;
-
-    case BIT_IOR_EXPR:
-      return ior_optab;
-
-    case BIT_NOT_EXPR:
-      return one_cmpl_optab;
-
-    case BIT_XOR_EXPR:
-      return xor_optab;
-
-    case MULT_HIGHPART_EXPR:
-      return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
-
-    case TRUNC_MOD_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-      return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
-
-    case RDIV_EXPR:
-    case TRUNC_DIV_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case EXACT_DIV_EXPR:
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
-      return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
-
-    case LSHIFT_EXPR:
-      if (TREE_CODE (type) == VECTOR_TYPE)
-	{
-	  if (subtype == optab_vector)
-	    return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
-
-	  gcc_assert (subtype == optab_scalar);
-	}
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
-      return ashl_optab;
-
-    case RSHIFT_EXPR:
-      if (TREE_CODE (type) == VECTOR_TYPE)
-	{
-	  if (subtype == optab_vector)
-	    return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
-
-	  gcc_assert (subtype == optab_scalar);
-	}
-      return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
-
-    case LROTATE_EXPR:
-      if (TREE_CODE (type) == VECTOR_TYPE)
-	{
-	  if (subtype == optab_vector)
-	    return vrotl_optab;
-
-	  gcc_assert (subtype == optab_scalar);
-	}
-      return rotl_optab;
-
-    case RROTATE_EXPR:
-      if (TREE_CODE (type) == VECTOR_TYPE)
-	{
-	  if (subtype == optab_vector)
-	    return vrotr_optab;
-
-	  gcc_assert (subtype == optab_scalar);
-	}
-      return rotr_optab;
-
-    case MAX_EXPR:
-      return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
-
-    case MIN_EXPR:
-      return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
-
-    case REALIGN_LOAD_EXPR:
-      return vec_realign_load_optab;
-
-    case WIDEN_SUM_EXPR:
-      return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
-
-    case DOT_PROD_EXPR:
-      return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
-
-    case SAD_EXPR:
-      return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
-
-    case WIDEN_MULT_PLUS_EXPR:
-      return (TYPE_UNSIGNED (type)
-	      ? (TYPE_SATURATING (type)
-		 ? usmadd_widen_optab : umadd_widen_optab)
-	      : (TYPE_SATURATING (type)
-		 ? ssmadd_widen_optab : smadd_widen_optab));
-
-    case WIDEN_MULT_MINUS_EXPR:
-      return (TYPE_UNSIGNED (type)
-	      ? (TYPE_SATURATING (type)
-		 ? usmsub_widen_optab : umsub_widen_optab)
-	      : (TYPE_SATURATING (type)
-		 ? ssmsub_widen_optab : smsub_widen_optab));
-
-    case FMA_EXPR:
-      return fma_optab;
-
-    case REDUC_MAX_EXPR:
-      return TYPE_UNSIGNED (type)
-	     ? reduc_umax_scal_optab : reduc_smax_scal_optab;
-
-    case REDUC_MIN_EXPR:
-      return TYPE_UNSIGNED (type)
-	     ? reduc_umin_scal_optab : reduc_smin_scal_optab;
-
-    case REDUC_PLUS_EXPR:
-      return reduc_plus_scal_optab;
-
-    case VEC_WIDEN_MULT_HI_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
-
-    case VEC_WIDEN_MULT_LO_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
-
-    case VEC_WIDEN_MULT_EVEN_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_widen_umult_even_optab : vec_widen_smult_even_optab;
-
-    case VEC_WIDEN_MULT_ODD_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
-
-    case VEC_WIDEN_LSHIFT_HI_EXPR:
-      return TYPE_UNSIGNED (type) ?
-        vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
-
-    case VEC_WIDEN_LSHIFT_LO_EXPR:
-      return TYPE_UNSIGNED (type) ?
-        vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
-
-    case VEC_UNPACK_HI_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_unpacku_hi_optab : vec_unpacks_hi_optab;
-
-    case VEC_UNPACK_LO_EXPR:
-      return TYPE_UNSIGNED (type) ?
-	vec_unpacku_lo_optab : vec_unpacks_lo_optab;
-
-    case VEC_UNPACK_FLOAT_HI_EXPR:
-      /* The signedness is determined from input operand.  */
-      return TYPE_UNSIGNED (type) ?
-	vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
-
-    case VEC_UNPACK_FLOAT_LO_EXPR:
-      /* The signedness is determined from input operand.  */
-      return TYPE_UNSIGNED (type) ?
-	vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
-
-    case VEC_PACK_TRUNC_EXPR:
-      return vec_pack_trunc_optab;
-
-    case VEC_PACK_SAT_EXPR:
-      return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
-
-    case VEC_PACK_FIX_TRUNC_EXPR:
-      /* The signedness is determined from output operand.  */
-      return TYPE_UNSIGNED (type) ?
-	vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
-
-    default:
-      break;
-    }
-
-  trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
-  switch (code)
-    {
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
-      return trapv ? addv_optab : add_optab;
-
-    case MINUS_EXPR:
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
-      return trapv ? subv_optab : sub_optab;
-
-    case MULT_EXPR:
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
-      return trapv ? smulv_optab : smul_optab;
-
-    case NEGATE_EXPR:
-      if (TYPE_SATURATING (type))
-	return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
-      return trapv ? negv_optab : neg_optab;
-
-    case ABS_EXPR:
-      return trapv ? absv_optab : abs_optab;
-
-    default:
-      return unknown_optab;
-    }
-}
-
-/* Given optab UNOPTAB that reduces a vector to a scalar, find instead the old
-   optab that produces a vector with the reduction result in one element,
-   for a tree with type TYPE.  */
-
-optab
-scalar_reduc_to_vector (optab unoptab, const_tree type)
-{
-  switch (unoptab)
-    {
-    case reduc_plus_scal_optab:
-      return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
-
-    case reduc_smin_scal_optab: return reduc_smin_optab;
-    case reduc_umin_scal_optab: return reduc_umin_optab;
-    case reduc_smax_scal_optab: return reduc_smax_optab;
-    case reduc_umax_scal_optab: return reduc_umax_optab;
-    default: return unknown_optab;
-    }
-}
-
 /* Expand vector widening operations.
 
    There are two different classes of operations handled here:
@@ -4606,23 +4210,6 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
   return NULL_RTX;
 }
 
-/* Return nonzero if a conditional move of mode MODE is supported.
-
-   This function is for combine so it can tell whether an insn that looks
-   like a conditional move is actually supported by the hardware.  If we
-   guess wrong we lose a bit on optimization, but that's it.  */
-/* ??? sparc64 supports conditionally moving integers values based on fp
-   comparisons, and vice versa.  How do we handle them?  */
-
-int
-can_conditionally_move_p (machine_mode mode)
-{
-  if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
-    return 1;
-
-  return 0;
-}
-
 /* Emit a conditional addition instruction if the machine supports one for that
    condition and machine mode.
 
@@ -4853,22 +4440,6 @@ have_sub2_insn (rtx x, rtx y)
   return 1;
 }
 
-/* Return the insn code used to extend FROM_MODE to TO_MODE.
-   UNSIGNEDP specifies zero-extension instead of sign-extension.  If
-   no such operation exists, CODE_FOR_nothing will be returned.  */
-
-enum insn_code
-can_extend_p (machine_mode to_mode, machine_mode from_mode,
-	      int unsignedp)
-{
-  convert_optab tab;
-  if (unsignedp < 0 && targetm.have_ptr_extend ())
-    return targetm.code_for_ptr_extend;
-
-  tab = unsignedp ? zext_optab : sext_optab;
-  return convert_optab_handler (tab, to_mode, from_mode);
-}
-
 /* Generate the body of an insn to extend Y (with mode MFROM)
    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
 
@@ -4880,110 +4451,6 @@ gen_extend_insn (rtx x, rtx y, machine_mode mto,
   return GEN_FCN (icode) (x, y);
 }
 
-/* can_fix_p and can_float_p say whether the target machine
-   can directly convert a given fixed point type to
-   a given floating point type, or vice versa.
-   The returned value is the CODE_FOR_... value to use,
-   or CODE_FOR_nothing if these modes cannot be directly converted.
-
-   *TRUNCP_PTR is set to 1 if it is necessary to output
-   an explicit FTRUNC insn before the fix insn; otherwise 0.  */
-
-static enum insn_code
-can_fix_p (machine_mode fixmode, machine_mode fltmode,
-	   int unsignedp, int *truncp_ptr)
-{
-  convert_optab tab;
-  enum insn_code icode;
-
-  tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
-  icode = convert_optab_handler (tab, fixmode, fltmode);
-  if (icode != CODE_FOR_nothing)
-    {
-      *truncp_ptr = 0;
-      return icode;
-    }
-
-  /* FIXME: This requires a port to define both FIX and FTRUNC pattern
-     for this to work. We need to rework the fix* and ftrunc* patterns
-     and documentation.  */
-  tab = unsignedp ? ufix_optab : sfix_optab;
-  icode = convert_optab_handler (tab, fixmode, fltmode);
-  if (icode != CODE_FOR_nothing
-      && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
-    {
-      *truncp_ptr = 1;
-      return icode;
-    }
-
-  *truncp_ptr = 0;
-  return CODE_FOR_nothing;
-}
-
-enum insn_code
-can_float_p (machine_mode fltmode, machine_mode fixmode,
-	     int unsignedp)
-{
-  convert_optab tab;
-
-  tab = unsignedp ? ufloat_optab : sfloat_optab;
-  return convert_optab_handler (tab, fltmode, fixmode);
-}
-
-/* Function supportable_convert_operation
-
-   Check whether an operation represented by the code CODE is a
-   convert operation that is supported by the target platform in
-   vector form (i.e., when operating on arguments of type VECTYPE_IN
-   producing a result of type VECTYPE_OUT).
-   
-   Convert operations we currently support directly are FIX_TRUNC and FLOAT.
-   This function checks if these operations are supported
-   by the target platform either directly (via vector tree-codes), or via
-   target builtins.
-   
-   Output:
-   - CODE1 is code of vector operation to be used when
-   vectorizing the operation, if available.
-   - DECL is decl of target builtin functions to be used
-   when vectorizing the operation, if available.  In this case,
-   CODE1 is CALL_EXPR.  */
-
-bool
-supportable_convert_operation (enum tree_code code,
-                                    tree vectype_out, tree vectype_in,
-                                    tree *decl, enum tree_code *code1)
-{
-  machine_mode m1,m2;
-  int truncp;
-
-  m1 = TYPE_MODE (vectype_out);
-  m2 = TYPE_MODE (vectype_in);
-
-  /* First check if we can done conversion directly.  */
-  if ((code == FIX_TRUNC_EXPR 
-       && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp) 
-          != CODE_FOR_nothing)
-      || (code == FLOAT_EXPR
-          && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
-	     != CODE_FOR_nothing))
-    {
-      *code1 = code;
-      return true;
-    }
-
-  /* Now check for builtin.  */
-  if (targetm.vectorize.builtin_conversion
-      && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
-    {
-      *code1 = CALL_EXPR;
-      *decl = targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in);
-      return true;
-    }
-  return false;
-}
-
-
 /* Generate code to convert FROM to floating point
    and store in TO.  FROM must be fixed point and not VOIDmode.
    UNSIGNEDP nonzero means regard FROM as unsigned.
@@ -5197,7 +4664,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
   enum insn_code icode;
   rtx target = to;
   machine_mode fmode, imode;
-  int must_trunc = 0;
+  bool must_trunc = false;
 
   /* We first try to find a pair of modes, one real and one integer, at
      least as wide as FROM and TO, respectively, in which we can open-code
@@ -5478,957 +4945,91 @@ have_insn_for (enum rtx_code code, machine_mode mode)
 	      != CODE_FOR_nothing));
 }
 
-/* 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
-   a mode name (downshifted to lowercase) followed by a single character
-   representing the number of operands for the given operation (which is
-   usually one of the characters '2', '3', or '4').
-
-   OPTABLE is the table in which libfunc fields are to be initialized.
-   OPNAME is the generic (string) name of the operation.
-   SUFFIX is the character which specifies the number of operands for
-     the given generic operation.
-   MODE is the mode to generate for.
-*/
+/* Print information about the current contents of the optabs on
+   STDERR.  */
 
-static void
-gen_libfunc (optab optable, const char *opname, int suffix,
-	     machine_mode mode)
+DEBUG_FUNCTION void
+debug_optab_libfuncs (void)
 {
-  unsigned opname_len = strlen (opname);
-  const char *mname = GET_MODE_NAME (mode);
-  unsigned mname_len = strlen (mname);
-  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
-  int len = prefix_len + opname_len + mname_len + 1 + 1;
-  char *libfunc_name = XALLOCAVEC (char, len);
-  char *p;
-  const char *q;
-
-  p = libfunc_name;
-  *p++ = '_';
-  *p++ = '_';
-  if (targetm.libfunc_gnu_prefix)
-    {
-      *p++ = 'g';
-      *p++ = 'n';
-      *p++ = 'u';
-      *p++ = '_';
-    }
-  for (q = opname; *q; )
-    *p++ = *q++;
-  for (q = mname; *q; q++)
-    *p++ = TOLOWER (*q);
-  *p++ = suffix;
-  *p = '\0';
-
-  set_optab_libfunc (optable, mode,
-		     ggc_alloc_string (libfunc_name, p - libfunc_name));
+  int i, j, k;
+
+  /* Dump the arithmetic optabs.  */
+  for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
+    for (j = 0; j < NUM_MACHINE_MODES; ++j)
+      {
+	rtx l = optab_libfunc ((optab) i, (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 ((optab) i)),
+		     GET_MODE_NAME (j),
+		     XSTR (l, 0));
+	  }
+      }
+
+  /* Dump the conversion optabs.  */
+  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)
+	{
+	  rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
+					 (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 ((optab) i)),
+		       GET_MODE_NAME (j),
+		       GET_MODE_NAME (k),
+		       XSTR (l, 0));
+	    }
+	}
 }
 
-/* Like gen_libfunc, but verify that integer operation is involved.  */
+/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
+   CODE.  Return 0 on failure.  */
 
-void
-gen_int_libfunc (optab optable, const char *opname, char suffix,
-		 machine_mode mode)
+rtx_insn *
+gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
 {
-  int maxsize = 2 * BITS_PER_WORD;
-  int minsize = BITS_PER_WORD;
+  machine_mode mode = GET_MODE (op1);
+  enum insn_code icode;
+  rtx_insn *insn;
+  rtx trap_rtx;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
-    return;
-  if (maxsize < LONG_LONG_TYPE_SIZE)
-    maxsize = LONG_LONG_TYPE_SIZE;
-  if (minsize > INT_TYPE_SIZE
-      && (trapv_binoptab_p (optable)
-	  || trapv_unoptab_p (optable)))
-    minsize = INT_TYPE_SIZE;
-  if (GET_MODE_BITSIZE (mode) < minsize
-      || GET_MODE_BITSIZE (mode) > maxsize)
-    return;
-  gen_libfunc (optable, opname, suffix, mode);
-}
+  if (mode == VOIDmode)
+    return 0;
+
+  icode = optab_handler (ctrap_optab, mode);
+  if (icode == CODE_FOR_nothing)
+    return 0;
 
-/* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
+  /* Some targets only accept a zero trap code.  */
+  if (!insn_operand_matches (icode, 3, tcode))
+    return 0;
 
-void
-gen_fp_libfunc (optab optable, const char *opname, char suffix,
-		machine_mode mode)
-{
-  char *dec_opname;
+  do_pending_stack_adjust ();
+  start_sequence ();
+  prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
+		    &trap_rtx, &mode);
+  if (!trap_rtx)
+    insn = NULL;
+  else
+    insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
+			    tcode);
 
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
-    gen_libfunc (optable, opname, suffix, mode);
-  if (DECIMAL_FLOAT_MODE_P (mode))
+  /* If that failed, then give up.  */
+  if (insn == 0)
     {
-      dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
-      /* For BID support, change the name to have either a bid_ or dpd_ prefix
-	 depending on the low level floating format used.  */
-      memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
-      strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
-      gen_libfunc (optable, dec_opname, suffix, mode);
+      end_sequence ();
+      return 0;
     }
-}
-
-/* Like gen_libfunc, but verify that fixed-point operation is involved.  */
-
-void
-gen_fixed_libfunc (optab optable, const char *opname, char suffix,
-		   machine_mode mode)
-{
-  if (!ALL_FIXED_POINT_MODE_P (mode))
-    return;
-  gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that signed fixed-point operation is
-   involved.  */
-
-void
-gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
-			  machine_mode mode)
-{
-  if (!SIGNED_FIXED_POINT_MODE_P (mode))
-    return;
-  gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that unsigned fixed-point operation is
-   involved.  */
-
-void
-gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
-			    machine_mode mode)
-{
-  if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
-    return;
-  gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT operation is involved.  */
-
-void
-gen_int_fp_libfunc (optab optable, const char *name, char suffix,
-		    machine_mode mode)
-{
-  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
-    gen_fp_libfunc (optable, name, suffix, mode);
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT operation is involved
-   and add 'v' suffix for integer operation.  */
-
-void
-gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
-		     machine_mode mode)
-{
-  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
-    gen_fp_libfunc (optable, name, suffix, mode);
-  if (GET_MODE_CLASS (mode) == MODE_INT)
-    {
-      int len = strlen (name);
-      char *v_name = XALLOCAVEC (char, len + 2);
-      strcpy (v_name, name);
-      v_name[len] = 'v';
-      v_name[len + 1] = 0;
-      gen_int_libfunc (optable, v_name, suffix, mode);
-    }
-}
-
-/* Like gen_libfunc, but verify that FP or INT or FIXED operation is
-   involved.  */
-
-void
-gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
-			  machine_mode mode)
-{
-  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
-    gen_fp_libfunc (optable, name, suffix, mode);
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-  if (ALL_FIXED_POINT_MODE_P (mode))
-    gen_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
-   involved.  */
-
-void
-gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
-				 machine_mode mode)
-{
-  if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
-    gen_fp_libfunc (optable, name, suffix, mode);
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-  if (SIGNED_FIXED_POINT_MODE_P (mode))
-    gen_signed_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or FIXED operation is
-   involved.  */
-
-void
-gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
-		       machine_mode mode)
-{
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-  if (ALL_FIXED_POINT_MODE_P (mode))
-    gen_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or signed FIXED operation is
-   involved.  */
-
-void
-gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
-			      machine_mode mode)
-{
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-  if (SIGNED_FIXED_POINT_MODE_P (mode))
-    gen_signed_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
-   involved.  */
-
-void
-gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
-				machine_mode mode)
-{
-  if (INTEGRAL_MODE_P (mode))
-    gen_int_libfunc (optable, name, suffix, mode);
-  if (UNSIGNED_FIXED_POINT_MODE_P (mode))
-    gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Initialize the libfunc fields of an entire group of entries of an
-   inter-mode-class conversion optab.  The string formation rules are
-   similar to the ones for init_libfuncs, above, but instead of having
-   a mode name and an operand count these functions have two mode names
-   and no operand count.  */
-
-void
-gen_interclass_conv_libfunc (convert_optab tab,
-			     const char *opname,
-			     machine_mode tmode,
-			     machine_mode fmode)
-{
-  size_t opname_len = strlen (opname);
-  size_t mname_len = 0;
-
-  const char *fname, *tname;
-  const char *q;
-  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
-  char *libfunc_name, *suffix;
-  char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
-  char *p;
-
-  /* If this is a decimal conversion, add the current BID vs. DPD prefix that
-     depends on which underlying decimal floating point format is used.  */
-  const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
-
-  mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
-
-  nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
-  nondec_name[0] = '_';
-  nondec_name[1] = '_';
-  if (targetm.libfunc_gnu_prefix)
-    {
-      nondec_name[2] = 'g';
-      nondec_name[3] = 'n';
-      nondec_name[4] = 'u';
-      nondec_name[5] = '_';
-    }
-
-  memcpy (&nondec_name[prefix_len], opname, opname_len);
-  nondec_suffix = nondec_name + opname_len + prefix_len;
-
-  dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
-  dec_name[0] = '_';
-  dec_name[1] = '_';
-  memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
-  memcpy (&dec_name[2+dec_len], opname, opname_len);
-  dec_suffix = dec_name + dec_len + opname_len + 2;
-
-  fname = GET_MODE_NAME (fmode);
-  tname = GET_MODE_NAME (tmode);
-
-  if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
-    {
-      libfunc_name = dec_name;
-      suffix = dec_suffix;
-    }
-  else
-    {
-      libfunc_name = nondec_name;
-      suffix = nondec_suffix;
-    }
-
-  p = suffix;
-  for (q = fname; *q; p++, q++)
-    *p = TOLOWER (*q);
-  for (q = tname; *q; p++, q++)
-    *p = TOLOWER (*q);
-
-  *p = '\0';
-
-  set_conv_libfunc (tab, tmode, fmode,
-		    ggc_alloc_string (libfunc_name, p - libfunc_name));
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
-   int->fp conversion.  */
-
-void
-gen_int_to_fp_conv_libfunc (convert_optab tab,
-			    const char *opname,
-			    machine_mode tmode,
-			    machine_mode fmode)
-{
-  if (GET_MODE_CLASS (fmode) != MODE_INT)
-    return;
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
-    return;
-  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* ufloat_optab is special by using floatun for FP and floatuns decimal fp
-   naming scheme.  */
-
-void
-gen_ufloat_conv_libfunc (convert_optab tab,
-			 const char *opname ATTRIBUTE_UNUSED,
-			 machine_mode tmode,
-			 machine_mode fmode)
-{
-  if (DECIMAL_FLOAT_MODE_P (tmode))
-    gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
-  else
-    gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
-   fp->int conversion.  */
-
-void
-gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
-			               const char *opname,
-			               machine_mode tmode,
-			               machine_mode fmode)
-{
-  if (GET_MODE_CLASS (fmode) != MODE_INT)
-    return;
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
-    return;
-  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
-   fp->int conversion with no decimal floating point involved.  */
-
-void
-gen_fp_to_int_conv_libfunc (convert_optab tab,
-			    const char *opname,
-			    machine_mode tmode,
-			    machine_mode fmode)
-{
-  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
-    return;
-  if (GET_MODE_CLASS (tmode) != MODE_INT)
-    return;
-  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
-   The string formation rules are
-   similar to the ones for init_libfunc, above.  */
-
-void
-gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
-			     machine_mode tmode, machine_mode fmode)
-{
-  size_t opname_len = strlen (opname);
-  size_t mname_len = 0;
-
-  const char *fname, *tname;
-  const char *q;
-  int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
-  char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
-  char *libfunc_name, *suffix;
-  char *p;
-
-  /* If this is a decimal conversion, add the current BID vs. DPD prefix that
-     depends on which underlying decimal floating point format is used.  */
-  const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
-
-  mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
-
-  nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
-  nondec_name[0] = '_';
-  nondec_name[1] = '_';
-  if (targetm.libfunc_gnu_prefix)
-    {
-      nondec_name[2] = 'g';
-      nondec_name[3] = 'n';
-      nondec_name[4] = 'u';
-      nondec_name[5] = '_';
-    }
-  memcpy (&nondec_name[prefix_len], opname, opname_len);
-  nondec_suffix = nondec_name + opname_len + prefix_len;
-
-  dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
-  dec_name[0] = '_';
-  dec_name[1] = '_';
-  memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
-  memcpy (&dec_name[2 + dec_len], opname, opname_len);
-  dec_suffix = dec_name + dec_len + opname_len + 2;
-
-  fname = GET_MODE_NAME (fmode);
-  tname = GET_MODE_NAME (tmode);
-
-  if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
-    {
-      libfunc_name = dec_name;
-      suffix = dec_suffix;
-    }
-  else
-    {
-      libfunc_name = nondec_name;
-      suffix = nondec_suffix;
-    }
-
-  p = suffix;
-  for (q = fname; *q; p++, q++)
-    *p = TOLOWER (*q);
-  for (q = tname; *q; p++, q++)
-    *p = TOLOWER (*q);
-
-  *p++ = '2';
-  *p = '\0';
-
-  set_conv_libfunc (tab, tmode, fmode,
-		    ggc_alloc_string (libfunc_name, p - libfunc_name));
-}
-
-/* Pick proper libcall for trunc_optab.  We need to chose if we do
-   truncation or extension and interclass or intraclass.  */
-
-void
-gen_trunc_conv_libfunc (convert_optab tab,
-			 const char *opname,
-			 machine_mode tmode,
-			 machine_mode fmode)
-{
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
-    return;
-  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
-    return;
-  if (tmode == fmode)
-    return;
-
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
-      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
-     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-
-  if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
-    return;
-
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
-       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
-      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
-    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for extend_optab.  We need to chose if we do
-   truncation or extension and interclass or intraclass.  */
-
-void
-gen_extend_conv_libfunc (convert_optab tab,
-			 const char *opname ATTRIBUTE_UNUSED,
-			 machine_mode tmode,
-			 machine_mode fmode)
-{
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
-    return;
-  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
-    return;
-  if (tmode == fmode)
-    return;
-
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
-      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
-     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-
-  if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
-    return;
-
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
-       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
-      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
-    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for fract_optab.  We need to chose if we do
-   interclass or intraclass.  */
-
-void
-gen_fract_conv_libfunc (convert_optab tab,
-			const char *opname,
-			machine_mode tmode,
-			machine_mode fmode)
-{
-  if (tmode == fmode)
-    return;
-  if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
-    return;
-
-  if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
-    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-  else
-    gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for fractuns_optab.  */
-
-void
-gen_fractuns_conv_libfunc (convert_optab tab,
-			   const char *opname,
-			   machine_mode tmode,
-			   machine_mode fmode)
-{
-  if (tmode == fmode)
-    return;
-  /* One mode must be a fixed-point mode, and the other must be an integer
-     mode. */
-  if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
-	|| (ALL_FIXED_POINT_MODE_P (fmode)
-	    && GET_MODE_CLASS (tmode) == MODE_INT)))
-    return;
-
-  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for satfract_optab.  We need to chose if we do
-   interclass or intraclass.  */
-
-void
-gen_satfract_conv_libfunc (convert_optab tab,
-			   const char *opname,
-			   machine_mode tmode,
-			   machine_mode fmode)
-{
-  if (tmode == fmode)
-    return;
-  /* TMODE must be a fixed-point mode.  */
-  if (!ALL_FIXED_POINT_MODE_P (tmode))
-    return;
-
-  if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
-    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-  else
-    gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for satfractuns_optab.  */
-
-void
-gen_satfractuns_conv_libfunc (convert_optab tab,
-			      const char *opname,
-			      machine_mode tmode,
-			      machine_mode fmode)
-{
-  if (tmode == fmode)
-    return;
-  /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
-  if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
-    return;
-
-  gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Hashtable callbacks for libfunc_decls.  */
-
-struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
-{
-  static hashval_t
-  hash (tree entry)
-  {
-    return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
-  }
-
-  static bool
-  equal (tree decl, tree name)
-  {
-    return DECL_NAME (decl) == name;
-  }
-};
-
-/* A table of previously-created libfuncs, hashed by name.  */
-static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
-
-/* Build a decl for a libfunc named NAME. */
-
-tree
-build_libfunc_function (const char *name)
-{
-  tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
-			  get_identifier (name),
-                          build_function_type (integer_type_node, NULL_TREE));
-  /* ??? We don't have any type information except for this is
-     a function.  Pretend this is "int foo()".  */
-  DECL_ARTIFICIAL (decl) = 1;
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
-  gcc_assert (DECL_ASSEMBLER_NAME (decl));
-
-  /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
-     are the flags assigned by targetm.encode_section_info.  */
-  SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
-
-  return decl;
-}
-
-rtx
-init_one_libfunc (const char *name)
-{
-  tree id, decl;
-  hashval_t hash;
-
-  if (libfunc_decls == NULL)
-    libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
-
-  /* See if we have already created a libfunc decl for this function.  */
-  id = get_identifier (name);
-  hash = IDENTIFIER_HASH_VALUE (id);
-  tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
-  decl = *slot;
-  if (decl == NULL)
-    {
-      /* Create a new decl, so that it can be passed to
-	 targetm.encode_section_info.  */
-      decl = build_libfunc_function (name);
-      *slot = decl;
-    }
-  return XEXP (DECL_RTL (decl), 0);
-}
-
-/* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
-
-rtx
-set_user_assembler_libfunc (const char *name, const char *asmspec)
-{
-  tree id, decl;
-  hashval_t hash;
-
-  id = get_identifier (name);
-  hash = IDENTIFIER_HASH_VALUE (id);
-  tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
-  gcc_assert (slot);
-  decl = (tree) *slot;
-  set_user_assembler_name (decl, asmspec);
-  return XEXP (DECL_RTL (decl), 0);
-}
-
-/* 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 op, machine_mode mode, const char *name)
-{
-  rtx val;
-  struct libfunc_entry e;
-  struct libfunc_entry **slot;
-
-  e.op = op;
-  e.mode1 = mode;
-  e.mode2 = VOIDmode;
-
-  if (name)
-    val = init_one_libfunc (name);
-  else
-    val = 0;
-  slot = libfunc_hash->find_slot (&e, INSERT);
-  if (*slot == NULL)
-    *slot = ggc_alloc<libfunc_entry> ();
-  (*slot)->op = op;
-  (*slot)->mode1 = mode;
-  (*slot)->mode2 = VOIDmode;
-  (*slot)->libfunc = val;
-}
-
-/* Call this to reset the function entry for one conversion optab
-   (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
-   either 0 or a string constant.  */
-void
-set_conv_libfunc (convert_optab optab, machine_mode tmode,
-		  machine_mode fmode, const char *name)
-{
-  rtx val;
-  struct libfunc_entry e;
-  struct libfunc_entry **slot;
-
-  e.op = optab;
-  e.mode1 = tmode;
-  e.mode2 = fmode;
-
-  if (name)
-    val = init_one_libfunc (name);
-  else
-    val = 0;
-  slot = libfunc_hash->find_slot (&e, INSERT);
-  if (*slot == NULL)
-    *slot = ggc_alloc<libfunc_entry> ();
-  (*slot)->op = optab;
-  (*slot)->mode1 = tmode;
-  (*slot)->mode2 = fmode;
-  (*slot)->libfunc = val;
-}
-
-/* Call this to initialize the contents of the optabs
-   appropriately for the current target machine.  */
-
-void
-init_optabs (void)
-{
-  if (libfunc_hash)
-    libfunc_hash->empty ();
-  else
-    libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
-
-  /* Fill in the optabs with the insns we support.  */
-  init_all_optabs (this_fn_optabs);
-
-  /* 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)
-    set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
-		       "ffs");
-
-  /* Explicitly initialize the bswap libfuncs since we need them to be
-     valid for things other than word_mode.  */
-  if (targetm.libfunc_gnu_prefix)
-    {
-      set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
-      set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
-    }
-  else
-    {
-      set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
-      set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
-    }
-
-  /* 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");
-
-  abort_libfunc = init_one_libfunc ("abort");
-  memcpy_libfunc = init_one_libfunc ("memcpy");
-  memmove_libfunc = init_one_libfunc ("memmove");
-  memcmp_libfunc = init_one_libfunc ("memcmp");
-  memset_libfunc = init_one_libfunc ("memset");
-  setbits_libfunc = init_one_libfunc ("__setbits");
-
-#ifndef DONT_USE_BUILTIN_SETJMP
-  setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
-  longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
-#else
-  setjmp_libfunc = init_one_libfunc ("setjmp");
-  longjmp_libfunc = init_one_libfunc ("longjmp");
-#endif
-  unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
-  unwind_sjlj_unregister_libfunc
-    = init_one_libfunc ("_Unwind_SjLj_Unregister");
-
-  /* For function entry/exit instrumentation.  */
-  profile_function_entry_libfunc
-    = init_one_libfunc ("__cyg_profile_func_enter");
-  profile_function_exit_libfunc
-    = init_one_libfunc ("__cyg_profile_func_exit");
-
-  gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
-
-  /* Allow the target to add more libcalls or rename some, etc.  */
-  targetm.init_libfuncs ();
-}
-
-/* Use the current target and options to initialize
-   TREE_OPTIMIZATION_OPTABS (OPTNODE).  */
-
-void
-init_tree_optimization_optabs (tree optnode)
-{
-  /* Quick exit if we have already computed optabs for this target.  */
-  if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
-    return;
-
-  /* Forget any previous information and set up for the current target.  */
-  TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
-  struct target_optabs *tmp_optabs = (struct target_optabs *)
-    TREE_OPTIMIZATION_OPTABS (optnode);
-  if (tmp_optabs)
-    memset (tmp_optabs, 0, sizeof (struct target_optabs));
-  else
-    tmp_optabs = ggc_alloc<target_optabs> ();
-
-  /* Generate a new set of optabs into tmp_optabs.  */
-  init_all_optabs (tmp_optabs);
-
-  /* If the optabs changed, record it.  */
-  if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
-    TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
-  else
-    {
-      TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
-      ggc_free (tmp_optabs);
-    }
-}
-
-/* A helper function for init_sync_libfuncs.  Using the basename BASE,
-   install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
-
-static void
-init_sync_libfuncs_1 (optab tab, const char *base, int max)
-{
-  machine_mode mode;
-  char buf[64];
-  size_t len = strlen (base);
-  int i;
-
-  gcc_assert (max <= 8);
-  gcc_assert (len + 3 < sizeof (buf));
-
-  memcpy (buf, base, len);
-  buf[len] = '_';
-  buf[len + 1] = '0';
-  buf[len + 2] = '\0';
-
-  mode = QImode;
-  for (i = 1; i <= max; i *= 2)
-    {
-      buf[len + 1] = '0' + i;
-      set_optab_libfunc (tab, mode, buf);
-      mode = GET_MODE_2XWIDER_MODE (mode);
-    }
-}
-
-void
-init_sync_libfuncs (int max)
-{
-  if (!flag_sync_libcalls)
-    return;
-
-  init_sync_libfuncs_1 (sync_compare_and_swap_optab,
-			"__sync_val_compare_and_swap", max);
-  init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
-			"__sync_lock_test_and_set", max);
-
-  init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
-  init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
-  init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
-  init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
-  init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
-  init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
-
-  init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
-  init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
-  init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
-  init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
-  init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
-  init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
-}
-
-/* Print information about the current contents of the optabs on
-   STDERR.  */
-
-DEBUG_FUNCTION void
-debug_optab_libfuncs (void)
-{
-  int i, j, k;
-
-  /* Dump the arithmetic optabs.  */
-  for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
-    for (j = 0; j < NUM_MACHINE_MODES; ++j)
-      {
-	rtx l = optab_libfunc ((optab) i, (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 ((optab) i)),
-		     GET_MODE_NAME (j),
-		     XSTR (l, 0));
-	  }
-      }
-
-  /* Dump the conversion optabs.  */
-  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)
-	{
-	  rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
-					 (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 ((optab) i)),
-		       GET_MODE_NAME (j),
-		       GET_MODE_NAME (k),
-		       XSTR (l, 0));
-	    }
-	}
-}
-
-
-/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
-   CODE.  Return 0 on failure.  */
-
-rtx_insn *
-gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
-{
-  machine_mode mode = GET_MODE (op1);
-  enum insn_code icode;
-  rtx_insn *insn;
-  rtx trap_rtx;
-
-  if (mode == VOIDmode)
-    return 0;
-
-  icode = optab_handler (ctrap_optab, mode);
-  if (icode == CODE_FOR_nothing)
-    return 0;
-
-  /* Some targets only accept a zero trap code.  */
-  if (!insn_operand_matches (icode, 3, tcode))
-    return 0;
-
-  do_pending_stack_adjust ();
-  start_sequence ();
-  prepare_cmp_insn (op1, op2, code, NULL_RTX, false, OPTAB_DIRECT,
-		    &trap_rtx, &mode);
-  if (!trap_rtx)
-    insn = NULL;
-  else
-    insn = GEN_FCN (icode) (trap_rtx, XEXP (trap_rtx, 0), XEXP (trap_rtx, 1),
-			    tcode);
-
-  /* If that failed, then give up.  */
-  if (insn == 0)
-    {
-      end_sequence ();
-      return 0;
-    }
-
-  emit_insn (insn);
-  insn = get_insns ();
-  end_sequence ();
-  return insn;
+
+  emit_insn (insn);
+  insn = get_insns ();
+  end_sequence ();
+  return insn;
 }
 
 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
@@ -6534,63 +5135,6 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
   return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
 }
 
-/* Return true if VEC_PERM_EXPR of arbitrary input vectors can be expanded using
-   SIMD extensions of the CPU.  SEL may be NULL, which stands for an unknown
-   constant.  Note that additional permutations representing whole-vector shifts
-   may also be handled via the vec_shr optab, but only where the second input
-   vector is entirely constant zeroes; this case is not dealt with here.  */
-
-bool
-can_vec_perm_p (machine_mode mode, bool variable,
-		const unsigned char *sel)
-{
-  machine_mode qimode;
-
-  /* If the target doesn't implement a vector mode for the vector type,
-     then no operations are supported.  */
-  if (!VECTOR_MODE_P (mode))
-    return false;
-
-  if (!variable)
-    {
-      if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
-	  && (sel == NULL
-	      || targetm.vectorize.vec_perm_const_ok == NULL
-	      || targetm.vectorize.vec_perm_const_ok (mode, sel)))
-	return true;
-    }
-
-  if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
-    return true;
-
-  /* We allow fallback to a QI vector mode, and adjust the mask.  */
-  if (GET_MODE_INNER (mode) == QImode)
-    return false;
-  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
-  if (!VECTOR_MODE_P (qimode))
-    return false;
-
-  /* ??? For completeness, we ought to check the QImode version of
-      vec_perm_const_optab.  But all users of this implicit lowering
-      feature implement the variable vec_perm_optab.  */
-  if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
-    return false;
-
-  /* In order to support the lowering of variable permutations,
-     we need to support shifts and adds.  */
-  if (variable)
-    {
-      if (GET_MODE_UNIT_SIZE (mode) > 2
-	  && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
-	  && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
-	return false;
-      if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
-	return false;
-    }
-
-  return true;
-}
-
 /* Checks if vec_perm mask SEL is a constant equivalent to a shift of the first
    vec_perm operand, assuming the second operand is a constant vector of zeroes.
    Return the shift distance in bits if so, or NULL_RTX if the vec_perm is not a
@@ -6800,37 +5344,6 @@ expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
   return tmp;
 }
 
-/* Return insn code for a conditional operator with a comparison in
-   mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
-
-static inline enum insn_code
-get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
-{
-  enum insn_code icode = CODE_FOR_nothing;
-  if (uns)
-    icode = convert_optab_handler (vcondu_optab, vmode, cmode);
-  else
-    icode = convert_optab_handler (vcond_optab, vmode, cmode);
-  return icode;
-}
-
-/* Return TRUE iff, appropriate vector insns are available
-   for vector cond expr with vector type VALUE_TYPE and a comparison
-   with operand vector types in CMP_OP_TYPE.  */
-
-bool
-expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
-{
-  machine_mode value_mode = TYPE_MODE (value_type);
-  machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
-  if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
-      || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
-      || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
-			  TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
-    return false;
-  return true;
-}
-
 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
    three operands.  */
 
@@ -6886,57 +5399,6 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
   return ops[0].value;
 }
 
-/* Return non-zero if a highpart multiply is supported of can be synthisized.
-   For the benefit of expand_mult_highpart, the return value is 1 for direct,
-   2 for even/odd widening, and 3 for hi/lo widening.  */
-
-int
-can_mult_highpart_p (machine_mode mode, bool uns_p)
-{
-  optab op;
-  unsigned char *sel;
-  unsigned i, nunits;
-
-  op = uns_p ? umul_highpart_optab : smul_highpart_optab;
-  if (optab_handler (op, mode) != CODE_FOR_nothing)
-    return 1;
-
-  /* If the mode is an integral vector, synth from widening operations.  */
-  if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
-    return 0;
-
-  nunits = GET_MODE_NUNITS (mode);
-  sel = XALLOCAVEC (unsigned char, nunits);
-
-  op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
-  if (optab_handler (op, mode) != CODE_FOR_nothing)
-    {
-      op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
-      if (optab_handler (op, mode) != CODE_FOR_nothing)
-	{
-	  for (i = 0; i < nunits; ++i)
-	    sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
-	  if (can_vec_perm_p (mode, false, sel))
-	    return 2;
-	}
-    }
-
-  op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
-  if (optab_handler (op, mode) != CODE_FOR_nothing)
-    {
-      op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
-      if (optab_handler (op, mode) != CODE_FOR_nothing)
-	{
-	  for (i = 0; i < nunits; ++i)
-	    sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
-	  if (can_vec_perm_p (mode, false, sel))
-	    return 3;
-	}
-    }
-
-  return 0;
-}
-
 /* Expand a highpart multiply.  */
 
 rtx
@@ -7008,89 +5470,7 @@ expand_mult_highpart (machine_mode mode, rtx op0, rtx op1,
 
   return expand_vec_perm (mode, m1, m2, perm, target);
 }
-
-/* Return true if target supports vector masked load/store for mode.  */
-bool
-can_vec_mask_load_store_p (machine_mode mode, bool is_load)
-{
-  optab op = is_load ? maskload_optab : maskstore_optab;
-  machine_mode vmode;
-  unsigned int vector_sizes;
-
-  /* If mode is vector mode, check it directly.  */
-  if (VECTOR_MODE_P (mode))
-    return optab_handler (op, mode) != CODE_FOR_nothing;
-
-  /* Otherwise, return true if there is some vector mode with
-     the mask load/store supported.  */
-
-  /* See if there is any chance the mask load or store might be
-     vectorized.  If not, punt.  */
-  vmode = targetm.vectorize.preferred_simd_mode (mode);
-  if (!VECTOR_MODE_P (vmode))
-    return false;
-
-  if (optab_handler (op, vmode) != CODE_FOR_nothing)
-    return true;
-
-  vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
-  while (vector_sizes != 0)
-    {
-      unsigned int cur = 1 << floor_log2 (vector_sizes);
-      vector_sizes &= ~cur;
-      if (cur <= GET_MODE_SIZE (mode))
-	continue;
-      vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
-      if (VECTOR_MODE_P (vmode)
-	  && optab_handler (op, vmode) != CODE_FOR_nothing)
-	return true;
-    }
-  return false;
-}
 
-/* Return true if there is a compare_and_swap pattern.  */
-
-bool
-can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
-{
-  enum insn_code icode;
-
-  /* Check for __atomic_compare_and_swap.  */
-  icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
-  if (icode != CODE_FOR_nothing)
-    return true;
-
-  /* Check for __sync_compare_and_swap.  */
-  icode = optab_handler (sync_compare_and_swap_optab, mode);
-  if (icode != CODE_FOR_nothing)
-    return true;
-  if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
-    return true;
-
-  /* No inline compare and swap.  */
-  return false;
-}
-
-/* Return true if an atomic exchange can be performed.  */
-
-bool
-can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
-{
-  enum insn_code icode;
-
-  /* Check for __atomic_exchange.  */
-  icode = direct_optab_handler (atomic_exchange_optab, mode);
-  if (icode != CODE_FOR_nothing)
-    return true;
-
-  /* Don't check __sync_test_and_set, as on some platforms that
-     has reduced functionality.  Targets that really do support
-     a proper exchange should simply be updated to the __atomics.  */
-
-  return can_compare_and_swap_p (mode, allow_libcall);
-}
-
-
 /* Helper function to find the MODE_CC set in a sync_compare_and_swap
    pattern.  */
 
@@ -8411,225 +6791,3 @@ expand_jump_insn (enum insn_code icode, unsigned int nops,
   if (!maybe_expand_jump_insn (icode, nops, ops))
     gcc_unreachable ();
 }
-
-/* Reduce conditional compilation elsewhere.  */
-
-/* Enumerates the possible types of structure operand to an
-   extraction_insn.  */
-enum extraction_type { ET_unaligned_mem, ET_reg };
-
-/* Check whether insv, extv or extzv pattern ICODE can be used for an
-   insertion or extraction of type TYPE on a structure of mode MODE.
-   Return true if so and fill in *INSN accordingly.  STRUCT_OP is the
-   operand number of the structure (the first sign_extract or zero_extract
-   operand) and FIELD_OP is the operand number of the field (the other
-   side of the set from the sign_extract or zero_extract).  */
-
-static bool
-get_traditional_extraction_insn (extraction_insn *insn,
-				 enum extraction_type type,
-				 machine_mode mode,
-				 enum insn_code icode,
-				 int struct_op, int field_op)
-{
-  const struct insn_data_d *data = &insn_data[icode];
-
-  machine_mode struct_mode = data->operand[struct_op].mode;
-  if (struct_mode == VOIDmode)
-    struct_mode = word_mode;
-  if (mode != struct_mode)
-    return false;
-
-  machine_mode field_mode = data->operand[field_op].mode;
-  if (field_mode == VOIDmode)
-    field_mode = word_mode;
-
-  machine_mode pos_mode = data->operand[struct_op + 2].mode;
-  if (pos_mode == VOIDmode)
-    pos_mode = word_mode;
-
-  insn->icode = icode;
-  insn->field_mode = field_mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
-  insn->pos_mode = pos_mode;
-  return true;
-}
-
-/* Return true if an optab exists to perform an insertion or extraction
-   of type TYPE in mode MODE.  Describe the instruction in *INSN if so.
-
-   REG_OPTAB is the optab to use for register structures and
-   MISALIGN_OPTAB is the optab to use for misaligned memory structures.
-   POS_OP is the operand number of the bit position.  */
-
-static bool
-get_optab_extraction_insn (struct extraction_insn *insn,
-			   enum extraction_type type,
-			   machine_mode mode, direct_optab reg_optab,
-			   direct_optab misalign_optab, int pos_op)
-{
-  direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
-  enum insn_code icode = direct_optab_handler (optab, mode);
-  if (icode == CODE_FOR_nothing)
-    return false;
-
-  const struct insn_data_d *data = &insn_data[icode];
-
-  insn->icode = icode;
-  insn->field_mode = mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
-  insn->pos_mode = data->operand[pos_op].mode;
-  if (insn->pos_mode == VOIDmode)
-    insn->pos_mode = word_mode;
-  return true;
-}
-
-/* Return true if an instruction exists to perform an insertion or
-   extraction (PATTERN says which) of type TYPE in mode MODE.
-   Describe the instruction in *INSN if so.  */
-
-static bool
-get_extraction_insn (extraction_insn *insn,
-		     enum extraction_pattern pattern,
-		     enum extraction_type type,
-		     machine_mode mode)
-{
-  switch (pattern)
-    {
-    case EP_insv:
-      if (targetm.have_insv ()
-	  && get_traditional_extraction_insn (insn, type, mode,
-					      targetm.code_for_insv, 0, 3))
-	return true;
-      return get_optab_extraction_insn (insn, type, mode, insv_optab,
-					insvmisalign_optab, 2);
-
-    case EP_extv:
-      if (targetm.have_extv ()
-	  && get_traditional_extraction_insn (insn, type, mode,
-					      targetm.code_for_extv, 1, 0))
-	return true;
-      return get_optab_extraction_insn (insn, type, mode, extv_optab,
-					extvmisalign_optab, 3);
-
-    case EP_extzv:
-      if (targetm.have_extzv ()
-	  && get_traditional_extraction_insn (insn, type, mode,
-					      targetm.code_for_extzv, 1, 0))
-	return true;
-      return get_optab_extraction_insn (insn, type, mode, extzv_optab,
-					extzvmisalign_optab, 3);
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-/* Return true if an instruction exists to access a field of mode
-   FIELDMODE in a structure that has STRUCT_BITS significant bits.
-   Describe the "best" such instruction in *INSN if so.  PATTERN and
-   TYPE describe the type of insertion or extraction we want to perform.
-
-   For an insertion, the number of significant structure bits includes
-   all bits of the target.  For an extraction, it need only include the
-   most significant bit of the field.  Larger widths are acceptable
-   in both cases.  */
-
-static bool
-get_best_extraction_insn (extraction_insn *insn,
-			  enum extraction_pattern pattern,
-			  enum extraction_type type,
-			  unsigned HOST_WIDE_INT struct_bits,
-			  machine_mode field_mode)
-{
-  machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
-  while (mode != VOIDmode)
-    {
-      if (get_extraction_insn (insn, pattern, type, mode))
-	{
-	  while (mode != VOIDmode
-		 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
-		 && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
-						    field_mode))
-	    {
-	      get_extraction_insn (insn, pattern, type, mode);
-	      mode = GET_MODE_WIDER_MODE (mode);
-	    }
-	  return true;
-	}
-      mode = GET_MODE_WIDER_MODE (mode);
-    }
-  return false;
-}
-
-/* Return true if an instruction exists to access a field of mode
-   FIELDMODE in a register structure that has STRUCT_BITS significant bits.
-   Describe the "best" such instruction in *INSN if so.  PATTERN describes
-   the type of insertion or extraction we want to perform.
-
-   For an insertion, the number of significant structure bits includes
-   all bits of the target.  For an extraction, it need only include the
-   most significant bit of the field.  Larger widths are acceptable
-   in both cases.  */
-
-bool
-get_best_reg_extraction_insn (extraction_insn *insn,
-			      enum extraction_pattern pattern,
-			      unsigned HOST_WIDE_INT struct_bits,
-			      machine_mode field_mode)
-{
-  return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
-				   field_mode);
-}
-
-/* Return true if an instruction exists to access a field of BITSIZE
-   bits starting BITNUM bits into a memory structure.  Describe the
-   "best" such instruction in *INSN if so.  PATTERN describes the type
-   of insertion or extraction we want to perform and FIELDMODE is the
-   natural mode of the extracted field.
-
-   The instructions considered here only access bytes that overlap
-   the bitfield; they do not touch any surrounding bytes.  */
-
-bool
-get_best_mem_extraction_insn (extraction_insn *insn,
-			      enum extraction_pattern pattern,
-			      HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
-			      machine_mode field_mode)
-{
-  unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
-					+ bitsize
-					+ BITS_PER_UNIT - 1);
-  struct_bits -= struct_bits % BITS_PER_UNIT;
-  return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
-				   struct_bits, field_mode);
-}
-
-/* Determine whether "1 << x" is relatively cheap in word_mode.  */
-
-bool
-lshift_cheap_p (bool speed_p)
-{
-  /* FIXME: This should be made target dependent via this "this_target"
-     mechanism, similar to e.g. can_copy_init_p in gcse.c.  */
-  static bool init[2] = { false, false };
-  static bool cheap[2] = { true, true };
-
-  /* If the targer has no lshift in word_mode, the operation will most
-     probably not be cheap.  ??? Does GCC even work for such targets?  */
-  if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
-    return false;
-
-  if (!init[speed_p])
-    {
-      rtx reg = gen_raw_REG (word_mode, 10000);
-      int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
-			       word_mode, speed_p);
-      cheap[speed_p] = cost < COSTS_N_INSNS (3);
-      init[speed_p] = true;
-    }
-
-  return cheap[speed_p];
-}
-
-#include "gt-optabs.h"
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 95f5cbc..3f29d1b 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -20,87 +20,12 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_OPTABS_H
 #define GCC_OPTABS_H
 
-#include "insn-opinit.h"
+#include "optabs-query.h"
+#include "optabs-libfuncs.h"
 
 /* Generate code for a widening multiply.  */
 extern rtx expand_widening_mult (machine_mode, rtx, rtx, rtx, int, optab);
 
-/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
-   if the target does not have such an insn.  */
-
-static inline enum insn_code
-optab_handler (optab op, machine_mode mode)
-{
-  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
-   to mode TO_MODE; return CODE_FOR_nothing if the target does not have
-   such an insn.  */
-
-static inline enum insn_code
-convert_optab_handler (convert_optab op, machine_mode to_mode,
-		       machine_mode from_mode)
-{
-  unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
-  gcc_assert (op > unknown_optab && op <= LAST_CONV_OPTAB);
-  return raw_optab_handler (scode);
-}
-
-/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
-   if the target does not have such an insn.  */
-
-static inline enum insn_code
-direct_optab_handler (direct_optab op, machine_mode mode)
-{
-  return optab_handler (op, mode);
-}
-
-/* Return true if UNOPTAB is for a trapping-on-overflow operation.  */
-
-static inline bool
-trapv_unoptab_p (optab unoptab)
-{
-  return (unoptab == negv_optab
-	  || unoptab == absv_optab); 
-}
-
-/* Return true if BINOPTAB is for a trapping-on-overflow operation.  */
-
-static inline bool
-trapv_binoptab_p (optab binoptab)
-{
-  return (binoptab == addv_optab
-	  || binoptab == subv_optab
-	  || binoptab == smulv_optab);
-}
-
-
-
-/* Describes an instruction that inserts or extracts a bitfield.  */
-struct extraction_insn
-{
-  /* The code of the instruction.  */
-  enum insn_code icode;
-
-  /* The mode that the structure operand should have.  This is byte_mode
-     when using the legacy insv, extv and extzv patterns to access memory.  */
-  machine_mode struct_mode;
-
-  /* The mode of the field to be inserted or extracted, and by extension
-     the mode of the insertion or extraction itself.  */
-  machine_mode field_mode;
-
-  /* The mode of the field's bit position.  This is only important
-     when the position is variable rather than constant.  */
-  machine_mode pos_mode;
-};
-
-
-
-
 /* Describes the type of an expand_operand.  Each value is associated
    with a create_*_operand function; see the comments above those
    functions for details.  */
@@ -227,30 +152,6 @@ create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
 }
 
 
-extern rtx convert_optab_libfunc (convert_optab optab, machine_mode mode1,
-			          machine_mode mode2);
-extern rtx optab_libfunc (optab optab, machine_mode mode);
-extern enum insn_code widening_optab_handler (optab, machine_mode,
-					      machine_mode);
-/* Find a widening optab even if it doesn't widen as much as we want.  */
-#define find_widening_optab_handler(A,B,C,D) \
-  find_widening_optab_handler_and_mode (A, B, C, D, NULL)
-extern enum insn_code find_widening_optab_handler_and_mode (optab,
-							    machine_mode,
-							    machine_mode,
-							    int,
-							    machine_mode *);
-
-/* An extra flag to control optab_for_tree_code's behavior.  This is needed to
-   distinguish between machines with a vector shift that takes a scalar for the
-   shift amount vs. machines that take a vector for the shift amount.  */
-enum optab_subtype
-{
-  optab_default,
-  optab_scalar,
-  optab_vector
-};
-
 /* Passed to expand_simple_binop and expand_binop to say which options
    to try to use if the requested operation can't be open-coded on the
    requisite mode.  Either OPTAB_LIB or OPTAB_LIB_WIDEN says try using
@@ -267,16 +168,6 @@ enum optab_methods
   OPTAB_MUST_WIDEN
 };
 
-/* Return the optab used for computing the given operation on the type given by
-   the second argument.  The third argument distinguishes between the types of
-   vector shifts and rotates */
-extern optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
-
-/* Given an optab that reduces a vector to a scalar, find instead the old
-   optab that produces a vector with the reduction result in one element,
-   for a tree with the specified type.  */
-extern optab scalar_reduc_to_vector (optab, const_tree type);
-
 extern rtx expand_widen_pattern_expr (struct separate_ops *, rtx , rtx , rtx,
                                       rtx, int);
 extern rtx expand_ternary_op (machine_mode mode, optab ternary_optab,
@@ -368,9 +259,6 @@ extern void emit_indirect_jump (rtx);
 rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode,
 			   rtx, rtx, machine_mode, int);
 
-/* Return nonzero if the conditional move is supported.  */
-int can_conditionally_move_p (machine_mode mode);
-
 rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
 			  rtx, rtx, machine_mode, int);
 
@@ -386,22 +274,10 @@ extern rtx_insn *gen_sub2_insn (rtx, rtx);
 extern rtx_insn *gen_sub3_insn (rtx, rtx, rtx);
 extern int have_sub2_insn (rtx, rtx);
 
-/* Return the INSN_CODE to use for an extend operation.  */
-extern enum insn_code can_extend_p (machine_mode, machine_mode, int);
-
 /* Generate the body of an insn to extend Y (with mode MFROM)
    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
 extern rtx_insn *gen_extend_insn (rtx, rtx, machine_mode, machine_mode, int);
 
-/* Return the insn_code for a FLOAT_EXPR.  */
-enum insn_code can_float_p (machine_mode, machine_mode, int);
-
-/* Check whether an operation represented by the code CODE is a
-   convert operation that is supported by the target platform in
-   vector form */
-bool supportable_convert_operation (enum tree_code, tree, tree, tree *, 
-                                    enum tree_code *);
-
 /* Generate code for a FLOAT_EXPR.  */
 extern void expand_float (rtx, rtx, int);
 
@@ -418,104 +294,18 @@ extern bool expand_sfix_optab (rtx, rtx, convert_optab);
    perform the operation described by CODE and MODE.  */
 extern int have_insn_for (enum rtx_code, machine_mode);
 
-extern void gen_int_libfunc (optab, const char *, char, machine_mode);
-extern void gen_fp_libfunc (optab, const char *, char, machine_mode);
-extern void gen_fixed_libfunc (optab, const char *, char, machine_mode);
-extern void gen_signed_fixed_libfunc (optab, const char *, char,
-				      machine_mode);
-extern void gen_unsigned_fixed_libfunc (optab, const char *, char,
-					machine_mode);
-extern void gen_int_fp_libfunc (optab, const char *, char, machine_mode);
-extern void gen_intv_fp_libfunc (optab, const char *, char, machine_mode);
-extern void gen_int_fp_fixed_libfunc (optab, const char *, char,
-				      machine_mode);
-extern void gen_int_fp_signed_fixed_libfunc (optab, const char *, char,
-					     machine_mode);
-extern void gen_int_fixed_libfunc (optab, const char *, char,
-				   machine_mode);
-extern void gen_int_signed_fixed_libfunc (optab, const char *, char,
-					  machine_mode);
-extern void gen_int_unsigned_fixed_libfunc (optab, const char *, char,
-					    machine_mode);
-
-extern void gen_interclass_conv_libfunc (convert_optab, const char *,
-					 machine_mode, machine_mode);
-extern void gen_int_to_fp_conv_libfunc (convert_optab, const char *,
-					machine_mode, machine_mode);
-extern void gen_ufloat_conv_libfunc (convert_optab, const char *,
-				     machine_mode, machine_mode);
-extern void gen_int_to_fp_nondecimal_conv_libfunc  (convert_optab,
-						    const char *,
-						    machine_mode,
-						    machine_mode);
-extern void gen_fp_to_int_conv_libfunc (convert_optab, const char *,
-					machine_mode, machine_mode);
-extern void gen_intraclass_conv_libfunc (convert_optab, const char *,
-					 machine_mode, machine_mode);
-extern void gen_trunc_conv_libfunc (convert_optab, const char *,
-				    machine_mode, machine_mode);
-extern void gen_extend_conv_libfunc (convert_optab, const char *,
-				     machine_mode, machine_mode);
-extern void gen_fract_conv_libfunc (convert_optab, const char *,
-				    machine_mode, machine_mode);
-extern void gen_fractuns_conv_libfunc (convert_optab, const char *,
-				       machine_mode, machine_mode);
-extern void gen_satfract_conv_libfunc (convert_optab, const char *,
-				       machine_mode, machine_mode);
-extern void gen_satfractuns_conv_libfunc (convert_optab, const char *,
-					  machine_mode,
-					  machine_mode);
-
-/* Build a decl for a libfunc named NAME. */
-extern tree build_libfunc_function (const char *);
-
-/* Call this to initialize an optab function entry.  */
-extern rtx init_one_libfunc (const char *);
-extern rtx set_user_assembler_libfunc (const char *, const char *);
-
-/* Call this to reset the function entry for one optab.  */
-extern void set_optab_libfunc (optab, machine_mode, const char *);
-extern void set_conv_libfunc (convert_optab, machine_mode,
-			      machine_mode, const char *);
-
-/* Call this once to initialize the contents of the optabs
-   appropriately for the current target machine.  */
-extern void init_optabs (void);
-extern void init_tree_optimization_optabs (tree);
-
-/* Call this to install all of the __sync libcalls up to size MAX.  */
-extern void init_sync_libfuncs (int max);
-
 /* Generate a conditional trap instruction.  */
 extern rtx_insn *gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
 
-/* Return true if target supports vector operations for VEC_PERM_EXPR.  */
-extern bool can_vec_perm_p (machine_mode, bool, const unsigned char *);
-
 /* Generate code for VEC_PERM_EXPR.  */
 extern rtx expand_vec_perm (machine_mode, rtx, rtx, rtx, rtx);
 
-/* Return tree if target supports vector operations for COND_EXPR.  */
-bool expand_vec_cond_expr_p (tree, tree);
-
 /* Generate code for VEC_COND_EXPR.  */
 extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
 
-/* Return non-zero if target supports a given highpart multiplication.  */
-extern int can_mult_highpart_p (machine_mode, bool);
-
 /* Generate code for MULT_HIGHPART_EXPR.  */
 extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
 
-/* Return true if target supports vector masked load/store for mode.  */
-extern bool can_vec_mask_load_store_p (machine_mode, bool);
-
-/* Return true if there is an inline compare and swap pattern.  */
-extern bool can_compare_and_swap_p (machine_mode, bool);
-
-/* Return true if there is an inline atomic exchange pattern.  */
-extern bool can_atomic_exchange_p (machine_mode, bool);
-
 extern rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
 extern rtx expand_atomic_test_and_set (rtx, rtx, enum memmodel);
 extern rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
@@ -549,20 +339,6 @@ extern void expand_insn (enum insn_code icode, unsigned int nops,
 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
 			      struct expand_operand *ops);
 
-/* Enumerates the possible extraction_insn operations.  */
-enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
-
-extern bool get_best_reg_extraction_insn (extraction_insn *,
-					  enum extraction_pattern,
-					  unsigned HOST_WIDE_INT,
-					  machine_mode);
-extern bool get_best_mem_extraction_insn (extraction_insn *,
-					  enum extraction_pattern,
-					  HOST_WIDE_INT, HOST_WIDE_INT,
-					  machine_mode);
-
-extern bool lshift_cheap_p (bool);
-
 extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
 
 #endif /* GCC_OPTABS_H */
diff --git a/gcc/target-globals.c b/gcc/target-globals.c
index 654a059..54b8517 100644
--- a/gcc/target-globals.c
+++ b/gcc/target-globals.c
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
 #include "libfuncs.h"
 #include "cfgloop.h"
 #include "ira.h"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 926224a..68479e6 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -87,7 +87,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-prop.h"
 #include "gcse.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
+#include "optabs-libfuncs.h"
 #include "tree-chkp.h"
 #include "omp-low.h"
 
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 291e602..0987884 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -120,7 +120,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
 #include "tree-hash-traits.h"
 
 /* List of basic blocks in if-conversion-suitable order.  */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index ccfde5f..5978c59 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -54,7 +54,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "cfgloop.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
 #include "tree-ssa-propagate.h"
 #include "tree-ssa-dom.h"
 #include "builtins.h"
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index 1adaed5..0260b26 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -65,7 +65,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-query.h"
 #include "recog.h"
 
 /* This pass inserts prefetch instructions to optimize cache usage during
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index eae5358..b1cc42e 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -103,15 +103,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "stor-layout.h"
 #include "tree-cfg.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
 #include "tree-pass.h"
@@ -120,11 +111,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-pretty-print.h"
 #include "builtins.h"
 #include "params.h"
-
-/* FIXME: RTL headers have to be included here for optabs.  */
-#include "expr.h"		/* Because optabs.h wants sepops.  */
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 
 /* This structure represents one basic block that either computes a
    division, or is a common dominator for basic block that compute a
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index d46ba62..0c0a393 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -38,14 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "tree-cfg.h"
 #include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-pass.h"
 #include "langhooks.h"
@@ -54,7 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-data-ref.h"
 #include "gimple-pretty-print.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "tree-scalar-evolution.h"
 #include "tree-inline.h"
 #include "params.h"
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 45e7b61..7d3b691 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -43,15 +43,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop-niter.h"
 #include "tree-ssa-loop.h"
 #include "flags.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "tree-dfa.h"
 #include "tree-ssa.h"
 #include "tree-iterator.h"
@@ -65,7 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "gimplify.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 
 /*  This is a simple global reassociation pass.  It is, in part, based
     on the LLVM pass of the same name (They do some things more/less
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 3201912..4208140 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -52,17 +52,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    type in the GIMPLE type system that is language-independent?  */
 #include "langhooks.h"
 
-/* Need to include expr.h and optabs.h for lshift_cheap_p.  */
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "stmt.h"
-#include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 
 /* Maximum number of case bit tests.
    FIXME: This should be derived from PARAM_CASE_VALUES_THRESHOLD and
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 2439bd6..671e613 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -49,19 +49,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vectorizer.h"
 #include "diagnostic-core.h"
 #include "cgraph.h"
-/* Need to include rtl.h, expr.h, etc. for optabs.  */
-#include "flags.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
 #include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "builtins.h"
 #include "params.h"
 
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index be3d27f..68a7b74 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -40,19 +40,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "diagnostic.h"
 #include "target.h"
-
-/* Need to include rtl.h, expr.h, etc. for optabs.  */
-#include "insn-config.h"
 #include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 
 
 static void expand_vector_operations_1 (gimple_stmt_iterator *);
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 59c75af..c095317 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -44,18 +44,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "cfgloop.h"
 #include "flags.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
-#include "recog.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "params.h"
 #include "diagnostic-core.h"
 #include "tree-chrec.h"
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 758ca38..b0aae4f 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -40,15 +40,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "insn-config.h"
 #include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "params.h"
 #include "tree-data-ref.h"
 #include "tree-vectorizer.h"
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 2face16..1dd8167 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -40,17 +40,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "flags.h"
 #include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "recog.h"		/* FIXME: for insn_data */
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "tree-vectorizer.h"
 #include "langhooks.h"
 #include "gimple-walk.h"
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 359e010..d4a436d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -45,17 +45,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "flags.h"
 #include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "recog.h"		/* FIXME: for insn_data */
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "diagnostic-core.h"
 #include "tree-vectorizer.h"
 #include "cgraph.h"
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d7615e1..882f84d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -54,16 +54,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "tree-chrec.h"
 #include "tree-ssa-threadupdate.h"
-#include "insn-config.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
 #include "insn-codes.h"
-#include "optabs.h"
+#include "optabs-tree.h"
 #include "tree-ssa-scopedtables.h"
 #include "tree-ssa-threadedge.h"
 
