OSDN Git Service

* arm.h (HOST_INT, HOST_UINT): Delete. Remove all uses.
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
index 0e135af..28e227b 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+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 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 #include "config.h"
@@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 
 /* Include insn-config.h before expr.h so that HAVE_conditional_move
-   is properly defined. */
+   is properly defined.  */
 #include "insn-config.h"
 #include "rtl.h"
 #include "tree.h"
@@ -34,6 +34,8 @@ Boston, MA 02111-1307, USA.  */
 #include "function.h"
 #include "except.h"
 #include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
 #include "recog.h"
 #include "reload.h"
 #include "ggc.h"
@@ -99,7 +101,9 @@ static enum insn_code can_fix_p      PARAMS ((enum machine_mode, enum machine_mode,
 static enum insn_code can_float_p PARAMS ((enum machine_mode, enum machine_mode,
                                         int));
 static rtx ftruncify   PARAMS ((rtx));
-static optab init_optab        PARAMS ((enum rtx_code));
+static optab new_optab PARAMS ((void));
+static inline optab init_optab PARAMS ((enum rtx_code));
+static inline optab init_optabv        PARAMS ((enum rtx_code));
 static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
 static void init_integral_libfuncs PARAMS ((optab, const char *, int));
 static void init_floating_libfuncs PARAMS ((optab, const char *, int));
@@ -597,6 +601,25 @@ expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
   return 1;
 }
 \f
+/* Wrapper around expand_binop which takes an rtx code to specify
+   the operation to perform, not an optab pointer.  All other
+   arguments are the same.  */
+rtx
+expand_simple_binop (mode, code, op0, op1, target, unsignedp, methods)
+     enum machine_mode mode;
+     enum rtx_code code;
+     rtx op0, op1;
+     rtx target;
+     int unsignedp;
+     enum optab_methods methods;
+{
+  optab binop = code_to_optab [(int) code];
+  if (binop == 0)
+    abort ();
+
+  return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
+}
+
 /* Generate code to perform an operation specified by BINOPTAB
    on operands OP0 and OP1, with result having machine-mode MODE.
 
@@ -622,7 +645,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
        ? OPTAB_WIDEN : methods);
   enum mode_class class;
   enum machine_mode wider_mode;
-  register rtx temp;
+  rtx temp;
   int commutative_op = 0;
   int shift_op = (binoptab->code ==  ASHIFT
                  || binoptab->code == ASHIFTRT
@@ -715,7 +738,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
          if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
              && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
            {
-             register rtx tmp;
+             rtx tmp;
 
              tmp = op0; op0 = op1; op1 = tmp;
              tmp = xop0; xop0 = xop1; xop1 = tmp;
@@ -830,7 +853,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
 
            /* For certain integer operations, we need not actually extend
               the narrow operands, as long as we will truncate
-              the results to the same narrowness.   */
+              the results to the same narrowness.  */
 
            if ((binoptab == ior_optab || binoptab == and_optab
                 || binoptab == xor_optab
@@ -1162,7 +1185,6 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
       && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
     {
       unsigned int i;
-      rtx carry_tmp = gen_reg_rtx (word_mode);
       optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
       unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
       rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
@@ -1218,24 +1240,22 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
 
          if (i > 0)
            {
+             rtx newx;
+             
              /* Add/subtract previous carry to main result.  */
-             x = expand_binop (word_mode,
-                               normalizep == 1 ? binoptab : otheroptab,
-                               x, carry_in,
-                               target_piece, 1, next_methods);
-             if (x == 0)
-               break;
-             else if (target_piece != x)
-               emit_move_insn (target_piece, x);
+             newx = expand_binop (word_mode,
+                                  normalizep == 1 ? binoptab : otheroptab,
+                                  x, carry_in,
+                                  NULL_RTX, 1, next_methods);
 
              if (i + 1 < nwords)
                {
-                 /* THIS CODE HAS NOT BEEN TESTED.  */
                  /* Get out carry from adding/subtracting carry in.  */
+                 rtx carry_tmp = gen_reg_rtx (word_mode);
                  carry_tmp = emit_store_flag_force (carry_tmp,
-                                                    binoptab == add_optab
-                                                    ? LT : GT,
-                                                    x, carry_in,
+                                                    (binoptab == add_optab
+                                                     ? LT : GT),
+                                                    newx, x,
                                                     word_mode, 1, normalizep);
 
                  /* Logical-ior the two poss. carry together.  */
@@ -1245,6 +1265,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
                  if (carry_out == 0)
                    break;
                }
+             emit_move_insn (target_piece, newx);
            }
 
          carry_in = carry_out;
@@ -1841,7 +1862,7 @@ sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
     int unsignedp;
     enum optab_methods methods;
 {
-  register rtx temp;
+  rtx temp;
   optab direct_optab = unsignedp ? uoptab : soptab;
   struct optab wide_soptab;
 
@@ -1990,8 +2011,8 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
          if (binoptab->handlers[(int) wider_mode].insn_code
              != CODE_FOR_nothing)
            {
-             register rtx t0 = gen_reg_rtx (wider_mode);
-             register rtx t1 = gen_reg_rtx (wider_mode);
+             rtx t0 = gen_reg_rtx (wider_mode);
+             rtx t1 = gen_reg_rtx (wider_mode);
              rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
              rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
 
@@ -2012,6 +2033,24 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
   return 0;
 }
 \f
+/* Wrapper around expand_unop which takes an rtx code to specify
+   the operation to perform, not an optab pointer.  All other
+   arguments are the same.  */
+rtx
+expand_simple_unop (mode, code, op0, target, unsignedp)
+     enum machine_mode mode;
+     enum rtx_code code;
+     rtx op0;
+     rtx target;
+     int unsignedp;
+{
+  optab unop = code_to_optab [(int) code];
+  if (unop == 0)
+    abort ();
+
+  return expand_unop (mode, unop, op0, target, unsignedp);
+}
+
 /* Generate code to perform an operation specified by UNOPTAB
    on operand OP0, with result having machine-mode MODE.
 
@@ -2033,7 +2072,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
 {
   enum mode_class class;
   enum machine_mode wider_mode;
-  register rtx temp;
+  rtx temp;
   rtx last = get_last_insn ();
   rtx pat;
 
@@ -2409,7 +2448,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
 {
   enum mode_class class = GET_MODE_CLASS (mode);
   enum machine_mode wider_mode;
-  register rtx temp;
+  rtx temp;
   rtx entry_last = get_last_insn ();
   rtx last;
   rtx pat;
@@ -2610,7 +2649,7 @@ emit_unop_insn (icode, target, op0, code)
      rtx op0;
      enum rtx_code code;
 {
-  register rtx temp;
+  rtx temp;
   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
   rtx pat;
 
@@ -2820,23 +2859,36 @@ emit_libcall_block (insns, target, result, equiv)
      into a MEM later.  Protect the libcall block from this change.  */
   if (! REG_P (target) || REG_USERVAR_P (target))
     target = gen_reg_rtx (GET_MODE (target));
-
+  
+  /* If we're using non-call exceptions, a libcall corresponding to an
+     operation that may trap may also trap.  */
+  if (flag_non_call_exceptions && may_trap_p (equiv))
+    {
+      for (insn = insns; insn; insn = NEXT_INSN (insn))
+       if (GET_CODE (insn) == CALL_INSN)
+         {
+           rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+           
+           if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
+             remove_note (insn, note);
+         }
+    }
+  else
   /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
      reg note to indicate that this call cannot throw or execute a nonlocal
      goto (unless there is already a REG_EH_REGION note, in which case
      we update it).  */
-
-  for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == CALL_INSN)
-      {
-       rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-
-       if (note != 0)
-         XEXP (note, 0) = GEN_INT (-1);
-       else
-         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
-                                               REG_NOTES (insn));
-      }
+    for (insn = insns; insn; insn = NEXT_INSN (insn))
+      if (GET_CODE (insn) == CALL_INSN)
+       {
+         rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+       
+         if (note != 0)
+           XEXP (note, 0) = GEN_INT (-1);
+         else
+           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
+                                                 REG_NOTES (insn));
+       }
 
   /* First emit all insns that set pseudos.  Remove them from the list as
      we go.  Avoid insns that set pseudos which were referenced in previous
@@ -2905,9 +2957,13 @@ emit_libcall_block (insns, target, result, equiv)
     first = NEXT_INSN (prev);
 
   /* Encapsulate the block so it gets manipulated as a unit.  */
-  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
-                                        REG_NOTES (first));
-  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
+  if (!flag_non_call_exceptions || !may_trap_p (equiv))
+    {
+      REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
+                                            REG_NOTES (first));
+      REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
+                                           REG_NOTES (last));
+    }
 }
 \f
 /* Generate code to store zero in X.  */
