Split up optabs.[hc]
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 17 Sep 2015 14:28:59 +0000 (14:28 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 17 Sep 2015 14:28:59 +0000 (14:28 +0000)
optabs.[hc] is a bit of a behemoth.  It includes basic functions for querying
what a target can do, related tree- and gimple-level query functions,
related rtl-level query functions, and the functions that actually
generate code.  Some gimple optimisations therefore need:

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

purely to query whether the target has support for a particular operation.

This patch splits optabs up as follows:

      - optabs-query.[hc]: IL-independent functions for querying what a target
          can do natively.
      - optabs-tree.[hc]: tree and gimple query functions (an extension of
          optabs-query.[hc]).
      - optabs-libfuncs.[hc]: optabs-specific libfuncs (an extension of
          libfuncs.h)
      - optabs.h: For now includes optabs-query.h and optabs-libfuncs.h.

Only two files outside optabs need to include both optabs.h and
optabs-tree.h: expr.c and function.c.  I think that's expected given
that both are related to expand.

It might be good to split optabs.h further, but this is already quite
a big patch.

I changed can_conditionally_move_p from returning an int to returning
a bool and fixed a few formatting glitches.  There should be no other
changes to the functions themselves.

gcc/
* Makefile.in (OBJS): Add optabs-libfuncs.o, optabs-query.o
and optabs-tree.o.
(GTFILES): Replace optabs.c with optabs-libfunc.c.
* genopinit.c (main): Add an include guard to insn-opinit.h.
Protect the rtx_code parts with NUM_RTX_CODE.
* optabs.h: Split parts out to...
* optabs-libfuncs.h, optabs-query.h, optabs-tree.h: ...these
new files.
* optabs.c: Split parts out to...
* optabs-libfuncs.c, optabs-query.c, optabs-tree.c: ...these
new files.
* cilk-common.c: Include optabs-query.h rather than optabs.h.
* fold-const.c: Likewise.
* target-globals.c: Likewise.
* tree-if-conv.c: Likewise.
* tree-ssa-forwprop.c: Likewise.
* tree-ssa-loop-prefetch.c: Likewise.
* tree-ssa-math-opts.c: Include optabs-tree.h rather than
optabs.h.  Remove unncessary include files.
* tree-ssa-phiopt.c: Likewise.
* tree-ssa-reassoc.c: Likewise.
* tree-switch-conversion.c: Likewise.
* tree-vect-data-refs.c: Likewise.
* tree-vect-generic.c: Likewise.
* tree-vect-loop.c: Likewise.
* tree-vect-patterns.c: Likewise.
* tree-vect-slp.c: Likewise.
* tree-vect-stmts.c: Likewise.
* tree-vrp.c: Likewise.
* toplev.c: Include optabs-query.h and optabs-libfuncs.h
rather than optabs.h.
* expr.c: Include optabs-tree.h.
* function.c: Likewise.

From-SVN: r227865

31 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/cilk-common.c
gcc/expr.c
gcc/fold-const.c
gcc/function.c
gcc/genopinit.c
gcc/optabs-libfuncs.c [new file with mode: 0644]
gcc/optabs-libfuncs.h [new file with mode: 0644]
gcc/optabs-query.c [new file with mode: 0644]
gcc/optabs-query.h [new file with mode: 0644]
gcc/optabs-tree.c [new file with mode: 0644]
gcc/optabs-tree.h [new file with mode: 0644]
gcc/optabs.c
gcc/optabs.h
gcc/target-globals.c
gcc/toplev.c
gcc/tree-if-conv.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-loop-prefetch.c
gcc/tree-ssa-math-opts.c
gcc/tree-ssa-phiopt.c
gcc/tree-ssa-reassoc.c
gcc/tree-switch-conversion.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-generic.c
gcc/tree-vect-loop.c
gcc/tree-vect-patterns.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c
gcc/tree-vrp.c

index 8ac2d3da26689f26a515abdcb694c5367462b912..fa26892fc459dc129b1e6d459b6c596ace7be2d1 100644 (file)
@@ -1,3 +1,39 @@
+2015-09-17  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * Makefile.in (OBJS): Add optabs-libfuncs.o, optabs-query.o
+       and optabs-tree.o.
+       (GTFILES): Replace optabs.c with optabs-libfunc.c.
+       * genopinit.c (main): Add an include guard to insn-opinit.h.
+       Protect the rtx_code parts with NUM_RTX_CODE.
+       * optabs.h: Split parts out to...
+       * optabs-libfuncs.h, optabs-query.h, optabs-tree.h: ...these
+       new files.
+       * optabs.c: Split parts out to...
+       * optabs-libfuncs.c, optabs-query.c, optabs-tree.c: ...these
+       new files.
+       * cilk-common.c: Include optabs-query.h rather than optabs.h.
+       * fold-const.c: Likewise.
+       * target-globals.c: Likewise.
+       * tree-if-conv.c: Likewise.
+       * tree-ssa-forwprop.c: Likewise.
+       * tree-ssa-loop-prefetch.c: Likewise.
+       * tree-ssa-math-opts.c: Include optabs-tree.h rather than
+       optabs.h.  Remove unncessary include files.
+       * tree-ssa-phiopt.c: Likewise.
+       * tree-ssa-reassoc.c: Likewise.
+       * tree-switch-conversion.c: Likewise.
+       * tree-vect-data-refs.c: Likewise.
+       * tree-vect-generic.c: Likewise.
+       * tree-vect-loop.c: Likewise.
+       * tree-vect-patterns.c: Likewise.
+       * tree-vect-slp.c: Likewise.
+       * tree-vect-stmts.c: Likewise.
+       * tree-vrp.c: Likewise.
+       * toplev.c: Include optabs-query.h and optabs-libfuncs.h
+       rather than optabs.h.
+       * expr.c: Include optabs-tree.h.
+       * function.c: Likewise.
+
 2015-09-17  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR middle-end/65958
index 254837e6efe0545a01fff0c746a9178c10aa020f..c2df21db7b3e74f7671f451a6386c68edda6950e 100644 (file)
@@ -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 \
index d8340b2f42e5cc14919cd4335a04003d58a1ab80..62acc186d31803a3bd73d6565f593b4dc9db96ea 100644 (file)
@@ -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"
index cf28f4493096515b8a78d27e35cb4012a91a7b65..165b016cf3df4d816091bd20d8b018c58508c19f 100644 (file)
@@ -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"
index 15214507f083f7440392cf2513efaa89477c3bf8..a27ef2256abd62e529d3591d50c7b8b72fb10d18 100644 (file)
@@ -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
index bb75b1c80852093e0dfd5089a3e3a05a88331021..9b4c2b99bc2e77797b73172cbff49fd8df938d5b 100644 (file)
@@ -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"
index 77e81f5e4fbaae5df1934d0976aa81a4ab4530ad..167815d561d50247226f6e014f937617d7304e86 100644 (file)
@@ -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 (file)
index 0000000..bace520
--- /dev/null
@@ -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 (file)
index 0000000..4e43c80
--- /dev/null
@@ -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 (file)
index 0000000..254089f
--- /dev/null
@@ -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 (file)
index 0000000..73f2729
--- /dev/null
@@ -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 (file)
index 0000000..3b03338
--- /dev/null
@@ -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 (file)
index 0000000..bf6c9e3
--- /dev/null
@@ -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
index c2a9b1ce9effd8bcaffc99c98d685558a41b65b7..c49d66b5a0e92a75a4c8048527dd6ae1bf8d9d98 100644 (file)
@@ -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
-\f
-/* 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;
-}
-
 \f
 /* 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;
 }
 \f
-/* 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;
-}
-\f
 /* 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;
 }
 \f
-/* 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;
 }
 \f
-/* 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.  */
 
@@ -4879,110 +4450,6 @@ gen_extend_insn (rtx x, rtx y, machine_mode mto,
   enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
   return GEN_FCN (icode) (x, y);
 }
-\f
-/* 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;
-}
-
 \f
 /* Generate code to convert FROM to floating point
    and store in TO.  FROM must be fixed point and not VOIDmode.
@@ -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));
-           }
-       }
-}
-
-\f
-/* 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;
-}
 \f
-/* 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.  */
 
@@ -8412,225 +6792,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"
index 95f5cbcf56af7e3fea7d5cb305f84a4b788de50f..3f29d1b6f79055074b0bc3098bebeea5c92f8741 100644 (file)
@@ -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 */
index 654a059a3fc1362c47440d8f667feb66164a2541..54b8517d3696c512d8acdd7ed460e045c0710092 100644 (file)
@@ -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"
index 46689ab2860ba1e7f8ead559a756d843fcbb77d6..6d740d4233373479817fc0e21a38547215f5d56d 100644 (file)
@@ -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"
 
index 291e6020b25b4576e52be91d976fee255063a67a..0987884e4cc3f71cbc1f3cb83ec7b9feba73c8d5 100644 (file)
@@ -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.  */
index ccfde5f1e3668642402509afe73028778b757194..5978c59a738685cee193e7785961a30bfde41d8a 100644 (file)
@@ -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"
index 1adaed598c934e846b68ac85df1c9c5c747f5ec6..0260b260060d1df518327069bf368c01d1d7a49f 100644 (file)
@@ -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
index c8d0d331e9c249f1b344dd676b11ef22b04513fc..b90e9291ba0896ae6cd762f0613619d9b4a04c1b 100644 (file)
@@ -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
index d46ba6229612c86cc1db42ee59683143a5a2b271..0c0a39305b6ec8c3bb44f3f8cac6e11c2de30512 100644 (file)
@@ -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"
index f1ffb2490460e8a00fcb492d94ee155fdd1205e5..4aa2aabadc0d1a0193ddb44e5ceaa9fb43929cd9 100644 (file)
@@ -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
index 32019120b904de22b532c86ddea46eb29c17614f..4208140d73f037f0a4ca8cb7da99123a3226a9c9 100644 (file)
@@ -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"
 \f
 /* Maximum number of case bit tests.
    FIXME: This should be derived from PARAM_CASE_VALUES_THRESHOLD and
index 2439bd6390bad01ca57d2a090277f35480acc7d5..671e613a434e7dc4de0082ff488b769b510f676c 100644 (file)
@@ -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"
 
index be3d27fbdf3a4501cb3e74859f0e903a0d9c7575..68a7b7479f38b60b7193be3b9db9e78c277405b5 100644 (file)
@@ -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 *);
index 59c75af73237f6f6b74607de6adf3199fbae790a..c09531787a785b39a9d2d098195eb89a71824c02 100644 (file)
@@ -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"
index 758ca3875f8b8e1ac5fb6d61b2b10fb9b8b13dfc..b0aae4fd41d18382b6e89a306405473a62540a9f 100644 (file)
@@ -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"
index 2face16501fff7e7f3158a6a84466131a44db4b9..1dd816783f2a8f402b50cc9236fffc4a6617a29e 100644 (file)
@@ -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"
index 359e010f7f9eb5a39b64b043c7bd5e4ebbed7fd7..d4a436d38b0cd33994a0183babb812cae4bb96e1 100644 (file)
@@ -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"
index a1d8dd8ca5c8b73d151af76e8b15c4123f390dee..5e813906ac7dc5cae8a0d77eb16de585aa38016c 100644 (file)
@@ -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"