sem_aux.adb, [...] (Get_Low_Bound): Use Type_Low_Bound.
[gcc.git] / gcc / optabs.c
index 7ee84c4348c96a49e3749581b889364680ed292b..49e1c531c65dd95e0f0d040141952071d0d01a4f 100644 (file)
@@ -1,5 +1,5 @@
 /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
-   Copyright (C) 1987-2014 Free Software Foundation, Inc.
+   Copyright (C) 1987-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -28,20 +28,45 @@ along with GCC; see the file COPYING3.  If not see
    is properly defined.  */
 #include "insn-config.h"
 #include "rtl.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
 #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 "hard-reg-set.h"
 #include "function.h"
 #include "except.h"
+#include "hashtab.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.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 "libfuncs.h"
 #include "recog.h"
 #include "reload.h"
 #include "ggc.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "target.h"
 
@@ -57,9 +82,9 @@ struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
   (this_target_libfuncs->x_libfunc_hash)
 
 static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
-                                  enum machine_mode *);
-static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int);
-static void emit_libcall_block_1 (rtx, rtx, rtx, rtx, bool);
+                                  machine_mode *);
+static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int);
+static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool);
 
 /* Debug facility for use in GDB.  */
 void debug_optab_libfuncs (void);
@@ -73,20 +98,17 @@ void debug_optab_libfuncs (void);
 \f
 /* Used for libfunc_hash.  */
 
-static hashval_t
-hash_libfunc (const void *p)
+hashval_t
+libfunc_hasher::hash (libfunc_entry *e)
 {
-  const struct libfunc_entry *const e = (const struct libfunc_entry *) p;
   return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
 }
 
 /* Used for libfunc_hash.  */
 
-static int
-eq_libfunc (const void *p, const void *q)
+bool
+libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
 {
-  const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p;
-  const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q;
   return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
 }
 
@@ -94,8 +116,8 @@ eq_libfunc (const void *p, const void *q)
    from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
    if no libfunc is available.  */
 rtx
-convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
-                      enum machine_mode mode2)
+convert_optab_libfunc (convert_optab optab, machine_mode mode1,
+                      machine_mode mode2)
 {
   struct libfunc_entry e;
   struct libfunc_entry **slot;
@@ -109,8 +131,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
   e.op = optab;
   e.mode1 = mode1;
   e.mode2 = mode2;
-  slot = (struct libfunc_entry **)
-    htab_find_slot (libfunc_hash, &e, NO_INSERT);
+  slot = libfunc_hash->find_slot (&e, NO_INSERT);
   if (!slot)
     {
       const struct convert_optab_libcall_d *d
@@ -120,8 +141,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
        return NULL;
 
       d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
-      slot = (struct libfunc_entry **)
-       htab_find_slot (libfunc_hash, &e, NO_INSERT);
+      slot = libfunc_hash->find_slot (&e, NO_INSERT);
       if (!slot)
        return NULL;
     }
@@ -132,7 +152,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1,
    Trigger lazy initialization if needed, return NULL if no libfunc is
    available.  */
 rtx
-optab_libfunc (optab optab, enum machine_mode mode)
+optab_libfunc (optab optab, machine_mode mode)
 {
   struct libfunc_entry e;
   struct libfunc_entry **slot;
@@ -146,8 +166,7 @@ optab_libfunc (optab optab, enum machine_mode mode)
   e.op = optab;
   e.mode1 = mode;
   e.mode2 = VOIDmode;
-  slot = (struct libfunc_entry **)
-    htab_find_slot (libfunc_hash, &e, NO_INSERT);
+  slot = libfunc_hash->find_slot (&e, NO_INSERT);
   if (!slot)
     {
       const struct optab_libcall_d *d
@@ -157,8 +176,7 @@ optab_libfunc (optab optab, enum machine_mode mode)
        return NULL;
 
       d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
-      slot = (struct libfunc_entry **)
-       htab_find_slot (libfunc_hash, &e, NO_INSERT);
+      slot = libfunc_hash->find_slot (&e, NO_INSERT);
       if (!slot)
        return NULL;
     }
@@ -177,9 +195,10 @@ optab_libfunc (optab optab, enum machine_mode mode)
    try again, ensuring that TARGET is not one of the operands.  */
 
 static int
-add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
+add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
 {
-  rtx last_insn, set;
+  rtx_insn *last_insn;
+  rtx set;
   rtx note;
 
   gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
@@ -277,12 +296,12 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
    for a widening operation would be.  In most cases this would be OP0, but if
    that's a constant it'll be VOIDmode, which isn't useful.  */
 
-static enum machine_mode
-widened_mode (enum machine_mode to_mode, rtx op0, rtx op1)
+static machine_mode
+widened_mode (machine_mode to_mode, rtx op0, rtx op1)
 {
-  enum machine_mode m0 = GET_MODE (op0);
-  enum machine_mode m1 = GET_MODE (op1);
-  enum machine_mode result;
+  machine_mode m0 = GET_MODE (op0);
+  machine_mode m1 = GET_MODE (op1);
+  machine_mode result;
 
   if (m0 == VOIDmode && m1 == VOIDmode)
     return to_mode;
@@ -301,8 +320,8 @@ widened_mode (enum machine_mode to_mode, rtx op0, rtx op1)
    TO_MODE and a FROM_MODE.  */
 
 enum insn_code
-widening_optab_handler (optab op, enum machine_mode to_mode,
-                       enum machine_mode from_mode)
+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)
@@ -323,10 +342,10 @@ widening_optab_handler (optab op, enum machine_mode to_mode,
    non-widening optabs also.  */
 
 enum insn_code
-find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode,
-                                     enum machine_mode from_mode,
+find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
+                                     machine_mode from_mode,
                                      int permit_non_widening,
-                                     enum machine_mode *found_mode)
+                                     machine_mode *found_mode)
 {
   for (; (permit_non_widening || from_mode != to_mode)
         && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
@@ -354,7 +373,7 @@ find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode,
    of logical operations, but not right shifts.  */
 
 static rtx
-widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
+widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
               int unsignedp, int no_extend)
 {
   rtx result;
@@ -368,7 +387,7 @@ widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
      a promoted object differs from our extension.  */
   if (! no_extend
       || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
-         && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
+         && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp)))
     return convert_modes (mode, oldmode, op, unsignedp);
 
   /* If MODE is no wider than a single word, we return a lowpart or paradoxical
@@ -505,19 +524,15 @@ optab_for_tree_code (enum tree_code code, const_tree type,
       return fma_optab;
 
     case REDUC_MAX_EXPR:
-      return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab;
+      return TYPE_UNSIGNED (type)
+            ? reduc_umax_scal_optab : reduc_smax_scal_optab;
 
     case REDUC_MIN_EXPR:
-      return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab;
+      return TYPE_UNSIGNED (type)
+            ? reduc_umin_scal_optab : reduc_smin_scal_optab;
 
     case REDUC_PLUS_EXPR:
-      return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
-
-    case VEC_LSHIFT_EXPR:
-      return vec_shl_optab;
-
-    case VEC_RSHIFT_EXPR:
-      return vec_shr_optab;
+      return reduc_plus_scal_optab;
 
     case VEC_WIDEN_MULT_HI_EXPR:
       return TYPE_UNSIGNED (type) ?
@@ -607,7 +622,26 @@ optab_for_tree_code (enum tree_code code, const_tree type,
       return unknown_optab;
     }
 }
-\f
+
+/* 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.
 
@@ -635,7 +669,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
 {
   struct expand_operand eops[4];
   tree oprnd0, oprnd1, oprnd2;
-  enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
+  machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode;
   optab widen_pattern_optab;
   enum insn_code icode;
   int nops = TREE_CODE_LENGTH (ops->code);
@@ -694,7 +728,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
    this may or may not be TARGET.  */
 
 rtx
-expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
+expand_ternary_op (machine_mode mode, optab ternary_optab, rtx op0,
                   rtx op1, rtx op2, rtx target, int unsignedp)
 {
   struct expand_operand ops[4];
@@ -716,7 +750,7 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0,
    otherwise the same as for expand_binop.  */
 
 rtx
-simplify_expand_binop (enum machine_mode mode, optab binoptab,
+simplify_expand_binop (machine_mode mode, optab binoptab,
                       rtx op0, rtx op1, rtx target, int unsignedp,
                       enum optab_methods methods)
 {
@@ -735,7 +769,7 @@ simplify_expand_binop (enum machine_mode mode, optab binoptab,
    Return true if the expansion succeeded.  */
 
 bool
-force_expand_binop (enum machine_mode mode, optab binoptab,
+force_expand_binop (machine_mode mode, optab binoptab,
                    rtx op0, rtx op1, rtx target, int unsignedp,
                    enum optab_methods methods)
 {
@@ -748,51 +782,12 @@ force_expand_binop (enum machine_mode mode, optab binoptab,
   return true;
 }
 
-/* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR.  */
-
-rtx
-expand_vec_shift_expr (sepops ops, rtx target)
-{
-  struct expand_operand eops[3];
-  enum insn_code icode;
-  rtx rtx_op1, rtx_op2;
-  enum machine_mode mode = TYPE_MODE (ops->type);
-  tree vec_oprnd = ops->op0;
-  tree shift_oprnd = ops->op1;
-  optab shift_optab;
-
-  switch (ops->code)
-    {
-      case VEC_RSHIFT_EXPR:
-       shift_optab = vec_shr_optab;
-       break;
-      case VEC_LSHIFT_EXPR:
-       shift_optab = vec_shl_optab;
-       break;
-      default:
-       gcc_unreachable ();
-    }
-
-  icode = optab_handler (shift_optab, mode);
-  gcc_assert (icode != CODE_FOR_nothing);
-
-  rtx_op1 = expand_normal (vec_oprnd);
-  rtx_op2 = expand_normal (shift_oprnd);
-
-  create_output_operand (&eops[0], target, mode);
-  create_input_operand (&eops[1], rtx_op1, GET_MODE (rtx_op1));
-  create_convert_operand_from_type (&eops[2], rtx_op2, TREE_TYPE (shift_oprnd));
-  expand_insn (icode, 3, eops);
-
-  return eops[0].value;
-}
-
 /* Create a new vector value in VMODE with all elements set to OP.  The
    mode of OP must be the element mode of VMODE.  If OP is a constant,
    then the return value will be a constant.  */
 
 static rtx
-expand_vector_broadcast (enum machine_mode vmode, rtx op)
+expand_vector_broadcast (machine_mode vmode, rtx op)
 {
   enum insn_code icode;
   rtvec vec;
@@ -858,7 +853,7 @@ expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
    value are the same as for the parent routine.  */
 
 static bool
-expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
+expand_subword_shift (machine_mode op1_mode, optab binoptab,
                      rtx outof_input, rtx into_input, rtx op1,
                      rtx outof_target, rtx into_target,
                      int unsignedp, enum optab_methods methods,
@@ -934,7 +929,6 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
 }
 
 
-#ifdef HAVE_conditional_move
 /* Try implementing expand_doubleword_shift using conditional moves.
    The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true,
    otherwise it is by >= BITS_PER_WORD.  SUBWORD_OP1 and SUPERWORD_OP1
@@ -942,7 +936,7 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab,
    arguments are the same as the parent routine.  */
 
 static bool
-expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
+expand_doubleword_shift_condmove (machine_mode op1_mode, optab binoptab,
                                  enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
                                  rtx outof_input, rtx into_input,
                                  rtx subword_op1, rtx superword_op1,
@@ -994,7 +988,6 @@ expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
 
   return true;
 }
-#endif
 
 /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts.
    OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first
@@ -1026,14 +1019,13 @@ expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab,
    Return true if the shift could be successfully synthesized.  */
 
 static bool
-expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
+expand_doubleword_shift (machine_mode op1_mode, optab binoptab,
                         rtx outof_input, rtx into_input, rtx op1,
                         rtx outof_target, rtx into_target,
                         int unsignedp, enum optab_methods methods,
                         unsigned HOST_WIDE_INT shift_mask)
 {
   rtx superword_op1, tmp, cmp1, cmp2;
-  rtx subword_label, done_label;
   enum rtx_code cmp_code;
 
   /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will
@@ -1102,24 +1094,23 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
                                     unsignedp, methods, shift_mask);
     }
 
-#ifdef HAVE_conditional_move
   /* Try using conditional moves to generate straight-line code.  */
-  {
-    rtx start = get_last_insn ();
-    if (expand_doubleword_shift_condmove (op1_mode, binoptab,
-                                         cmp_code, cmp1, cmp2,
-                                         outof_input, into_input,
-                                         op1, superword_op1,
-                                         outof_target, into_target,
-                                         unsignedp, methods, shift_mask))
-      return true;
-    delete_insns_since (start);
-  }
-#endif
+  if (HAVE_conditional_move)
+    {
+      rtx_insn *start = get_last_insn ();
+      if (expand_doubleword_shift_condmove (op1_mode, binoptab,
+                                           cmp_code, cmp1, cmp2,
+                                           outof_input, into_input,
+                                           op1, superword_op1,
+                                           outof_target, into_target,
+                                           unsignedp, methods, shift_mask))
+       return true;
+      delete_insns_since (start);
+    }
 
   /* As a last resort, use branches to select the correct alternative.  */
-  subword_label = gen_label_rtx ();
-  done_label = gen_label_rtx ();
+  rtx_code_label *subword_label = gen_label_rtx ();
+  rtx_code_label *done_label = gen_label_rtx ();
 
   NO_DEFER_POP;
   do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
@@ -1201,7 +1192,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab,
       the 0 or -1.  */
 
 static rtx
-expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_doubleword_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
                       bool umulp, enum optab_methods methods)
 {
   int low = (WORDS_BIG_ENDIAN ? 1 : 0);
@@ -1309,7 +1300,7 @@ expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
    the operation to perform, not an optab pointer.  All other
    arguments are the same.  */
 rtx
-expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
+expand_simple_binop (machine_mode mode, enum rtx_code code, rtx op0,
                     rtx op1, rtx target, int unsignedp,
                     enum optab_methods methods)
 {
@@ -1381,7 +1372,7 @@ commutative_optab_p (optab binoptab)
    register.  Return X otherwise.  UNSIGNEDP says whether X is unsigned.  */
 
 static rtx
-avoid_expensive_constant (enum machine_mode mode, optab binoptab,
+avoid_expensive_constant (machine_mode mode, optab binoptab,
                          int opn, rtx x, bool unsignedp)
 {
   bool speed = optimize_insn_for_speed_p ();
@@ -1409,22 +1400,21 @@ avoid_expensive_constant (enum machine_mode mode, optab binoptab,
    is an insn that directly implements the indicated operation.
    Returns null if this is not possible.  */
 static rtx
-expand_binop_directly (enum machine_mode mode, optab binoptab,
+expand_binop_directly (machine_mode mode, optab binoptab,
                       rtx op0, rtx op1,
                       rtx target, int unsignedp, enum optab_methods methods,
-                      rtx last)
+                      rtx_insn *last)
 {
-  enum machine_mode from_mode = widened_mode (mode, op0, op1);
+  machine_mode from_mode = widened_mode (mode, op0, op1);
   enum insn_code icode = find_widening_optab_handler (binoptab, mode,
                                                      from_mode, 1);
-  enum machine_mode xmode0 = insn_data[(int) icode].operand[1].mode;
-  enum machine_mode xmode1 = insn_data[(int) icode].operand[2].mode;
-  enum machine_mode mode0, mode1, tmp_mode;
+  machine_mode xmode0 = insn_data[(int) icode].operand[1].mode;
+  machine_mode xmode1 = insn_data[(int) icode].operand[2].mode;
+  machine_mode mode0, mode1, tmp_mode;
   struct expand_operand ops[3];
   bool commutative_p;
-  rtx pat;
+  rtx_insn *pat;
   rtx xop0 = op0, xop1 = op1;
-  rtx swap;
 
   /* If it is a commutative operator and the modes would match
      if we would swap the operands, we can save the conversions.  */
@@ -1432,11 +1422,7 @@ expand_binop_directly (enum machine_mode mode, optab binoptab,
   if (commutative_p
       && GET_MODE (xop0) != xmode0 && GET_MODE (xop1) != xmode1
       && GET_MODE (xop0) == xmode1 && GET_MODE (xop1) == xmode1)
-    {
-      swap = xop0;
-      xop0 = xop1;
-      xop1 = swap;
-    }
+    std::swap (xop0, xop1);
 
   /* If we are optimizing, force expensive constants into a register.  */
   xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp);
@@ -1469,11 +1455,7 @@ expand_binop_directly (enum machine_mode mode, optab binoptab,
      Also try to make the last operand a constant.  */
   if (commutative_p
       && swap_commutative_operands_with_target (target, xop0, xop1))
-    {
-      swap = xop1;
-      xop1 = xop0;
-      xop0 = swap;
-    }
+    std::swap (xop0, xop1);
 
   /* Now, if insn's predicates don't allow our operands, put them into
      pseudo regs.  */
@@ -1506,7 +1488,8 @@ expand_binop_directly (enum machine_mode mode, optab binoptab,
         REG_EQUAL note to it.  If we can't because TEMP conflicts with an
         operand, call expand_binop again, this time without a target.  */
       if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-         && ! add_equal_note (pat, ops[0].value, optab_to_code (binoptab),
+         && ! add_equal_note (pat, ops[0].value,
+                              optab_to_code (binoptab),
                               ops[1].value, ops[2].value))
        {
          delete_insns_since (last);
@@ -1533,18 +1516,18 @@ expand_binop_directly (enum machine_mode mode, optab binoptab,
    this may or may not be TARGET.  */
 
 rtx
-expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
+expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
              rtx target, int unsignedp, enum optab_methods methods)
 {
   enum optab_methods next_methods
     = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
        ? OPTAB_WIDEN : methods);
   enum mode_class mclass;
-  enum machine_mode wider_mode;
+  machine_mode wider_mode;
   rtx libfunc;
   rtx temp;
-  rtx entry_last = get_last_insn ();
-  rtx last;
+  rtx_insn *entry_last = get_last_insn ();
+  rtx_insn *last;
 
   mclass = GET_MODE_CLASS (mode);
 
@@ -1727,11 +1710,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
      Also try to make the last operand a constant.  */
   if (commutative_optab_p (binoptab)
       && swap_commutative_operands_with_target (target, op0, op1))
-    {
-      temp = op1;
-      op1 = op0;
-      op0 = temp;
-    }
+    std::swap (op0, op1);
 
   /* These can be done a word at a time.  */
   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
@@ -1740,7 +1719,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
     {
       int i;
-      rtx insns;
+      rtx_insn *insns;
 
       /* If TARGET is the same as one of the operands, the REG_EQUAL note
         won't be accurate, so use a new target.  */
@@ -1790,7 +1769,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
     {
       unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
-      enum machine_mode op1_mode;
+      machine_mode op1_mode;
 
       double_shift_mask = targetm.shift_truncation_mask (mode);
       shift_mask = targetm.shift_truncation_mask (word_mode);
@@ -1809,7 +1788,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
          || (shift_mask == BITS_PER_WORD - 1
              && double_shift_mask == BITS_PER_WORD * 2 - 1))
        {
-         rtx insns;
+         rtx_insn *insns;
          rtx into_target, outof_target;
          rtx into_input, outof_input;
          int left_shift, outof_word;
@@ -1861,7 +1840,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
       && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
     {
-      rtx insns;
+      rtx_insn *insns;
       rtx into_target, outof_target;
       rtx into_input, outof_input;
       rtx inter;
@@ -2146,9 +2125,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
   if (libfunc
       && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
     {
-      rtx insns;
+      rtx_insn *insns;
       rtx op1x = op1;
-      enum machine_mode op1_mode = mode;
+      machine_mode op1_mode = mode;
       rtx value;
 
       start_sequence ();
@@ -2268,7 +2247,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
    of an unsigned wider operation, since the result would be the same.  */
 
 rtx
-sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
+sign_expand_binop (machine_mode mode, optab uoptab, optab soptab,
                   rtx op0, rtx op1, rtx target, int unsignedp,
                   enum optab_methods methods)
 {
@@ -2331,11 +2310,11 @@ int
 expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
                    int unsignedp)
 {
-  enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
+  machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
   enum mode_class mclass;
-  enum machine_mode wider_mode;
-  rtx entry_last = get_last_insn ();
-  rtx last;
+  machine_mode wider_mode;
+  rtx_insn *entry_last = get_last_insn ();
+  rtx_insn *last;
 
   mclass = GET_MODE_CLASS (mode);
 
@@ -2405,11 +2384,11 @@ int
 expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
                     int unsignedp)
 {
-  enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
+  machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
   enum mode_class mclass;
-  enum machine_mode wider_mode;
-  rtx entry_last = get_last_insn ();
-  rtx last;
+  machine_mode wider_mode;
+  rtx_insn *entry_last = get_last_insn ();
+  rtx_insn *last;
 
   mclass = GET_MODE_CLASS (mode);
 
@@ -2425,8 +2404,8 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
     {
       struct expand_operand ops[4];
       enum insn_code icode = optab_handler (binoptab, mode);
-      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-      enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+      machine_mode mode0 = insn_data[icode].operand[1].mode;
+      machine_mode mode1 = insn_data[icode].operand[2].mode;
       rtx xop0 = op0, xop1 = op1;
 
       /* If we are optimizing, force expensive constants into a register.  */
@@ -2487,10 +2466,10 @@ bool
 expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
                             rtx targ0, rtx targ1, enum rtx_code code)
 {
-  enum machine_mode mode;
-  enum machine_mode libval_mode;
+  machine_mode mode;
+  machine_mode libval_mode;
   rtx libval;
-  rtx insns;
+  rtx_insn *insns;
   rtx libfunc;
 
   /* Exactly one of TARG0 or TARG1 should be non-NULL.  */
@@ -2527,7 +2506,7 @@ expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
    the operation to perform, not an optab pointer.  All other
    arguments are the same.  */
 rtx
-expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
+expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0,
                    rtx target, int unsignedp)
 {
   optab unop = code_to_optab (code);
@@ -2544,19 +2523,20 @@ expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
    A similar operation can be used for clrsb.  UNOPTAB says which operation
    we are trying to expand.  */
 static rtx
-widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab)
+widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      enum machine_mode wider_mode;
+      machine_mode wider_mode;
       for (wider_mode = GET_MODE_WIDER_MODE (mode);
           wider_mode != VOIDmode;
           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
        {
          if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
            {
-             rtx xop0, temp, last;
+             rtx xop0, temp;
+             rtx_insn *last;
 
              last = get_last_insn ();
 
@@ -2586,14 +2566,15 @@ widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab)
 /* Try calculating clz of a double-word quantity as two clz's of word-sized
    quantities, choosing which based on whether the high word is nonzero.  */
 static rtx
-expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
+expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
 {
   rtx xop0 = force_reg (mode, op0);
   rtx subhi = gen_highpart (word_mode, xop0);
   rtx sublo = gen_lowpart (word_mode, xop0);
-  rtx hi0_label = gen_label_rtx ();
-  rtx after_label = gen_label_rtx ();
-  rtx seq, temp, result;
+  rtx_code_label *hi0_label = gen_label_rtx ();
+  rtx_code_label *after_label = gen_label_rtx ();
+  rtx_insn *seq;
+  rtx temp, result;
 
   /* If we were not given a target, use a word_mode register, not a
      'mode' register.  The result will fit, and nobody is expecting
@@ -2658,11 +2639,12 @@ expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target)
    as
        (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))).  */
 static rtx
-widen_bswap (enum machine_mode mode, rtx op0, rtx target)
+widen_bswap (machine_mode mode, rtx op0, rtx target)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
-  enum machine_mode wider_mode;
-  rtx x, last;
+  machine_mode wider_mode;
+  rtx x;
+  rtx_insn *last;
 
   if (!CLASS_HAS_WIDER_MODES_P (mclass))
     return NULL_RTX;
@@ -2703,7 +2685,7 @@ widen_bswap (enum machine_mode mode, rtx op0, rtx target)
 /* Try calculating bswap as two bswaps of two word-sized operands.  */
 
 static rtx
-expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
+expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)
 {
   rtx t0, t1;
 
@@ -2725,18 +2707,19 @@ expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
 /* Try calculating (parity x) as (and (popcount x) 1), where
    popcount can also be done in a wider mode.  */
 static rtx
-expand_parity (enum machine_mode mode, rtx op0, rtx target)
+expand_parity (machine_mode mode, rtx op0, rtx target)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      enum machine_mode wider_mode;
+      machine_mode wider_mode;
       for (wider_mode = mode; wider_mode != VOIDmode;
           wider_mode = GET_MODE_WIDER_MODE (wider_mode))
        {
          if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
            {
-             rtx xop0, temp, last;
+             rtx xop0, temp;
+             rtx_insn *last;
 
              last = get_last_insn ();
 
@@ -2771,9 +2754,10 @@ expand_parity (enum machine_mode mode, rtx op0, rtx target)
    less convenient for expand_ffs anyway.  */
 
 static rtx
-expand_ctz (enum machine_mode mode, rtx op0, rtx target)
+expand_ctz (machine_mode mode, rtx op0, rtx target)
 {
-  rtx seq, temp;
+  rtx_insn *seq;
+  rtx temp;
 
   if (optab_handler (clz_optab, mode) == CODE_FOR_nothing)
     return 0;
@@ -2813,11 +2797,12 @@ expand_ctz (enum machine_mode mode, rtx op0, rtx target)
    may have an undefined value in that case.  If they do not give us a
    convenient value, we have to generate a test and branch.  */
 static rtx
-expand_ffs (enum machine_mode mode, rtx op0, rtx target)
+expand_ffs (machine_mode mode, rtx op0, rtx target)
 {
   HOST_WIDE_INT val = 0;
   bool defined_at_zero = false;
-  rtx temp, seq;
+  rtx temp;
+  rtx_insn *seq;
 
   if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing)
     {
@@ -2859,7 +2844,7 @@ expand_ffs (enum machine_mode mode, rtx op0, rtx target)
         the operation sets condition codes that can be recycled for this.
         (This is true on i386, for instance.)  */
 
-      rtx nonzero_label = gen_label_rtx ();
+      rtx_code_label *nonzero_label = gen_label_rtx ();
       emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0,
                               mode, true, nonzero_label);
 
@@ -2892,8 +2877,8 @@ expand_ffs (enum machine_mode mode, rtx op0, rtx target)
    register will work around the situation.  */
 
 static rtx
-lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
-                          enum machine_mode imode)
+lowpart_subreg_maybe_copy (machine_mode omode, rtx val,
+                          machine_mode imode)
 {
   rtx ret;
   ret = lowpart_subreg (omode, val, imode);
@@ -2910,13 +2895,14 @@ lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
    logical operation on the sign bit.  */
 
 static rtx
-expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
+expand_absneg_bit (enum rtx_code code, machine_mode mode,
                   rtx op0, rtx target)
 {
   const struct real_format *fmt;
   int bitpos, word, nwords, i;
-  enum machine_mode imode;
-  rtx temp, insns;
+  machine_mode imode;
+  rtx temp;
+  rtx_insn *insns;
 
   /* The format has to have a simple sign bit.  */
   fmt = REAL_MODE_FORMAT (mode);
@@ -3006,15 +2992,15 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
 /* As expand_unop, but will fail rather than attempt the operation in a
    different mode or with a libcall.  */
 static rtx
-expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
+expand_unop_direct (machine_mode mode, optab unoptab, rtx op0, rtx target,
             int unsignedp)
 {
   if (optab_handler (unoptab, mode) != CODE_FOR_nothing)
     {
       struct expand_operand ops[2];
       enum insn_code icode = optab_handler (unoptab, mode);
-      rtx last = get_last_insn ();
-      rtx pat;
+      rtx_insn *last = get_last_insn ();
+      rtx_insn *pat;
 
       create_output_operand (&ops[0], target, mode);
       create_convert_operand_from (&ops[1], op0, mode, unsignedp);
@@ -3022,7 +3008,8 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       if (pat)
        {
          if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-             && ! add_equal_note (pat, ops[0].value, optab_to_code (unoptab),
+             && ! add_equal_note (pat, ops[0].value,
+                                  optab_to_code (unoptab),
                                   ops[1].value, NULL_RTX))
            {
              delete_insns_since (last);
@@ -3049,11 +3036,11 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
    this may or may not be TARGET.  */
 
 rtx
-expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
+expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
             int unsignedp)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
-  enum machine_mode wider_mode;
+  machine_mode wider_mode;
   rtx temp;
   rtx libfunc;
 
@@ -3098,7 +3085,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
         be always more efficient than the other fallback methods.  */
       if (mode == HImode)
        {
-         rtx last, temp1, temp2;
+         rtx_insn *last;
+         rtx temp1, temp2;
 
          if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing)
            {
@@ -3156,7 +3144,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
        if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
          {
            rtx xop0 = op0;
-           rtx last = get_last_insn ();
+           rtx_insn *last = get_last_insn ();
 
            /* For certain operations, we need not actually extend
               the narrow operand, as long as we will truncate the
@@ -3195,7 +3183,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
       && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
     {
       int i;
-      rtx insns;
+      rtx_insn *insns;
 
       if (target == 0 || target == op0 || !valid_multiword_target_p (target))
        target = gen_reg_rtx (mode);
@@ -3273,10 +3261,10 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
   libfunc = optab_libfunc (unoptab, mode);
   if (libfunc)
     {
-      rtx insns;
+      rtx_insn *insns;
       rtx value;
       rtx eq_value;
-      enum machine_mode outmode = mode;
+      machine_mode outmode = mode;
 
       /* All of these functions return small values.  Thus we choose to
         have them return something that isn't a double-word.  */
@@ -3320,7 +3308,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
              || optab_libfunc (unoptab, wider_mode))
            {
              rtx xop0 = op0;
-             rtx last = get_last_insn ();
+             rtx_insn *last = get_last_insn ();
 
              /* For certain operations, we need not actually extend
                 the narrow operand, as long as we will truncate the
@@ -3403,7 +3391,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
  */
 
 rtx
-expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
+expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
                   int result_unsignedp)
 {
   rtx temp;
@@ -3430,7 +3418,7 @@ expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
   if (optab_handler (smax_optab, mode) != CODE_FOR_nothing
       && !HONOR_SIGNED_ZEROS (mode))
     {
-      rtx last = get_last_insn ();
+      rtx_insn *last = get_last_insn ();
 
       temp = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
                          op0, NULL_RTX, 0);
@@ -3470,10 +3458,11 @@ expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
 }
 
 rtx
-expand_abs (enum machine_mode mode, rtx op0, rtx target,
+expand_abs (machine_mode mode, rtx op0, rtx target,
            int result_unsignedp, int safe)
 {
-  rtx temp, op1;
+  rtx temp;
+  rtx_code_label *op1;
 
   if (GET_MODE_CLASS (mode) != MODE_INT
       || ! flag_trapv)
@@ -3503,7 +3492,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
   NO_DEFER_POP;
 
   do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
-                          NULL_RTX, NULL_RTX, op1, -1);
+                          NULL_RTX, NULL, op1, -1);
 
   op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
                      target, target, 0);
@@ -3523,7 +3512,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
    different but can be deduced from MODE.  */
 
 rtx
-expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
+expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
 {
   rtx temp;
 
@@ -3534,7 +3523,7 @@ expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
   /* If we have a MAX insn, we can do this as MAX (x, ~x).  */
   if (optab_handler (smax_optab, mode) != CODE_FOR_nothing)
     {
-      rtx last = get_last_insn ();
+      rtx_insn *last = get_last_insn ();
 
       temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
       if (temp != 0)
@@ -3574,12 +3563,13 @@ expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
    and not playing with subregs so much, will help the register allocator.  */
 
 static rtx
-expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
                        int bitpos, bool op0_is_abs)
 {
-  enum machine_mode imode;
+  machine_mode imode;
   enum insn_code icode;
-  rtx sign, label;
+  rtx sign;
+  rtx_code_label *label;
 
   if (target == op1)
     target = NULL_RTX;
@@ -3657,12 +3647,13 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
    is true if op0 is known to have its sign bit clear.  */
 
 static rtx
-expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
                     int bitpos, bool op0_is_abs)
 {
-  enum machine_mode imode;
+  machine_mode imode;
   int word, nwords, i;
-  rtx temp, insns;
+  rtx temp;
+  rtx_insn *insns;
 
   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
     {
@@ -3754,7 +3745,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
 rtx
 expand_copysign (rtx op0, rtx op1, rtx target)
 {
-  enum machine_mode mode = GET_MODE (op0);
+  machine_mode mode = GET_MODE (op0);
   const struct real_format *fmt;
   bool op0_is_abs;
   rtx temp;
@@ -3810,7 +3801,7 @@ maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0,
                      enum rtx_code code)
 {
   struct expand_operand ops[2];
-  rtx pat;
+  rtx_insn *pat;
 
   create_output_operand (&ops[0], target, GET_MODE (target));
   create_input_operand (&ops[1], op0, GET_MODE (op0));
@@ -3818,7 +3809,8 @@ maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0,
   if (!pat)
     return false;
 
-  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
+  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
+      && code != UNKNOWN)
     add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX);
 
   emit_insn (pat);
@@ -3842,7 +3834,8 @@ emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code)
 \f
 struct no_conflict_data
 {
-  rtx target, first, insn;
+  rtx target;
+  rtx_insn *first, *insn;
   bool must_stay;
 };
 
@@ -3894,11 +3887,11 @@ no_conflict_move_test (rtx dest, const_rtx set, void *p0)
    note with an operand of EQUIV.  */
 
 static void
-emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv,
+emit_libcall_block_1 (rtx_insn *insns, rtx target, rtx result, rtx equiv,
                      bool equiv_may_trap)
 {
   rtx final_dest = target;
-  rtx next, last, insn;
+  rtx_insn *next, *last, *insn;
 
   /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
      into a MEM later.  Protect the libcall block from this change.  */
@@ -3959,12 +3952,12 @@ emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv,
          if (! data.must_stay)
            {
              if (PREV_INSN (insn))
-               NEXT_INSN (PREV_INSN (insn)) = next;
+               SET_NEXT_INSN (PREV_INSN (insn)) = next;
              else
                insns = next;
 
              if (next)
-               PREV_INSN (next) = PREV_INSN (insn);
+               SET_PREV_INSN (next) = PREV_INSN (insn);
 
              add_insn (insn);
            }
@@ -3994,7 +3987,8 @@ emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv,
 void
 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
 {
-  emit_libcall_block_1 (insns, target, result, equiv, false);
+  emit_libcall_block_1 (safe_as_a <rtx_insn *> (insns),
+                       target, result, equiv, false);
 }
 \f
 /* Nonzero if we can perform a comparison of mode MODE straightforwardly.
@@ -4006,7 +4000,7 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
    required to implement all (or any) of the unordered bcc operations.  */
 
 int
-can_compare_p (enum rtx_code code, enum machine_mode mode,
+can_compare_p (enum rtx_code code, machine_mode mode,
               enum can_compare_purpose purpose)
 {
   rtx test;
@@ -4055,11 +4049,11 @@ can_compare_p (enum rtx_code code, enum machine_mode mode,
 static void
 prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
                  int unsignedp, enum optab_methods methods,
-                 rtx *ptest, enum machine_mode *pmode)
+                 rtx *ptest, machine_mode *pmode)
 {
-  enum machine_mode mode = *pmode;
+  machine_mode mode = *pmode;
   rtx libfunc, test;
-  enum machine_mode cmp_mode;
+  machine_mode cmp_mode;
   enum mode_class mclass;
 
   /* The other methods are not needed.  */
@@ -4077,7 +4071,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
           > COSTS_N_INSNS (1)))
     y = force_reg (mode, y);
 
-#ifdef HAVE_cc0
+#if HAVE_cc0
   /* Make sure if we have a canonical comparison.  The RTL
      documentation states that canonical comparisons are required only
      for targets which have cc0.  */
@@ -4094,7 +4088,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
   if (mode == BLKmode)
     {
-      enum machine_mode result_mode;
+      machine_mode result_mode;
       enum insn_code cmp_code;
       tree length_type;
       rtx libfunc;
@@ -4170,8 +4164,11 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
   if (GET_MODE_CLASS (mode) == MODE_CC)
     {
-      gcc_assert (can_compare_p (comparison, CCmode, ccp_jump));
-      *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
+      enum insn_code icode = optab_handler (cbranch_optab, CCmode);
+      test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
+      gcc_assert (icode != CODE_FOR_nothing
+                  && insn_operand_matches (icode, 0, test));
+      *ptest = test;
       return;
     }
 
@@ -4185,7 +4182,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
       if (icode != CODE_FOR_nothing
          && insn_operand_matches (icode, 0, test))
        {
-         rtx last = get_last_insn ();
+         rtx_insn *last = get_last_insn ();
          rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp);
          rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp);
          if (op0 && op1
@@ -4213,7 +4210,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
   if (!SCALAR_FLOAT_MODE_P (mode))
     {
       rtx result;
-      enum machine_mode ret_mode;
+      machine_mode ret_mode;
 
       /* Handle a libcall just for the mode we are using.  */
       libfunc = optab_libfunc (cmp_optab, mode);
@@ -4253,7 +4250,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
            y = const0_rtx;
        }
 
-      *pmode = word_mode;
+      *pmode = ret_mode;
       prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods,
                        ptest, pmode);
     }
@@ -4272,17 +4269,20 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
    that it is accepted by the operand predicate.  Return the new value.  */
 
 rtx
-prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode,
-                enum machine_mode wider_mode, int unsignedp)
+prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode,
+                machine_mode wider_mode, int unsignedp)
 {
   if (mode != wider_mode)
     x = convert_modes (wider_mode, mode, x, unsignedp);
 
   if (!insn_operand_matches (icode, opnum, x))
     {
+      machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode;
       if (reload_completed)
        return NULL_RTX;
-      x = copy_to_mode_reg (insn_data[(int) icode].operand[opnum].mode, x);
+      if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode)
+       return NULL_RTX;
+      x = copy_to_mode_reg (op_mode, x);
     }
 
   return x;
@@ -4292,12 +4292,12 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode,
    we can do the branch.  */
 
 static void
-emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob)
+emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
 {
-  enum machine_mode optab_mode;
+  machine_mode optab_mode;
   enum mode_class mclass;
   enum insn_code icode;
-  rtx insn;
+  rtx_insn *insn;
 
   mclass = GET_MODE_CLASS (mode);
   optab_mode = (mclass == MODE_CC) ? CCmode : mode;
@@ -4337,7 +4337,7 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob)
 
 void
 emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
-                        enum machine_mode mode, int unsignedp, rtx label,
+                        machine_mode mode, int unsignedp, rtx label,
                          int prob)
 {
   rtx op0 = x, op1 = y;
@@ -4371,14 +4371,15 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
 static void
 prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
-                      rtx *ptest, enum machine_mode *pmode)
+                      rtx *ptest, machine_mode *pmode)
 {
   enum rtx_code swapped = swap_condition (comparison);
   enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
-  enum machine_mode orig_mode = GET_MODE (x);
-  enum machine_mode mode, cmp_mode;
+  machine_mode orig_mode = GET_MODE (x);
+  machine_mode mode, cmp_mode;
   rtx true_rtx, false_rtx;
-  rtx value, target, insns, equiv;
+  rtx value, target, equiv;
+  rtx_insn *insns;
   rtx libfunc = 0;
   bool reversed_p = false;
   cmp_mode = targetm.libgcc_cmp_return_mode ();
@@ -4502,16 +4503,18 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
 
 void
-emit_indirect_jump (rtx loc)
+emit_indirect_jump (rtx loc ATTRIBUTE_UNUSED)
 {
+#ifndef HAVE_indirect_jump
+  sorry ("indirect jumps are not available on this target");
+#else
   struct expand_operand ops[1];
-
   create_address_operand (&ops[0], loc);
   expand_jump_insn (CODE_FOR_indirect_jump, 1, ops);
   emit_barrier ();
+#endif
 }
 \f
-#ifdef HAVE_conditional_move
 
 /* Emit a conditional move instruction if the machine supports one for that
    condition and machine mode.
@@ -4529,10 +4532,11 @@ emit_indirect_jump (rtx loc)
 
 rtx
 emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
-                      enum machine_mode cmode, rtx op2, rtx op3,
-                      enum machine_mode mode, int unsignedp)
+                      machine_mode cmode, rtx op2, rtx op3,
+                      machine_mode mode, int unsignedp)
 {
-  rtx tem, comparison, last;
+  rtx comparison;
+  rtx_insn *last;
   enum insn_code icode;
   enum rtx_code reversed;
 
@@ -4541,9 +4545,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
   if (swap_commutative_operands_p (op0, op1))
     {
-      tem = op0;
-      op0 = op1;
-      op1 = tem;
+      std::swap (op0, op1);
       code = swap_condition (code);
     }
 
@@ -4562,9 +4564,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
       && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
           != UNKNOWN))
     {
-      tem = op2;
-      op2 = op3;
-      op3 = tem;
+      std::swap (op2, op3);
       code = reversed;
     }
 
@@ -4624,7 +4624,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
    comparisons, and vice versa.  How do we handle them?  */
 
 int
-can_conditionally_move_p (enum machine_mode mode)
+can_conditionally_move_p (machine_mode mode)
 {
   if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
     return 1;
@@ -4632,8 +4632,6 @@ can_conditionally_move_p (enum machine_mode mode)
   return 0;
 }
 
-#endif /* HAVE_conditional_move */
-
 /* Emit a conditional addition instruction if the machine supports one for that
    condition and machine mode.
 
@@ -4650,10 +4648,11 @@ can_conditionally_move_p (enum machine_mode mode)
 
 rtx
 emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
-                     enum machine_mode cmode, rtx op2, rtx op3,
-                     enum machine_mode mode, int unsignedp)
+                     machine_mode cmode, rtx op2, rtx op3,
+                     machine_mode mode, int unsignedp)
 {
-  rtx tem, comparison, last;
+  rtx comparison;
+  rtx_insn *last;
   enum insn_code icode;
 
   /* If one operand is constant, make it the second one.  Only do this
@@ -4661,9 +4660,7 @@ emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
   if (swap_commutative_operands_p (op0, op1))
     {
-      tem = op0;
-      op0 = op1;
-      op1 = tem;
+      std::swap (op0, op1);
       code = swap_condition (code);
     }
 
@@ -4864,28 +4861,13 @@ have_sub2_insn (rtx x, rtx y)
 
   return 1;
 }
-
-/* Generate the body of an instruction to copy Y into X.
-   It may be a list of insns, if one insn isn't enough.  */
-
-rtx
-gen_move_insn (rtx x, rtx y)
-{
-  rtx seq;
-
-  start_sequence ();
-  emit_move_insn_1 (x, y);
-  seq = get_insns ();
-  end_sequence ();
-  return seq;
-}
 \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 (enum machine_mode to_mode, enum machine_mode from_mode,
+can_extend_p (machine_mode to_mode, machine_mode from_mode,
              int unsignedp)
 {
   convert_optab tab;
@@ -4902,8 +4884,8 @@ can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
    into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
 
 rtx
-gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
-                enum machine_mode mfrom, int unsignedp)
+gen_extend_insn (rtx x, rtx y, machine_mode mto,
+                machine_mode mfrom, int unsignedp)
 {
   enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
   return GEN_FCN (icode) (x, y);
@@ -4919,7 +4901,7 @@ gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
    an explicit FTRUNC insn before the fix insn; otherwise 0.  */
 
 static enum insn_code
-can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
+can_fix_p (machine_mode fixmode, machine_mode fltmode,
           int unsignedp, int *truncp_ptr)
 {
   convert_optab tab;
@@ -4950,7 +4932,7 @@ can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
 }
 
 enum insn_code
-can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
+can_float_p (machine_mode fltmode, machine_mode fixmode,
             int unsignedp)
 {
   convert_optab tab;
@@ -4983,7 +4965,7 @@ supportable_convert_operation (enum tree_code code,
                                     tree vectype_out, tree vectype_in,
                                     tree *decl, enum tree_code *code1)
 {
-  enum machine_mode m1,m2;
+  machine_mode m1,m2;
   int truncp;
 
   m1 = TYPE_MODE (vectype_out);
@@ -5024,7 +5006,7 @@ expand_float (rtx to, rtx from, int unsignedp)
 {
   enum insn_code icode;
   rtx target = to;
-  enum machine_mode fmode, imode;
+  machine_mode fmode, imode;
   bool can_do_signed = false;
 
   /* Crash now, because we won't be able to decide which mode to use.  */
@@ -5077,7 +5059,7 @@ expand_float (rtx to, rtx from, int unsignedp)
      then unconditionally adjust the result.  */
   if (unsignedp && can_do_signed)
     {
-      rtx label = gen_label_rtx ();
+      rtx_code_label *label = gen_label_rtx ();
       rtx temp;
       REAL_VALUE_TYPE offset;
 
@@ -5101,7 +5083,7 @@ expand_float (rtx to, rtx from, int unsignedp)
              < GET_MODE_PRECISION (GET_MODE (from)))
            {
              rtx temp1;
-             rtx neglabel = gen_label_rtx ();
+             rtx_code_label *neglabel = gen_label_rtx ();
 
              /* Don't use TARGET if it isn't a register, is a hard register,
                 or is the wrong mode.  */
@@ -5180,11 +5162,11 @@ expand_float (rtx to, rtx from, int unsignedp)
   /* No hardware instruction available; call a library routine.  */
     {
       rtx libfunc;
-      rtx insns;
+      rtx_insn *insns;
       rtx value;
       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
-      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
+      if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
        from = convert_to_mode (SImode, from, unsignedp);
 
       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
@@ -5225,7 +5207,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
 {
   enum insn_code icode;
   rtx target = to;
-  enum machine_mode fmode, imode;
+  machine_mode fmode, imode;
   int must_trunc = 0;
 
   /* We first try to find a pair of modes, one real and one integer, at
@@ -5246,7 +5228,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
 
        if (icode != CODE_FOR_nothing)
          {
-           rtx last = get_last_insn ();
+           rtx_insn *last = get_last_insn ();
            if (fmode != GET_MODE (from))
              from = convert_to_mode (fmode, from, 0);
 
@@ -5304,7 +5286,9 @@ expand_fix (rtx to, rtx from, int unsignedp)
        {
          int bitsize;
          REAL_VALUE_TYPE offset;
-         rtx limit, lab1, lab2, insn;
+         rtx limit;
+         rtx_code_label *lab1, *lab2;
+         rtx_insn *insn;
 
          bitsize = GET_MODE_PRECISION (GET_MODE (to));
          real_2expN (&offset, bitsize - 1, fmode);
@@ -5360,7 +5344,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
      that the mode of TO is at least as wide as SImode, since those are the
      only library calls we know about.  */
 
-  if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
+  if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode))
     {
       target = gen_reg_rtx (SImode);
 
@@ -5368,7 +5352,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
     }
   else
     {
-      rtx insns;
+      rtx_insn *insns;
       rtx value;
       rtx libfunc;
 
@@ -5405,12 +5389,13 @@ expand_fix (rtx to, rtx from, int unsignedp)
 void
 expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
 {
-  enum machine_mode to_mode = GET_MODE (to);
-  enum machine_mode from_mode = GET_MODE (from);
+  machine_mode to_mode = GET_MODE (to);
+  machine_mode from_mode = GET_MODE (from);
   convert_optab tab;
   enum rtx_code this_code;
   enum insn_code code;
-  rtx insns, value;
+  rtx_insn *insns;
+  rtx value;
   rtx libfunc;
 
   if (to_mode == from_mode)
@@ -5458,7 +5443,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab)
 {
   enum insn_code icode;
   rtx target = to;
-  enum machine_mode fmode, imode;
+  machine_mode fmode, imode;
 
   /* 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
@@ -5473,7 +5458,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab)
        icode = convert_optab_handler (tab, imode, fmode);
        if (icode != CODE_FOR_nothing)
          {
-           rtx last = get_last_insn ();
+           rtx_insn *last = get_last_insn ();
            if (fmode != GET_MODE (from))
              from = convert_to_mode (fmode, from, 0);
 
@@ -5497,7 +5482,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab)
 /* Report whether we have an instruction to perform the operation
    specified by CODE on operands of mode MODE.  */
 int
-have_insn_for (enum rtx_code code, enum machine_mode mode)
+have_insn_for (enum rtx_code code, machine_mode mode)
 {
   return (code_to_optab (code)
          && (optab_handler (code_to_optab (code), mode)
@@ -5520,7 +5505,7 @@ have_insn_for (enum rtx_code code, enum machine_mode mode)
 
 static void
 gen_libfunc (optab optable, const char *opname, int suffix,
-            enum machine_mode mode)
+            machine_mode mode)
 {
   unsigned opname_len = strlen (opname);
   const char *mname = GET_MODE_NAME (mode);
@@ -5556,16 +5541,20 @@ gen_libfunc (optab optable, const char *opname, int suffix,
 
 void
 gen_int_libfunc (optab optable, const char *opname, char suffix,
-                enum machine_mode mode)
+                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 (GET_MODE_CLASS (mode) != MODE_INT
-      || GET_MODE_BITSIZE (mode) < BITS_PER_WORD
+  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);
@@ -5575,7 +5564,7 @@ gen_int_libfunc (optab optable, const char *opname, char suffix,
 
 void
 gen_fp_libfunc (optab optable, const char *opname, char suffix,
-               enum machine_mode mode)
+               machine_mode mode)
 {
   char *dec_opname;
 
@@ -5596,7 +5585,7 @@ gen_fp_libfunc (optab optable, const char *opname, char suffix,
 
 void
 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
-                  enum machine_mode mode)
+                  machine_mode mode)
 {
   if (!ALL_FIXED_POINT_MODE_P (mode))
     return;
@@ -5608,7 +5597,7 @@ gen_fixed_libfunc (optab optable, const char *opname, char suffix,
 
 void
 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
-                         enum machine_mode mode)
+                         machine_mode mode)
 {
   if (!SIGNED_FIXED_POINT_MODE_P (mode))
     return;
@@ -5620,7 +5609,7 @@ gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
 
 void
 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
-                           enum machine_mode mode)
+                           machine_mode mode)
 {
   if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
     return;
@@ -5631,7 +5620,7 @@ gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
 
 void
 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
-                   enum machine_mode mode)
+                   machine_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     gen_fp_libfunc (optable, name, suffix, mode);
@@ -5644,7 +5633,7 @@ gen_int_fp_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
-                    enum machine_mode mode)
+                    machine_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     gen_fp_libfunc (optable, name, suffix, mode);
@@ -5664,7 +5653,7 @@ gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
-                         enum machine_mode mode)
+                         machine_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     gen_fp_libfunc (optable, name, suffix, mode);
@@ -5679,7 +5668,7 @@ gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
-                                enum machine_mode mode)
+                                machine_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
     gen_fp_libfunc (optable, name, suffix, mode);
@@ -5694,7 +5683,7 @@ gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
-                      enum machine_mode mode)
+                      machine_mode mode)
 {
   if (INTEGRAL_MODE_P (mode))
     gen_int_libfunc (optable, name, suffix, mode);
@@ -5707,7 +5696,7 @@ gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
-                             enum machine_mode mode)
+                             machine_mode mode)
 {
   if (INTEGRAL_MODE_P (mode))
     gen_int_libfunc (optable, name, suffix, mode);
@@ -5720,7 +5709,7 @@ gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
 
 void
 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
-                               enum machine_mode mode)
+                               machine_mode mode)
 {
   if (INTEGRAL_MODE_P (mode))
     gen_int_libfunc (optable, name, suffix, mode);
@@ -5737,8 +5726,8 @@ gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
 void
 gen_interclass_conv_libfunc (convert_optab tab,
                             const char *opname,
-                            enum machine_mode tmode,
-                            enum machine_mode fmode)
+                            machine_mode tmode,
+                            machine_mode fmode)
 {
   size_t opname_len = strlen (opname);
   size_t mname_len = 0;
@@ -5809,8 +5798,8 @@ gen_interclass_conv_libfunc (convert_optab tab,
 void
 gen_int_to_fp_conv_libfunc (convert_optab tab,
                            const char *opname,
-                           enum machine_mode tmode,
-                           enum machine_mode fmode)
+                           machine_mode tmode,
+                           machine_mode fmode)
 {
   if (GET_MODE_CLASS (fmode) != MODE_INT)
     return;
@@ -5825,8 +5814,8 @@ gen_int_to_fp_conv_libfunc (convert_optab tab,
 void
 gen_ufloat_conv_libfunc (convert_optab tab,
                         const char *opname ATTRIBUTE_UNUSED,
-                        enum machine_mode tmode,
-                        enum machine_mode fmode)
+                        machine_mode tmode,
+                        machine_mode fmode)
 {
   if (DECIMAL_FLOAT_MODE_P (tmode))
     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
@@ -5840,8 +5829,8 @@ gen_ufloat_conv_libfunc (convert_optab tab,
 void
 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
                                       const char *opname,
-                                      enum machine_mode tmode,
-                                      enum machine_mode fmode)
+                                      machine_mode tmode,
+                                      machine_mode fmode)
 {
   if (GET_MODE_CLASS (fmode) != MODE_INT)
     return;
@@ -5856,8 +5845,8 @@ gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
 void
 gen_fp_to_int_conv_libfunc (convert_optab tab,
                            const char *opname,
-                           enum machine_mode tmode,
-                           enum machine_mode fmode)
+                           machine_mode tmode,
+                           machine_mode fmode)
 {
   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
     return;
@@ -5872,7 +5861,7 @@ gen_fp_to_int_conv_libfunc (convert_optab tab,
 
 void
 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
-                            enum machine_mode tmode, enum machine_mode fmode)
+                            machine_mode tmode, machine_mode fmode)
 {
   size_t opname_len = strlen (opname);
   size_t mname_len = 0;
@@ -5943,8 +5932,8 @@ gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
 void
 gen_trunc_conv_libfunc (convert_optab tab,
                         const char *opname,
-                        enum machine_mode tmode,
-                        enum machine_mode fmode)
+                        machine_mode tmode,
+                        machine_mode fmode)
 {
   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
     return;
@@ -5972,8 +5961,8 @@ gen_trunc_conv_libfunc (convert_optab tab,
 void
 gen_extend_conv_libfunc (convert_optab tab,
                         const char *opname ATTRIBUTE_UNUSED,
-                        enum machine_mode tmode,
-                        enum machine_mode fmode)
+                        machine_mode tmode,
+                        machine_mode fmode)
 {
   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
     return;
@@ -6001,8 +5990,8 @@ gen_extend_conv_libfunc (convert_optab tab,
 void
 gen_fract_conv_libfunc (convert_optab tab,
                        const char *opname,
-                       enum machine_mode tmode,
-                       enum machine_mode fmode)
+                       machine_mode tmode,
+                       machine_mode fmode)
 {
   if (tmode == fmode)
     return;
@@ -6020,8 +6009,8 @@ gen_fract_conv_libfunc (convert_optab tab,
 void
 gen_fractuns_conv_libfunc (convert_optab tab,
                           const char *opname,
-                          enum machine_mode tmode,
-                          enum machine_mode fmode)
+                          machine_mode tmode,
+                          machine_mode fmode)
 {
   if (tmode == fmode)
     return;
@@ -6041,8 +6030,8 @@ gen_fractuns_conv_libfunc (convert_optab tab,
 void
 gen_satfract_conv_libfunc (convert_optab tab,
                           const char *opname,
-                          enum machine_mode tmode,
-                          enum machine_mode fmode)
+                          machine_mode tmode,
+                          machine_mode fmode)
 {
   if (tmode == fmode)
     return;
@@ -6061,8 +6050,8 @@ gen_satfract_conv_libfunc (convert_optab tab,
 void
 gen_satfractuns_conv_libfunc (convert_optab tab,
                              const char *opname,
-                             enum machine_mode tmode,
-                             enum machine_mode fmode)
+                             machine_mode tmode,
+                             machine_mode fmode)
 {
   if (tmode == fmode)
     return;
@@ -6073,22 +6062,25 @@ gen_satfractuns_conv_libfunc (convert_optab tab,
   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
 }
 
-/* A table of previously-created libfuncs, hashed by name.  */
-static GTY ((param_is (union tree_node))) htab_t libfunc_decls;
-
 /* Hashtable callbacks for libfunc_decls.  */
 
-static hashval_t
-libfunc_decl_hash (const void *entry)
+struct libfunc_decl_hasher : ggc_hasher<tree>
 {
-  return IDENTIFIER_HASH_VALUE (DECL_NAME ((const_tree) entry));
-}
+  static hashval_t
+  hash (tree entry)
+  {
+    return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
+  }
 
-static int
-libfunc_decl_eq (const void *entry1, const void *entry2)
-{
-  return DECL_NAME ((const_tree) entry1) == (const_tree) entry2;
-}
+  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. */
 
@@ -6116,18 +6108,16 @@ rtx
 init_one_libfunc (const char *name)
 {
   tree id, decl;
-  void **slot;
   hashval_t hash;
 
   if (libfunc_decls == NULL)
-    libfunc_decls = htab_create_ggc (37, libfunc_decl_hash,
-                                    libfunc_decl_eq, 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);
-  slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT);
-  decl = (tree) *slot;
+  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
@@ -6144,12 +6134,11 @@ rtx
 set_user_assembler_libfunc (const char *name, const char *asmspec)
 {
   tree id, decl;
-  void **slot;
   hashval_t hash;
 
   id = get_identifier (name);
   hash = IDENTIFIER_HASH_VALUE (id);
-  slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT);
+  tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
   gcc_assert (slot);
   decl = (tree) *slot;
   set_user_assembler_name (decl, asmspec);
@@ -6159,7 +6148,7 @@ set_user_assembler_libfunc (const char *name, const char *asmspec)
 /* Call this to reset the function entry for one optab (OPTABLE) in mode
    MODE to NAME, which should be either 0 or a string constant.  */
 void
-set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
+set_optab_libfunc (optab op, machine_mode mode, const char *name)
 {
   rtx val;
   struct libfunc_entry e;
@@ -6173,7 +6162,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
     val = init_one_libfunc (name);
   else
     val = 0;
-  slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
+  slot = libfunc_hash->find_slot (&e, INSERT);
   if (*slot == NULL)
     *slot = ggc_alloc<libfunc_entry> ();
   (*slot)->op = op;
@@ -6186,8 +6175,8 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
    either 0 or a string constant.  */
 void
-set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
-                 enum machine_mode fmode, const char *name)
+set_conv_libfunc (convert_optab optab, machine_mode tmode,
+                 machine_mode fmode, const char *name)
 {
   rtx val;
   struct libfunc_entry e;
@@ -6201,7 +6190,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
     val = init_one_libfunc (name);
   else
     val = 0;
-  slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
+  slot = libfunc_hash->find_slot (&e, INSERT);
   if (*slot == NULL)
     *slot = ggc_alloc<libfunc_entry> ();
   (*slot)->op = optab;
@@ -6217,9 +6206,9 @@ void
 init_optabs (void)
 {
   if (libfunc_hash)
-    htab_empty (libfunc_hash);
+    libfunc_hash->empty ();
   else
-    libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL);
+    libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
 
   /* Fill in the optabs with the insns we support.  */
   init_all_optabs (this_fn_optabs);
@@ -6317,7 +6306,7 @@ init_tree_optimization_optabs (tree optnode)
 static void
 init_sync_libfuncs_1 (optab tab, const char *base, int max)
 {
-  enum machine_mode mode;
+  machine_mode mode;
   char buf[64];
   size_t len = strlen (base);
   int i;
@@ -6377,7 +6366,7 @@ debug_optab_libfuncs (void)
   for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       {
-       rtx l = optab_libfunc ((optab) i, (enum machine_mode) j);
+       rtx l = optab_libfunc ((optab) i, (machine_mode) j);
        if (l)
          {
            gcc_assert (GET_CODE (l) == SYMBOL_REF);
@@ -6393,8 +6382,8 @@ debug_optab_libfuncs (void)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       for (k = 0; k < NUM_MACHINE_MODES; ++k)
        {
-         rtx l = convert_optab_libfunc ((optab) i, (enum machine_mode) j,
-                                        (enum machine_mode) k);
+         rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
+                                        (machine_mode) k);
          if (l)
            {
              gcc_assert (GET_CODE (l) == SYMBOL_REF);
@@ -6414,7 +6403,7 @@ debug_optab_libfuncs (void)
 rtx
 gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
 {
-  enum machine_mode mode = GET_MODE (op1);
+  machine_mode mode = GET_MODE (op1);
   enum insn_code icode;
   rtx insn;
   rtx trap_rtx;
@@ -6456,7 +6445,7 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
 /* Return rtx code for TCODE. Use UNSIGNEDP to select signed
    or unsigned operation code.  */
 
-static enum rtx_code
+enum rtx_code
 get_rtx_code (enum tree_code tcode, bool unsignedp)
 {
   enum rtx_code code;
@@ -6506,6 +6495,14 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
       code = LTGT;
       break;
 
+    case BIT_AND_EXPR:
+      code = AND;
+      break;
+
+    case BIT_IOR_EXPR:
+      code = IOR;
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -6521,31 +6518,44 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
 {
   struct expand_operand ops[2];
   rtx rtx_op0, rtx_op1;
+  machine_mode m0, m1;
   enum rtx_code rcode = get_rtx_code (tcode, unsignedp);
 
   gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison);
 
-  /* Expand operands.  */
+  /* Expand operands.  For vector types with scalar modes, e.g. where int64x1_t
+     has mode DImode, this can produce a constant RTX of mode VOIDmode; in such
+     cases, use the original mode.  */
   rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)),
                         EXPAND_STACK_PARM);
+  m0 = GET_MODE (rtx_op0);
+  if (m0 == VOIDmode)
+    m0 = TYPE_MODE (TREE_TYPE (t_op0));
+
   rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)),
                         EXPAND_STACK_PARM);
+  m1 = GET_MODE (rtx_op1);
+  if (m1 == VOIDmode)
+    m1 = TYPE_MODE (TREE_TYPE (t_op1));
 
-  create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0));
-  create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1));
+  create_input_operand (&ops[0], rtx_op0, m0);
+  create_input_operand (&ops[1], rtx_op1, m1);
   if (!maybe_legitimize_operands (icode, 4, 2, ops))
     gcc_unreachable ();
   return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
 }
 
-/* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions
-   of the CPU.  SEL may be NULL, which stands for an unknown constant.  */
+/* 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 (enum machine_mode mode, bool variable,
+can_vec_perm_p (machine_mode mode, bool variable,
                const unsigned char *sel)
 {
-  enum machine_mode qimode;
+  machine_mode qimode;
 
   /* If the target doesn't implement a vector mode for the vector type,
      then no operations are supported.  */
@@ -6592,14 +6602,42 @@ can_vec_perm_p (enum machine_mode mode, bool variable,
   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
+   shift.  */
+static rtx
+shift_amt_for_vec_perm_mask (rtx sel)
+{
+  unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel));
+  unsigned int bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (sel)));
+
+  if (GET_CODE (sel) != CONST_VECTOR)
+    return NULL_RTX;
+
+  first = INTVAL (CONST_VECTOR_ELT (sel, 0));
+  if (first >= 2*nelt)
+    return NULL_RTX;
+  for (i = 1; i < nelt; i++)
+    {
+      int idx = INTVAL (CONST_VECTOR_ELT (sel, i));
+      unsigned int expected = (i + first) & (2 * nelt - 1);
+      /* Indices into the second vector are all equivalent.  */
+      if (idx < 0 || (MIN (nelt, (unsigned) idx) != MIN (nelt, expected)))
+       return NULL_RTX;
+    }
+
+  return GEN_INT (first * bitsize);
+}
+
 /* A subroutine of expand_vec_perm for expanding one vec_perm insn.  */
 
 static rtx
 expand_vec_perm_1 (enum insn_code icode, rtx target,
                   rtx v0, rtx v1, rtx sel)
 {
-  enum machine_mode tmode = GET_MODE (target);
-  enum machine_mode smode = GET_MODE (sel);
+  machine_mode tmode = GET_MODE (target);
+  machine_mode smode = GET_MODE (sel);
   struct expand_operand ops[4];
 
   create_output_operand (&ops[0], target, tmode);
@@ -6620,6 +6658,17 @@ expand_vec_perm_1 (enum insn_code icode, rtx target,
   else
     {
       create_input_operand (&ops[1], v0, tmode);
+      /* See if this can be handled with a vec_shr.  We only do this if the
+         second vector is all zeroes.  */
+      enum insn_code shift_code = optab_handler (vec_shr_optab, GET_MODE (v0));
+      if (v1 == CONST0_RTX (GET_MODE (v1)) && shift_code)
+       if (rtx shift_amt = shift_amt_for_vec_perm_mask (sel))
+         {
+           create_convert_operand_from_type (&ops[2], shift_amt,
+                                             sizetype_tab[(int) stk_sizetype]);
+           if (maybe_expand_insn (shift_code, 3, ops))
+             return ops[0].value;
+         }
       create_input_operand (&ops[2], v1, tmode);
     }
 
@@ -6632,10 +6681,10 @@ expand_vec_perm_1 (enum insn_code icode, rtx target,
    and three operands.  */
 
 rtx
-expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
+expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
 {
   enum insn_code icode;
-  enum machine_mode qimode;
+  machine_mode qimode;
   unsigned int i, w, e, u;
   rtx tmp, sel_qi = NULL;
   rtvec vec;
@@ -6718,14 +6767,14 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
   if (sel_qi == NULL)
     {
       /* Multiply each element by its byte size.  */
-      enum machine_mode selmode = GET_MODE (sel);
+      machine_mode selmode = GET_MODE (sel);
       if (u == 2)
        sel = expand_simple_binop (selmode, PLUS, sel, sel,
-                                  sel, 0, OPTAB_DIRECT);
+                                  NULL, 0, OPTAB_DIRECT);
       else
        sel = expand_simple_binop (selmode, ASHIFT, sel,
                                   GEN_INT (exact_log2 (u)),
-                                  sel, 0, OPTAB_DIRECT);
+                                  NULL, 0, OPTAB_DIRECT);
       gcc_assert (sel != NULL);
 
       /* Broadcast the low byte each element into each of its bytes.  */
@@ -6766,7 +6815,7 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
    mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE.  */
 
 static inline enum insn_code
-get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
+get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
 {
   enum insn_code icode = CODE_FOR_nothing;
   if (uns)
@@ -6783,8 +6832,8 @@ get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns)
 bool
 expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
 {
-  enum machine_mode value_mode = TYPE_MODE (value_type);
-  enum machine_mode cmp_op_mode = TYPE_MODE (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),
@@ -6803,8 +6852,8 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
   struct expand_operand ops[6];
   enum insn_code icode;
   rtx comparison, rtx_op1, rtx_op2;
-  enum machine_mode mode = TYPE_MODE (vec_cond_type);
-  enum machine_mode cmp_op_mode;
+  machine_mode mode = TYPE_MODE (vec_cond_type);
+  machine_mode cmp_op_mode;
   bool unsignedp;
   tree op0a, op0b;
   enum tree_code tcode;
@@ -6853,7 +6902,7 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
    2 for even/odd widening, and 3 for hi/lo widening.  */
 
 int
-can_mult_highpart_p (enum machine_mode mode, bool uns_p)
+can_mult_highpart_p (machine_mode mode, bool uns_p)
 {
   optab op;
   unsigned char *sel;
@@ -6902,13 +6951,13 @@ can_mult_highpart_p (enum machine_mode mode, bool uns_p)
 /* Expand a highpart multiply.  */
 
 rtx
-expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1,
+expand_mult_highpart (machine_mode mode, rtx op0, rtx op1,
                      rtx target, bool uns_p)
 {
   struct expand_operand eops[3];
   enum insn_code icode;
   int method, i, nunits;
-  enum machine_mode wmode;
+  machine_mode wmode;
   rtx m1, m2, perm;
   optab tab1, tab2;
   rtvec v;
@@ -6977,10 +7026,10 @@ expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1,
 
 /* Return true if target supports vector masked load/store for mode.  */
 bool
-can_vec_mask_load_store_p (enum machine_mode mode, bool is_load)
+can_vec_mask_load_store_p (machine_mode mode, bool is_load)
 {
   optab op = is_load ? maskload_optab : maskstore_optab;
-  enum machine_mode vmode;
+  machine_mode vmode;
   unsigned int vector_sizes;
 
   /* If mode is vector mode, check it directly.  */
@@ -7017,7 +7066,7 @@ can_vec_mask_load_store_p (enum machine_mode mode, bool is_load)
 /* Return true if there is a compare_and_swap pattern.  */
 
 bool
-can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall)
+can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
 {
   enum insn_code icode;
 
@@ -7040,7 +7089,7 @@ can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall)
 /* Return true if an atomic exchange can be performed.  */
 
 bool
-can_atomic_exchange_p (enum machine_mode mode, bool allow_libcall)
+can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
 {
   enum insn_code icode;
 
@@ -7084,8 +7133,9 @@ find_cc_set (rtx x, const_rtx pat, void *data)
 static bool
 expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
 {
-  enum machine_mode mode = GET_MODE (mem);
-  rtx label, cmp_reg, success, oldval;
+  machine_mode mode = GET_MODE (mem);
+  rtx_code_label *label;
+  rtx cmp_reg, success, oldval;
 
   /* The loop we want to generate looks like
 
@@ -7112,7 +7162,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
   success = NULL_RTX;
   oldval = cmp_reg;
   if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
-                                      new_reg, false, MEMMODEL_SEQ_CST,
+                                      new_reg, false, MEMMODEL_SYNC_SEQ_CST,
                                       MEMMODEL_RELAXED))
     return false;
 
@@ -7133,7 +7183,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
 static rtx
 maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
 
   /* If the target supports the exchange directly, great.  */
@@ -7163,9 +7213,9 @@ static rtx
 maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
                                   enum memmodel model)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
-  rtx last_insn = get_last_insn ();
+  rtx_insn *last_insn = get_last_insn ();
 
   icode = optab_handler (sync_lock_test_and_set_optab, mode);
 
@@ -7173,9 +7223,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
      exists, and the memory model is stronger than acquire, add a release 
      barrier before the instruction.  */
 
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST
-      || (model & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_seq_cst (model) || is_mm_release (model) || is_mm_acq_rel (model))
     expand_mem_thread_fence (model);
 
   if (icode != CODE_FOR_nothing)
@@ -7219,7 +7267,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
 static rtx 
 maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
 
   if (can_compare_and_swap_p (mode, true))
     {
@@ -7244,7 +7292,7 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
 static rtx
 maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
 {
-  enum machine_mode pat_bool_mode;
+  machine_mode pat_bool_mode;
   struct expand_operand ops[3];
 
   if (!HAVE_atomic_test_and_set)
@@ -7282,11 +7330,12 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
   rtx ret;
 
   /* Try an atomic_exchange first.  */
-  ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
+  ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_SYNC_ACQUIRE);
   if (ret)
     return ret;
 
-  ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE);
+  ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
+                                          MEMMODEL_SYNC_ACQUIRE);
   if (ret)
     return ret;
 
@@ -7297,7 +7346,7 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
   /* If there are no other options, try atomic_test_and_set if the value
      being stored is 1.  */
   if (val == const1_rtx)
-    ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
+    ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_SYNC_ACQUIRE);
 
   return ret;
 }
@@ -7311,7 +7360,7 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
 rtx
 expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   rtx ret, trueval, subtarget;
 
   ret = maybe_emit_atomic_test_and_set (target, mem, model);
@@ -7352,7 +7401,10 @@ expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model)
      perform the operation.  */
   if (!ret)
     {
-      emit_move_insn (subtarget, mem);
+      /* If the result is ignored skip the move to target.  */
+      if (subtarget != const0_rtx)
+        emit_move_insn (subtarget, mem);
+
       emit_move_insn (mem, trueval);
       ret = subtarget;
     }
@@ -7403,7 +7455,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
                                bool is_weak, enum memmodel succ_model,
                                enum memmodel fail_model)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   struct expand_operand ops[8];
   enum insn_code icode;
   rtx target_oval, target_bool = NULL_RTX;
@@ -7424,7 +7476,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval,
   icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
   if (icode != CODE_FOR_nothing)
     {
-      enum machine_mode bool_mode = insn_data[icode].operand[0].mode;
+      machine_mode bool_mode = insn_data[icode].operand[0].mode;
 
       /* Make sure we always have a place for the bool operand.  */
       if (ptarget_bool == NULL
@@ -7537,21 +7589,12 @@ expand_asm_memory_barrier (void)
 /* This routine will either emit the mem_thread_fence pattern or issue a 
    sync_synchronize to generate a fence for memory model MEMMODEL.  */
 
-#ifndef HAVE_mem_thread_fence
-# define HAVE_mem_thread_fence 0
-# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-#ifndef HAVE_memory_barrier
-# define HAVE_memory_barrier 0
-# define gen_memory_barrier()  (gcc_unreachable (), NULL_RTX)
-#endif
-
 void
 expand_mem_thread_fence (enum memmodel model)
 {
   if (HAVE_mem_thread_fence)
     emit_insn (gen_mem_thread_fence (GEN_INT (model)));
-  else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+  else if (!is_mm_relaxed (model))
     {
       if (HAVE_memory_barrier)
        emit_insn (gen_memory_barrier ());
@@ -7565,17 +7608,12 @@ expand_mem_thread_fence (enum memmodel model)
 /* This routine will either emit the mem_signal_fence pattern or issue a 
    sync_synchronize to generate a fence for memory model MEMMODEL.  */
 
-#ifndef HAVE_mem_signal_fence
-# define HAVE_mem_signal_fence 0
-# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX)
-#endif
-
 void
 expand_mem_signal_fence (enum memmodel model)
 {
   if (HAVE_mem_signal_fence)
     emit_insn (gen_mem_signal_fence (GEN_INT (model)));
-  else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+  else if (!is_mm_relaxed (model))
     {
       /* By default targets are coherent between a thread and the signal
         handler running on the same thread.  Thus this really becomes a
@@ -7594,7 +7632,7 @@ expand_mem_signal_fence (enum memmodel model)
 rtx
 expand_atomic_load (rtx target, rtx mem, enum memmodel model)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
 
   /* If the target supports the load directly, great.  */
@@ -7630,7 +7668,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model)
     target = gen_reg_rtx (mode);
 
   /* For SEQ_CST, emit a barrier before the load.  */
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
 
   emit_move_insn (target, mem);
@@ -7650,7 +7688,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model)
 rtx
 expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   enum insn_code icode;
   struct expand_operand ops[3];
 
@@ -7676,7 +7714,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
          if (maybe_expand_insn (icode, 2, ops))
            {
              /* lock_release is only a release barrier.  */
-             if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+             if (is_mm_seq_cst (model))
                expand_mem_thread_fence (model);
              return const0_rtx;
            }
@@ -7703,7 +7741,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
   emit_move_insn (mem, val);
 
   /* For SEQ_CST, also emit a barrier after the store.  */
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
 
   return const0_rtx;
@@ -7845,7 +7883,7 @@ static rtx
 maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
               rtx val, bool use_memmodel, enum memmodel model, bool after)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   struct expand_operand ops[4];
   enum insn_code icode;
   int op_counter = 0;
@@ -7915,7 +7953,7 @@ expand_atomic_fetch_op_no_fallback (rtx target, rtx mem, rtx val,
                                    enum rtx_code code, enum memmodel model,
                                    bool after)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   struct atomic_op_functions optab;
   rtx result;
   bool unused_result = (target == const0_rtx);
@@ -8004,7 +8042,7 @@ rtx
 expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
                        enum memmodel model, bool after)
 {
-  enum machine_mode mode = GET_MODE (mem);
+  machine_mode mode = GET_MODE (mem);
   rtx result;
   bool unused_result = (target == const0_rtx);
 
@@ -8076,7 +8114,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
   /* If nothing else has succeeded, default to a compare and swap loop.  */
   if (can_compare_and_swap_p (mode, true))
     {
-      rtx insn;
+      rtx_insn *insn;
       rtx t0 = gen_reg_rtx (mode), t1;
 
       start_sequence ();
@@ -8135,7 +8173,7 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
 bool
 valid_multiword_target_p (rtx target)
 {
-  enum machine_mode mode;
+  machine_mode mode;
   int i;
 
   mode = GET_MODE (target);
@@ -8169,8 +8207,8 @@ maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno,
       if (!(REG_P (addr) && REGNO (addr) > LAST_VIRTUAL_REGISTER)
          && !side_effects_p (addr))
        {
-         rtx last;
-         enum machine_mode mode;
+         rtx_insn *last;
+         machine_mode mode;
 
          last = get_last_insn ();
          mode = get_address_mode (mem);
@@ -8194,7 +8232,7 @@ static bool
 maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
                          struct expand_operand *op)
 {
-  enum machine_mode mode, imode;
+  machine_mode mode, imode;
   bool old_volatile_ok, result;
 
   mode = op->mode;
@@ -8283,7 +8321,7 @@ bool
 maybe_legitimize_operands (enum insn_code icode, unsigned int opno,
                           unsigned int nops, struct expand_operand *ops)
 {
-  rtx last;
+  rtx_insn *last;
   unsigned int i;
 
   last = get_last_insn ();
@@ -8301,13 +8339,13 @@ maybe_legitimize_operands (enum insn_code icode, unsigned int opno,
    and emit any necessary set-up code.  Return null and emit no
    code on failure.  */
 
-rtx
+rtx_insn *
 maybe_gen_insn (enum insn_code icode, unsigned int nops,
                struct expand_operand *ops)
 {
   gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args);
   if (!maybe_legitimize_operands (icode, 0, nops, ops))
-    return NULL_RTX;
+    return NULL;
 
   switch (nops)
     {
@@ -8422,23 +8460,23 @@ enum extraction_type { ET_unaligned_mem, ET_reg };
 static bool
 get_traditional_extraction_insn (extraction_insn *insn,
                                 enum extraction_type type,
-                                enum machine_mode mode,
+                                machine_mode mode,
                                 enum insn_code icode,
                                 int struct_op, int field_op)
 {
   const struct insn_data_d *data = &insn_data[icode];
 
-  enum machine_mode struct_mode = data->operand[struct_op].mode;
+  machine_mode struct_mode = data->operand[struct_op].mode;
   if (struct_mode == VOIDmode)
     struct_mode = word_mode;
   if (mode != struct_mode)
     return false;
 
-  enum machine_mode field_mode = data->operand[field_op].mode;
+  machine_mode field_mode = data->operand[field_op].mode;
   if (field_mode == VOIDmode)
     field_mode = word_mode;
 
-  enum machine_mode pos_mode = data->operand[struct_op + 2].mode;
+  machine_mode pos_mode = data->operand[struct_op + 2].mode;
   if (pos_mode == VOIDmode)
     pos_mode = word_mode;
 
@@ -8459,7 +8497,7 @@ get_traditional_extraction_insn (extraction_insn *insn,
 static bool
 get_optab_extraction_insn (struct extraction_insn *insn,
                           enum extraction_type type,
-                          enum machine_mode mode, direct_optab reg_optab,
+                          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);
@@ -8486,7 +8524,7 @@ static bool
 get_extraction_insn (extraction_insn *insn,
                     enum extraction_pattern pattern,
                     enum extraction_type type,
-                    enum machine_mode mode)
+                    machine_mode mode)
 {
   switch (pattern)
     {
@@ -8534,9 +8572,9 @@ get_best_extraction_insn (extraction_insn *insn,
                          enum extraction_pattern pattern,
                          enum extraction_type type,
                          unsigned HOST_WIDE_INT struct_bits,
-                         enum machine_mode field_mode)
+                         machine_mode field_mode)
 {
-  enum machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
+  machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
   while (mode != VOIDmode)
     {
       if (get_extraction_insn (insn, pattern, type, mode))
@@ -8570,7 +8608,7 @@ bool
 get_best_reg_extraction_insn (extraction_insn *insn,
                              enum extraction_pattern pattern,
                              unsigned HOST_WIDE_INT struct_bits,
-                             enum machine_mode field_mode)
+                             machine_mode field_mode)
 {
   return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
                                   field_mode);
@@ -8589,7 +8627,7 @@ bool
 get_best_mem_extraction_insn (extraction_insn *insn,
                              enum extraction_pattern pattern,
                              HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
-                             enum machine_mode field_mode)
+                             machine_mode field_mode)
 {
   unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
                                        + bitsize
@@ -8599,4 +8637,31 @@ get_best_mem_extraction_insn (extraction_insn *insn,
                                   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),
+                              speed_p);
+      cheap[speed_p] = cost < COSTS_N_INSNS (3);
+      init[speed_p] = true;
+    }
+
+  return cheap[speed_p];
+}
+
 #include "gt-optabs.h"