@@ -3164,7 +3220,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
 
 /* Before emitting an insn with code ICODE, make sure that X, which is going
    to be used for operand OPNUM of the insn, is converted from mode MODE to
-   WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
+   WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
    that it is accepted by the operand predicate.  Return the new value.  */
 
 rtx
@@ -3725,7 +3781,7 @@ can_conditionally_move_p (mode)
 
 #endif /* HAVE_conditional_move */
 \f
-/* These three functions generate an insn body and return it
+/* These functions generate an insn body and return it
    rather than emitting the insn.
 
    They do not protect from queued increments,
@@ -3751,11 +3807,49 @@ gen_add2_insn (x, y)
   return (GEN_FCN (icode) (x, x, y));
 }
 
+/* Generate and return an insn body to add r1 and c,
+   storing the result in r0.  */
+rtx
+gen_add3_insn (r0, r1, c)
+     rtx r0, r1, c;
+{
+  int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
+
+    if (icode == CODE_FOR_nothing
+      || ! ((*insn_data[icode].operand[0].predicate)
+           (r0, insn_data[icode].operand[0].mode))
+      || ! ((*insn_data[icode].operand[1].predicate)
+           (r1, insn_data[icode].operand[1].mode))
+      || ! ((*insn_data[icode].operand[2].predicate)
+           (c, insn_data[icode].operand[2].mode)))
+    return NULL_RTX;
+
+  return (GEN_FCN (icode) (r0, r1, c));
+}
+
 int
-have_add2_insn (mode)
-     enum machine_mode mode;
+have_add2_insn (x, y)
+     rtx x, y;
 {
-  return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+  int icode;
+
+  if (GET_MODE (x) == VOIDmode)
+    abort ();
+
+  icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code; 
+
+  if (icode == CODE_FOR_nothing)
+    return 0;
+
+  if (! ((*insn_data[icode].operand[0].predicate)
+        (x, insn_data[icode].operand[0].mode))
+      || ! ((*insn_data[icode].operand[1].predicate)
+           (x, insn_data[icode].operand[1].mode))
+      || ! ((*insn_data[icode].operand[2].predicate)
+           (y, insn_data[icode].operand[2].mode)))
+    return 0;
+
+  return 1;
 }
 
 /* Generate and return an insn body to subtract Y from X.  */
@@ -3777,11 +3871,49 @@ gen_sub2_insn (x, y)
   return (GEN_FCN (icode) (x, x, y));
 }
 
+/* Generate and return an insn body to subtract r1 and c,
+   storing the result in r0.  */
+rtx
+gen_sub3_insn (r0, r1, c)
+     rtx r0, r1, c;
+{
+  int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
+
+    if (icode == CODE_FOR_nothing
+      || ! ((*insn_data[icode].operand[0].predicate)
+           (r0, insn_data[icode].operand[0].mode))
+      || ! ((*insn_data[icode].operand[1].predicate)
+           (r1, insn_data[icode].operand[1].mode))
+      || ! ((*insn_data[icode].operand[2].predicate)
+           (c, insn_data[icode].operand[2].mode)))
+    return NULL_RTX;
+
+  return (GEN_FCN (icode) (r0, r1, c));
+}
+
 int
-have_sub2_insn (mode)
-     enum machine_mode mode;
+have_sub2_insn (x, y)
+     rtx x, y;
 {
-  return sub_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
+  int icode;
+
+  if (GET_MODE (x) == VOIDmode)
+    abort ();
+
+  icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code; 
+
+  if (icode == CODE_FOR_nothing)
+    return 0;
+
+  if (! ((*insn_data[icode].operand[0].predicate)
+        (x, insn_data[icode].operand[0].mode))
+      || ! ((*insn_data[icode].operand[1].predicate)
+           (x, insn_data[icode].operand[1].mode))
+      || ! ((*insn_data[icode].operand[2].predicate)
+           (y, insn_data[icode].operand[2].mode)))
+    return 0;
+
+  return 1;
 }
 
 /* Generate the body of an instruction to copy Y into X.
@@ -3791,7 +3923,7 @@ rtx
 gen_move_insn (x, y)
      rtx x, y;
 {
-  register enum machine_mode mode = GET_MODE (x);
+  enum machine_mode mode = GET_MODE (x);
   enum insn_code insn_code;
   rtx seq;
 
@@ -3833,16 +3965,14 @@ gen_move_insn (x, y)
          x = gen_lowpart_common (tmode, x1);
          if (x == 0 && GET_CODE (x1) == MEM)
            {
-             x = gen_rtx_MEM (tmode, XEXP (x1, 0));
-             MEM_COPY_ATTRIBUTES (x, x1);
+             x = adjust_address_nv (x1, tmode, 0);
              copy_replacements (x1, x);
            }
 
          y = gen_lowpart_common (tmode, y1);
          if (y == 0 && GET_CODE (y1) == MEM)
            {
-             y = gen_rtx_MEM (tmode, XEXP (y1, 0));
-             MEM_COPY_ATTRIBUTES (y, y1);
+             y = adjust_address_nv (y1, tmode, 0);
              copy_replacements (y1, y);
            }
        }
@@ -3872,7 +4002,12 @@ can_extend_p (to_mode, from_mode, unsignedp)
      enum machine_mode to_mode, from_mode;
      int unsignedp;
 {
-  return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
+#ifdef HAVE_ptr_extend
+  if (unsignedp < 0)
+    return CODE_FOR_ptr_extend;
+  else
+#endif
+    return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
 }
 
 /* Generate the body of an insn to extend Y (with mode MFROM)
@@ -3935,7 +4070,7 @@ expand_float (to, from, unsignedp)
      int unsignedp;
 {
   enum insn_code icode;
-  register rtx target = to;
+  rtx target = to;
   enum machine_mode fmode, imode;
 
   /* Crash now, because we won't be able to decide which mode to use.  */
@@ -4202,11 +4337,11 @@ ftruncify (x)
 
 void
 expand_fix (to, from, unsignedp)
-     register rtx to, from;
+     rtx to, from;
      int unsignedp;
 {
   enum insn_code icode;
-  register rtx target = to;
+  rtx target = to;
   enum machine_mode fmode, imode;
   int must_trunc = 0;
   rtx libfcn = 0;
@@ -4421,22 +4556,53 @@ expand_fix (to, from, unsignedp)
     }
 }
 \f
-static optab
-init_optab (code)
+/* Report whether we have an instruction to perform the operation
+   specified by CODE on operands of mode MODE.  */
+int
+have_insn_for (code, mode)
      enum rtx_code code;
+     enum machine_mode mode;
+{
+  return (code_to_optab[(int) code] != 0
+         && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
+             != CODE_FOR_nothing));
+}
+
+/* Create a blank optab.  */
+static optab
+new_optab ()
 {
   int i;
   optab op = (optab) xmalloc (sizeof (struct optab));
-  op->code = code;
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
       op->handlers[i].insn_code = CODE_FOR_nothing;
       op->handlers[i].libfunc = 0;
     }
 
-  if (code != UNKNOWN)
-    code_to_optab[(int) code] = op;
+  return op;
+}
+
+/* Same, but fill in its code as CODE, and write it into the
+   code_to_optab table.  */
+static inline optab
+init_optab (code)
+     enum rtx_code code;
+{
+  optab op = new_optab ();
+  op->code = code;
+  code_to_optab[(int) code] = op;
+  return op;
+}
 
+/* Same, but fill in its code as CODE, and do _not_ write it into
+   the code_to_optab table.  */
+static inline optab
+init_optabv (code)
+     enum rtx_code code;
+{
+  optab op = new_optab ();
+  op->code = code;
   return op;
 }
 
@@ -4459,23 +4625,23 @@ init_optab (code)
 
 static void
 init_libfuncs (optable, first_mode, last_mode, opname, suffix)
-    register optab optable;
-    register int first_mode;
-    register int last_mode;
-    register const char *opname;
-    register int suffix;
+    optab optable;
+    int first_mode;
+    int last_mode;
+    const char *opname;
+    int suffix;
 {
-  register int mode;
-  register unsigned opname_len = strlen (opname);
+  int mode;
+  unsigned opname_len = strlen (opname);
 
   for (mode = first_mode; (int) mode <= (int) last_mode;
        mode = (enum machine_mode) ((int) mode + 1))
     {
-      register const char *mname = GET_MODE_NAME(mode);
-      register unsigned mname_len = strlen (mname);
-      register char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
-      register char *p;
-      register const char *q;
+      const char *mname = GET_MODE_NAME(mode);
+      unsigned mname_len = strlen (mname);
+      char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
+      char *p;
+      const char *q;
 
       p = libfunc_name;
       *p++ = '_';
@@ -4500,9 +4666,9 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
 
 static void
 init_integral_libfuncs (optable, opname, suffix)
-    register optab optable;
-    register const char *opname;
-    register int suffix;
+    optab optable;
+    const char *opname;
+    int suffix;
 {
   init_libfuncs (optable, SImode, TImode, opname, suffix);
 }
@@ -4514,20 +4680,28 @@ init_integral_libfuncs (optable, opname, suffix)
 
 static void
 init_floating_libfuncs (optable, opname, suffix)
-    register optab optable;
-    register const char *opname;
-    register int suffix;
+    optab optable;
+    const char *opname;
+    int suffix;
 {
   init_libfuncs (optable, SFmode, TFmode, opname, suffix);
 }
 
 rtx
 init_one_libfunc (name)
-     register const char *name;
+     const char *name;
 {
-  name = ggc_strdup (name);
-
-  return gen_rtx_SYMBOL_REF (Pmode, name);
+  /* Create a FUNCTION_DECL that can be passed to ENCODE_SECTION_INFO.  */
+  /* ??? We don't have any type information except for this is
+     a function.  Pretend this is "int foo()".  */
+  tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
+                         build_function_type (integer_type_node, NULL_TREE));
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+
+  /* Return the symbol_ref from the mem rtx.  */
+  return XEXP (DECL_RTL (decl), 0);
 }
 
 /* Mark ARG (which is really an OPTAB *) for GC.  */
@@ -4582,23 +4756,22 @@ init_optabs ()
 #endif
 
   add_optab = init_optab (PLUS);
-  addv_optab = init_optab (PLUS);
+  addv_optab = init_optabv (PLUS);
   sub_optab = init_optab (MINUS);
-  subv_optab = init_optab (MINUS);
+  subv_optab = init_optabv (MINUS);
   smul_optab = init_optab (MULT);
-  smulv_optab = init_optab (MULT);
+  smulv_optab = init_optabv (MULT);
   smul_highpart_optab = init_optab (UNKNOWN);
   umul_highpart_optab = init_optab (UNKNOWN);
   smul_widen_optab = init_optab (UNKNOWN);
   umul_widen_optab = init_optab (UNKNOWN);
   sdiv_optab = init_optab (DIV);
-  sdivv_optab = init_optab (DIV);
+  sdivv_optab = init_optabv (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
   udiv_optab = init_optab (UDIV);
   udivmod_optab = init_optab (UNKNOWN);
   smod_optab = init_optab (MOD);
   umod_optab = init_optab (UMOD);
-  flodiv_optab = init_optab (DIV);
   ftrunc_optab = init_optab (UNKNOWN);
   and_optab = init_optab (AND);
   ior_optab = init_optab (IOR);
@@ -4612,15 +4785,19 @@ init_optabs ()
   smax_optab = init_optab (SMAX);
   umin_optab = init_optab (UMIN);
   umax_optab = init_optab (UMAX);
-  mov_optab = init_optab (UNKNOWN);
-  movstrict_optab = init_optab (UNKNOWN);
-  cmp_optab = init_optab (UNKNOWN);
+
+  /* These three have codes assigned exclusively for the sake of
+     have_insn_for.  */
+  mov_optab = init_optab (SET);
+  movstrict_optab = init_optab (STRICT_LOW_PART);
+  cmp_optab = init_optab (COMPARE);
+
   ucmp_optab = init_optab (UNKNOWN);
   tst_optab = init_optab (UNKNOWN);
   neg_optab = init_optab (NEG);
-  negv_optab = init_optab (NEG);
+  negv_optab = init_optabv (NEG);
   abs_optab = init_optab (ABS);
-  absv_optab = init_optab (ABS);
+  absv_optab = init_optabv (ABS);
   one_cmpl_optab = init_optab (NOT);
   ffs_optab = init_optab (FFS);
   sqrt_optab = init_optab (SQRT);
@@ -4630,6 +4807,7 @@ init_optabs ()
   cbranch_optab = init_optab (UNKNOWN);
   cmov_optab = init_optab (UNKNOWN);
   cstore_optab = init_optab (UNKNOWN);
+  push_optab = init_optab (UNKNOWN);
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
@@ -4666,13 +4844,13 @@ init_optabs ()
   init_integral_libfuncs (smulv_optab, "mulv", '3');
   init_floating_libfuncs (smulv_optab, "mul", '3');
   init_integral_libfuncs (sdiv_optab, "div", '3');
+  init_floating_libfuncs (sdiv_optab, "div", '3');
   init_integral_libfuncs (sdivv_optab, "divv", '3');
   init_integral_libfuncs (udiv_optab, "udiv", '3');
   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
   init_integral_libfuncs (smod_optab, "mod", '3');
   init_integral_libfuncs (umod_optab, "umod", '3');
-  init_floating_libfuncs (flodiv_optab, "div", '3');
   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
   init_integral_libfuncs (and_optab, "and", '3');
   init_integral_libfuncs (ior_optab, "ior", '3');