OSDN Git Service

Add CONST1_RTX (vector mode) support.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index c390f54..44f485b 100644 (file)
@@ -119,8 +119,8 @@ struct store_by_pieces
   int reverse;
 };
 
-static rtx enqueue_insn (rtx, rtx);
 static unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT,
+                                                    unsigned int,
                                                     unsigned int);
 static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
                              struct move_by_pieces *);
@@ -145,13 +145,11 @@ static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
 static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
 static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode,
                        tree, enum machine_mode, int, tree, int);
-static rtx var_rtx (tree);
 
 static unsigned HOST_WIDE_INT highest_pow2_factor (tree);
 static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (tree, tree);
 
 static int is_aligning_offset (tree, tree);
-static rtx expand_increment (tree, int, int);
 static void expand_operands (tree, tree, rtx, rtx*, rtx*,
                             enum expand_modifier);
 static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
@@ -177,21 +175,25 @@ static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
    to perform a structure copy.  */
 #ifndef MOVE_BY_PIECES_P
 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
-  (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
+  (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
+   < (unsigned int) MOVE_RATIO)
 #endif
 
 /* This macro is used to determine whether clear_by_pieces should be
    called to clear storage.  */
 #ifndef CLEAR_BY_PIECES_P
 #define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
-  (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) CLEAR_RATIO)
+  (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
+   < (unsigned int) CLEAR_RATIO)
 #endif
 
 /* This macro is used to determine whether store_by_pieces should be
    called to "memset" storage with byte values other than zero, or
    to "memcpy" storage when the source is a constant string.  */
 #ifndef STORE_BY_PIECES_P
-#define STORE_BY_PIECES_P(SIZE, ALIGN) MOVE_BY_PIECES_P (SIZE, ALIGN)
+#define STORE_BY_PIECES_P(SIZE, ALIGN) \
+  (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
+   < (unsigned int) MOVE_RATIO)
 #endif
 
 /* This array records the insn_code of insns to perform block moves.  */
@@ -312,215 +314,6 @@ init_expr (void)
 {
   cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status));
 }
-
-/* Small sanity check that the queue is empty at the end of a function.  */
-
-void
-finish_expr_for_function (void)
-{
-  if (pending_chain)
-    abort ();
-}
-\f
-/* Manage the queue of increment instructions to be output
-   for POSTINCREMENT_EXPR expressions, etc.  */
-
-/* Queue up to increment (or change) VAR later.  BODY says how:
-   BODY should be the same thing you would pass to emit_insn
-   to increment right away.  It will go to emit_insn later on.
-
-   The value is a QUEUED expression to be used in place of VAR
-   where you want to guarantee the pre-incrementation value of VAR.  */
-
-static rtx
-enqueue_insn (rtx var, rtx body)
-{
-  pending_chain = gen_rtx_QUEUED (GET_MODE (var), var, NULL_RTX, NULL_RTX,
-                                 body, pending_chain);
-  return pending_chain;
-}
-
-/* Use protect_from_queue to convert a QUEUED expression
-   into something that you can put immediately into an instruction.
-   If the queued incrementation has not happened yet,
-   protect_from_queue returns the variable itself.
-   If the incrementation has happened, protect_from_queue returns a temp
-   that contains a copy of the old value of the variable.
-
-   Any time an rtx which might possibly be a QUEUED is to be put
-   into an instruction, it must be passed through protect_from_queue first.
-   QUEUED expressions are not meaningful in instructions.
-
-   Do not pass a value through protect_from_queue and then hold
-   on to it for a while before putting it in an instruction!
-   If the queue is flushed in between, incorrect code will result.  */
-
-rtx
-protect_from_queue (rtx x, int modify)
-{
-  RTX_CODE code = GET_CODE (x);
-
-#if 0  /* A QUEUED can hang around after the queue is forced out.  */
-  /* Shortcut for most common case.  */
-  if (pending_chain == 0)
-    return x;
-#endif
-
-  if (code != QUEUED)
-    {
-      /* A special hack for read access to (MEM (QUEUED ...)) to facilitate
-        use of autoincrement.  Make a copy of the contents of the memory
-        location rather than a copy of the address, but not if the value is
-        of mode BLKmode.  Don't modify X in place since it might be
-        shared.  */
-      if (code == MEM && GET_MODE (x) != BLKmode
-         && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
-       {
-         rtx y = XEXP (x, 0);
-         rtx new = replace_equiv_address_nv (x, QUEUED_VAR (y));
-
-         if (QUEUED_INSN (y))
-           {
-             rtx temp = gen_reg_rtx (GET_MODE (x));
-
-             emit_insn_before (gen_move_insn (temp, new),
-                               QUEUED_INSN (y));
-             return temp;
-           }
-
-         /* Copy the address into a pseudo, so that the returned value
-            remains correct across calls to emit_queue.  */
-         return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
-       }
-
-      /* Otherwise, recursively protect the subexpressions of all
-        the kinds of rtx's that can contain a QUEUED.  */
-      if (code == MEM)
-       {
-         rtx tem = protect_from_queue (XEXP (x, 0), 0);
-         if (tem != XEXP (x, 0))
-           {
-             x = copy_rtx (x);
-             XEXP (x, 0) = tem;
-           }
-       }
-      else if (code == PLUS || code == MULT)
-       {
-         rtx new0 = protect_from_queue (XEXP (x, 0), 0);
-         rtx new1 = protect_from_queue (XEXP (x, 1), 0);
-         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
-           {
-             x = copy_rtx (x);
-             XEXP (x, 0) = new0;
-             XEXP (x, 1) = new1;
-           }
-       }
-      return x;
-    }
-  /* If the increment has not happened, use the variable itself.  Copy it
-     into a new pseudo so that the value remains correct across calls to
-     emit_queue.  */
-  if (QUEUED_INSN (x) == 0)
-    return copy_to_reg (QUEUED_VAR (x));
-  /* If the increment has happened and a pre-increment copy exists,
-     use that copy.  */
-  if (QUEUED_COPY (x) != 0)
-    return QUEUED_COPY (x);
-  /* The increment has happened but we haven't set up a pre-increment copy.
-     Set one up now, and use it.  */
-  QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
-  emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
-                   QUEUED_INSN (x));
-  return QUEUED_COPY (x);
-}
-
-/* Return nonzero if X contains a QUEUED expression:
-   if it contains anything that will be altered by a queued increment.
-   We handle only combinations of MEM, PLUS, MINUS and MULT operators
-   since memory addresses generally contain only those.  */
-
-int
-queued_subexp_p (rtx x)
-{
-  enum rtx_code code = GET_CODE (x);
-  switch (code)
-    {
-    case QUEUED:
-      return 1;
-    case MEM:
-      return queued_subexp_p (XEXP (x, 0));
-    case MULT:
-    case PLUS:
-    case MINUS:
-      return (queued_subexp_p (XEXP (x, 0))
-             || queued_subexp_p (XEXP (x, 1)));
-    default:
-      return 0;
-    }
-}
-
-/* Retrieve a mark on the queue.  */
-  
-static rtx
-mark_queue (void)
-{
-  return pending_chain;
-}
-
-/* Perform all the pending incrementations that have been enqueued
-   after MARK was retrieved.  If MARK is null, perform all the
-   pending incrementations.  */
-
-static void
-emit_insns_enqueued_after_mark (rtx mark)
-{
-  rtx p;
-
-  /* The marked incrementation may have been emitted in the meantime
-     through a call to emit_queue.  In this case, the mark is not valid
-     anymore so do nothing.  */
-  if (mark && ! QUEUED_BODY (mark))
-    return;
-
-  while ((p = pending_chain) != mark)
-    {
-      rtx body = QUEUED_BODY (p);
-
-      switch (GET_CODE (body))
-       {
-       case INSN:
-       case JUMP_INSN:
-       case CALL_INSN:
-       case CODE_LABEL:
-       case BARRIER:
-       case NOTE:
-         QUEUED_INSN (p) = body;
-         emit_insn (body);
-         break;
-
-#ifdef ENABLE_CHECKING
-       case SEQUENCE:
-         abort ();
-         break;
-#endif
-
-       default:
-         QUEUED_INSN (p) = emit_insn (body);
-         break;
-       }
-
-      QUEUED_BODY (p) = 0;
-      pending_chain = QUEUED_NEXT (p);
-    }
-}
-
-/* Perform all the pending incrementations.  */
-
-void
-emit_queue (void)
-{
-  emit_insns_enqueued_after_mark (NULL_RTX);
-}
 \f
 /* Copy data from FROM to TO, where the machine modes are not the same.
    Both modes may be integer, or both may be floating.
@@ -541,11 +334,8 @@ convert_move (rtx to, rtx from, int unsignedp)
   enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
                              : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
 
-  to = protect_from_queue (to, 1);
-  from = protect_from_queue (from, 0);
 
-  if (to_real != from_real)
-    abort ();
+  gcc_assert (to_real == from_real);
 
   /* If the source and destination are already the same, then there's
      nothing to do.  */
@@ -562,8 +352,7 @@ convert_move (rtx to, rtx from, int unsignedp)
       && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
     from = gen_lowpart (to_mode, from), from_mode = to_mode;
 
-  if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
-    abort ();
+  gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to));
 
   if (to_mode == from_mode
       || (from_mode == VOIDmode && CONSTANT_P (from)))
@@ -574,8 +363,7 @@ convert_move (rtx to, rtx from, int unsignedp)
 
   if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
     {
-      if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
-       abort ();
+      gcc_assert (GET_MODE_BITSIZE (from_mode) == GET_MODE_BITSIZE (to_mode));
 
       if (VECTOR_MODE_P (to_mode))
        from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
@@ -598,12 +386,13 @@ convert_move (rtx to, rtx from, int unsignedp)
       rtx value, insns;
       convert_optab tab;
 
+      gcc_assert (GET_MODE_PRECISION (from_mode)
+                 != GET_MODE_PRECISION (to_mode));
+      
       if (GET_MODE_PRECISION (from_mode) < GET_MODE_PRECISION (to_mode))
        tab = sext_optab;
-      else if (GET_MODE_PRECISION (from_mode) > GET_MODE_PRECISION (to_mode))
-       tab = trunc_optab;
       else
-       abort ();
+       tab = trunc_optab;
 
       /* Try converting directly if the insn is supported.  */
 
@@ -618,9 +407,8 @@ convert_move (rtx to, rtx from, int unsignedp)
       /* Otherwise use a libcall.  */
       libcall = tab->handlers[to_mode][from_mode].libfunc;
 
-      if (!libcall)
-       /* This conversion is not implemented yet.  */
-       abort ();
+      /* Is this conversion implemented yet?  */
+      gcc_assert (libcall);
 
       start_sequence ();
       value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
@@ -642,9 +430,8 @@ convert_move (rtx to, rtx from, int unsignedp)
       enum machine_mode full_mode
        = smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
 
-      if (trunc_optab->handlers[to_mode][full_mode].insn_code
-         == CODE_FOR_nothing)
-       abort ();
+      gcc_assert (trunc_optab->handlers[to_mode][full_mode].insn_code
+                 != CODE_FOR_nothing);
 
       if (full_mode != from_mode)
        from = convert_to_mode (full_mode, from, unsignedp);
@@ -657,9 +444,8 @@ convert_move (rtx to, rtx from, int unsignedp)
       enum machine_mode full_mode
        = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
 
-      if (sext_optab->handlers[full_mode][from_mode].insn_code
-         == CODE_FOR_nothing)
-       abort ();
+      gcc_assert (sext_optab->handlers[full_mode][from_mode].insn_code
+                 != CODE_FOR_nothing);
 
       emit_unop_insn (sext_optab->handlers[full_mode][from_mode].insn_code,
                      to, from, UNKNOWN);
@@ -766,8 +552,7 @@ convert_move (rtx to, rtx from, int unsignedp)
          int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
          rtx subword = operand_subword (to, index, 1, to_mode);
 
-         if (subword == 0)
-           abort ();
+         gcc_assert (subword);
 
          if (fill_value != subword)
            emit_move_insn (subword, fill_value);
@@ -855,8 +640,9 @@ convert_move (rtx to, rtx from, int unsignedp)
 
          /* No suitable intermediate mode.
             Generate what we need with shifts.  */
-         shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
-                                     - GET_MODE_BITSIZE (from_mode), 0);
+         shift_amount = build_int_cst (NULL_TREE,
+                                       GET_MODE_BITSIZE (to_mode)
+                                       - GET_MODE_BITSIZE (from_mode));
          from = gen_lowpart (to_mode, force_reg (from_mode, from));
          tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
                              to, unsignedp);
@@ -891,7 +677,7 @@ convert_move (rtx to, rtx from, int unsignedp)
     }
 
   /* Mode combination is not recognized.  */
-  abort ();
+  gcc_unreachable ();
 }
 
 /* Return an rtx for a value that would result
@@ -899,10 +685,7 @@ convert_move (rtx to, rtx from, int unsignedp)
    Both X and MODE may be floating, or both integer.
    UNSIGNEDP is nonzero if X is an unsigned value.
    This can be done by referring to a part of X in place
-   or by copying to a new temporary with conversion.
-
-   This function *must not* call protect_from_queue
-   except when putting X into an insn (in which case convert_move does it).  */
+   or by copying to a new temporary with conversion.  */
 
 rtx
 convert_to_mode (enum machine_mode mode, rtx x, int unsignedp)
@@ -918,10 +701,7 @@ convert_to_mode (enum machine_mode mode, rtx x, int unsignedp)
    This can be done by referring to a part of X in place
    or by copying to a new temporary with conversion.
 
-   You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode.
-
-   This function *must not* call protect_from_queue
-   except when putting X into an insn (in which case convert_move does it).  */
+   You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode.  */
 
 rtx
 convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int unsignedp)
@@ -1011,8 +791,7 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns
      subreg operation.  */
   if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
     {
-      if (GET_MODE_BITSIZE (mode) != GET_MODE_BITSIZE (oldmode))
-       abort ();
+      gcc_assert (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (oldmode));
       return simplify_gen_subreg (mode, x, oldmode, 0);
     }
 
@@ -1040,8 +819,7 @@ can_move_by_pieces (unsigned HOST_WIDE_INT len,
 }
 
 /* Generate several move instructions to copy LEN bytes from block FROM to
-   block TO.  (These are MEM rtx's with BLKmode).  The caller must pass FROM
-   and TO through protect_from_queue before calling.
+   block TO.  (These are MEM rtx's with BLKmode).
 
    If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
    used to push FROM to the stack.
@@ -1103,7 +881,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
      copy addresses to registers (to make displacements shorter)
      and use post-increment if available.  */
   if (!(data.autinc_from && data.autinc_to)
-      && move_by_pieces_ninsns (len, align) > 2)
+      && move_by_pieces_ninsns (len, align, max_size) > 2)
     {
       /* Find the mode of the largest move...  */
       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
@@ -1141,9 +919,22 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
        data.to_addr = copy_addr_to_reg (to_addr);
     }
 
-  if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-    align = MOVE_MAX * BITS_PER_UNIT;
+  tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
+  if (align >= GET_MODE_ALIGNMENT (tmode))
+    align = GET_MODE_ALIGNMENT (tmode);
+  else
+    {
+      enum machine_mode xmode;
+
+      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
+          tmode != VOIDmode;
+          xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
+       if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES
+           || SLOW_UNALIGNED_ACCESS (tmode, align))
+         break;
+
+      align = MAX (align, GET_MODE_ALIGNMENT (xmode));
+    }
 
   /* First move what we can in the largest integer mode, then go to
      successively smaller modes.  */
@@ -1166,15 +957,13 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
     }
 
   /* The code above should have handled everything.  */
-  if (data.len > 0)
-    abort ();
+  gcc_assert (!data.len);
 
   if (endp)
     {
       rtx to1;
 
-      if (data.reverse)
-       abort ();
+      gcc_assert (!data.reverse);
       if (data.autinc_to)
        {
          if (endp == 2)
@@ -1204,18 +993,32 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
    ALIGN (in bits) is maximum alignment we can assume.  */
 
 static unsigned HOST_WIDE_INT
-move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align)
+move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
+                      unsigned int max_size)
 {
   unsigned HOST_WIDE_INT n_insns = 0;
-  unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
+  enum machine_mode tmode;
+
+  tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
+  if (align >= GET_MODE_ALIGNMENT (tmode))
+    align = GET_MODE_ALIGNMENT (tmode);
+  else
+    {
+      enum machine_mode tmode, xmode;
+
+      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
+          tmode != VOIDmode;
+          xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
+       if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES
+           || SLOW_UNALIGNED_ACCESS (tmode, align))
+         break;
 
-  if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-    align = MOVE_MAX * BITS_PER_UNIT;
+      align = MAX (align, GET_MODE_ALIGNMENT (xmode));
+    }
 
   while (max_size > 1)
     {
-      enum machine_mode mode = VOIDmode, tmode;
+      enum machine_mode mode = VOIDmode;
       enum insn_code icode;
 
       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
@@ -1233,8 +1036,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align)
       max_size = GET_MODE_SIZE (mode);
     }
 
-  if (l)
-    abort ();
+  gcc_assert (!l);
   return n_insns;
 }
 
@@ -1283,7 +1085,7 @@ move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
 #ifdef PUSH_ROUNDING
          emit_single_push_insn (mode, from1, NULL);
 #else
-         abort ();
+         gcc_unreachable ();
 #endif
        }
 
@@ -1337,21 +1139,14 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
 
-  x = protect_from_queue (x, 1);
-  y = protect_from_queue (y, 0);
-  size = protect_from_queue (size, 0);
-
-  if (!MEM_P (x))
-    abort ();
-  if (!MEM_P (y))
-    abort ();
-  if (size == 0)
-    abort ();
+  gcc_assert (MEM_P (x));
+  gcc_assert (MEM_P (y));
+  gcc_assert (size);
 
   /* Make sure we've got BLKmode addresses; store_one_arg can decide that
      block copy is more efficient for other large modes, e.g. DCmode.  */
@@ -1513,24 +1308,9 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
   enum machine_mode size_mode;
   rtx retval;
 
-  /* DST, SRC, or SIZE may have been passed through protect_from_queue.
-
-     It is unsafe to save the value generated by protect_from_queue and reuse
-     it later.  Consider what happens if emit_queue is called before the
-     return value from protect_from_queue is used.
-
-     Expansion of the CALL_EXPR below will call emit_queue before we are
-     finished emitting RTL for argument setup.  So if we are not careful we
-     could get the wrong value for an argument.
-
-     To avoid this problem we go ahead and emit code to copy the addresses of
-     DST and SRC and SIZE into new pseudos.
-
-     Note this is not strictly needed for library calls since they do not call
-     emit_queue before loading their arguments.  However, we may need to have
-     library calls call emit_queue in the future since failing to do so could
-     cause problems for targets which define SMALL_REGISTER_CLASSES and pass
-     arguments in registers.  */
+  /* Emit code to copy the addresses of DST and SRC and SIZE into new
+     pseudos.  We can then place those new pseudos into a VAR_DECL and
+     use them later.  */
 
   dst_addr = copy_to_mode_reg (Pmode, XEXP (dst, 0));
   src_addr = copy_to_mode_reg (Pmode, XEXP (src, 0));
@@ -1561,21 +1341,11 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
 
   /* Now we have to build up the CALL_EXPR itself.  */
   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
-  call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
-                    call_expr, arg_list, NULL_TREE);
+  call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+                     call_expr, arg_list, NULL_TREE);
 
   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 
-  /* If we are initializing a readonly value, show the above call clobbered
-     it. Otherwise, a load from it may erroneously be hoisted from a loop, or
-     the delay slot scheduler might overlook conflicts and take nasty
-     decisions.  */
-  if (RTX_UNCHANGING_P (dst))
-    add_function_usage_to
-      (last_call_insn (), gen_rtx_EXPR_LIST (VOIDmode,
-                                            gen_rtx_CLOBBER (VOIDmode, dst),
-                                            NULL_RTX));
-
   return retval;
 }
 
@@ -1607,10 +1377,7 @@ init_block_move_fn (const char *asmspec)
     }
 
   if (asmspec)
-    {
-      SET_DECL_RTL (block_move_fn, NULL_RTX);
-      SET_DECL_ASSEMBLER_NAME (block_move_fn, get_identifier (asmspec));
-    }
+    set_user_assembler_name (block_move_fn, asmspec);
 }
 
 static tree
@@ -1624,7 +1391,7 @@ emit_block_move_libcall_fn (int for_call)
   if (for_call && !emitted_extern)
     {
       emitted_extern = true;
-      make_decl_rtl (block_move_fn, NULL);
+      make_decl_rtl (block_move_fn);
       assemble_external (block_move_fn);
     }
 
@@ -1750,8 +1517,7 @@ move_block_from_reg (int regno, rtx x, int nregs)
     {
       rtx tem = operand_subword (x, i, 1, BLKmode);
 
-      if (tem == 0)
-       abort ();
+      gcc_assert (tem);
 
       emit_move_insn (tem, gen_rtx_REG (word_mode, regno + i));
     }
@@ -1769,8 +1535,7 @@ gen_group_rtx (rtx orig)
   int i, length;
   rtx *tmps;
 
-  if (GET_CODE (orig) != PARALLEL)
-    abort ();
+  gcc_assert (GET_CODE (orig) == PARALLEL);
 
   length = XVECLEN (orig, 0);
   tmps = alloca (sizeof (rtx) * length);
@@ -1803,8 +1568,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
   rtx *tmps, src;
   int start, i;
 
-  if (GET_CODE (dst) != PARALLEL)
-    abort ();
+  gcc_assert (GET_CODE (dst) == PARALLEL);
 
   /* Check for a NULL entry, used to indicate that the parameter goes
      both on the stack and in registers.  */
@@ -1838,8 +1602,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
              )
            shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
          bytelen = ssize - bytepos;
-         if (bytelen <= 0)
-           abort ();
+         gcc_assert (bytelen > 0);
        }
 
       /* If we won't be loading directly from memory, protect the real source
@@ -1886,16 +1649,17 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
                  && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
                tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
                                             (bytepos % slen0) * BITS_PER_UNIT,
-                                            1, NULL_RTX, mode, mode, ssize);
+                                            1, NULL_RTX, mode, mode);
            }
-         else if (bytepos == 0)
+         else
            {
-             rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
+             rtx mem;
+             
+             gcc_assert (!bytepos);
+             mem = assign_stack_temp (GET_MODE (src), slen, 0);
              emit_move_insn (mem, src);
              tmps[i] = adjust_address (mem, mode, 0);
            }
-         else
-           abort ();
        }
       /* FIXME: A SIMD parallel will eventually lead to a subreg of a
         SIMD register, which is currently broken.  While we get GCC
@@ -1919,15 +1683,13 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
       else
        tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
                                     bytepos * BITS_PER_UNIT, 1, NULL_RTX,
-                                    mode, mode, ssize);
+                                    mode, mode);
 
       if (shift)
        tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
-                               build_int_2 (shift, 0), tmps[i], 0);
+                               build_int_cst (NULL_TREE, shift), tmps[i], 0);
     }
 
-  emit_queue ();
-
   /* Copy the extracted pieces into the proper (probable) hard regs.  */
   for (i = start; i < XVECLEN (dst, 0); i++)
     emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
@@ -1941,10 +1703,9 @@ emit_group_move (rtx dst, rtx src)
 {
   int i;
 
-  if (GET_CODE (src) != PARALLEL
-      || GET_CODE (dst) != PARALLEL
-      || XVECLEN (src, 0) != XVECLEN (dst, 0))
-    abort ();
+  gcc_assert (GET_CODE (src) == PARALLEL
+             && GET_CODE (dst) == PARALLEL
+             && XVECLEN (src, 0) == XVECLEN (dst, 0));
 
   /* Skip first entry if NULL.  */
   for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
@@ -1963,8 +1724,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
   rtx *tmps, dst;
   int start, i;
 
-  if (GET_CODE (src) != PARALLEL)
-    abort ();
+  gcc_assert (GET_CODE (src) == PARALLEL);
 
   /* Check for a NULL entry, used to indicate that the parameter goes
      both on the stack and in registers.  */
@@ -1982,7 +1742,6 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
       tmps[i] = gen_reg_rtx (GET_MODE (reg));
       emit_move_insn (tmps[i], reg);
     }
-  emit_queue ();
 
   /* If we won't be storing directly into memory, protect the real destination
      from strange tricks we might play.  */
@@ -2037,7 +1796,8 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
            {
              int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
              tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
-                                     build_int_2 (shift, 0), tmps[i], 0);
+                                     build_int_cst (NULL_TREE, shift),
+                                     tmps[i], 0);
            }
          bytelen = ssize - bytepos;
        }
@@ -2051,8 +1811,9 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
              bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
              dest = XEXP (dst, 1);
            }
-         else if (bytepos == 0 && XVECLEN (src, 0))
+         else
            {
+             gcc_assert (bytepos == 0 && XVECLEN (src, 0));
              dest = assign_stack_temp (GET_MODE (dest),
                                        GET_MODE_SIZE (GET_MODE (dest)), 0);
              emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
@@ -2060,8 +1821,6 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
              dst = dest;
              break;
            }
-         else
-           abort ();
        }
 
       /* Optimize the access just a bit.  */
@@ -2073,11 +1832,9 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
        emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
       else
        store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
-                        mode, tmps[i], ssize);
+                        mode, tmps[i]);
     }
 
-  emit_queue ();
-
   /* Copy from the pseudo into the (probable) hard reg.  */
   if (orig_dst != dst)
     emit_move_insn (orig_dst, dst);
@@ -2159,9 +1916,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
       store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
                       extract_bit_field (src, bitsize,
                                          xbitpos % BITS_PER_WORD, 1,
-                                         NULL_RTX, word_mode, word_mode,
-                                         BITS_PER_WORD),
-                      BITS_PER_WORD);
+                                         NULL_RTX, word_mode, word_mode));
     }
 
   return tgtblk;
@@ -2173,10 +1928,8 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
 void
 use_reg (rtx *call_fusage, rtx reg)
 {
-  if (!REG_P (reg)
-      || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
-    abort ();
-
+  gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER);
+  
   *call_fusage
     = gen_rtx_EXPR_LIST (VOIDmode,
                         gen_rtx_USE (VOIDmode, reg), *call_fusage);
@@ -2190,8 +1943,7 @@ use_regs (rtx *call_fusage, int regno, int nregs)
 {
   int i;
 
-  if (regno + nregs > FIRST_PSEUDO_REGISTER)
-    abort ();
+  gcc_assert (regno + nregs <= FIRST_PSEUDO_REGISTER);
 
   for (i = 0; i < nregs; i++)
     use_reg (call_fusage, regno_reg_rtx[regno + i]);
@@ -2230,7 +1982,8 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
                     rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode),
                     void *constfundata, unsigned int align)
 {
-  unsigned HOST_WIDE_INT max_size, l;
+  unsigned HOST_WIDE_INT l;
+  unsigned int max_size;
   HOST_WIDE_INT offset = 0;
   enum machine_mode mode, tmode;
   enum insn_code icode;
@@ -2243,9 +1996,22 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
   if (! STORE_BY_PIECES_P (len, align))
     return 0;
 
-  if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-    align = MOVE_MAX * BITS_PER_UNIT;
+  tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
+  if (align >= GET_MODE_ALIGNMENT (tmode))
+    align = GET_MODE_ALIGNMENT (tmode);
+  else
+    {
+      enum machine_mode xmode;
+
+      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
+          tmode != VOIDmode;
+          xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
+       if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES
+           || SLOW_UNALIGNED_ACCESS (tmode, align))
+         break;
+
+      align = MAX (align, GET_MODE_ALIGNMENT (xmode));
+    }
 
   /* We would first store what we can in the largest integer mode, then go to
      successively smaller modes.  */
@@ -2293,8 +2059,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
        }
 
       /* The code above should have handled everything.  */
-      if (l != 0)
-       abort ();
+      gcc_assert (!l);
     }
 
   return 1;
@@ -2317,14 +2082,11 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
 
   if (len == 0)
     {
-      if (endp == 2)
-       abort ();
+      gcc_assert (endp != 2);
       return to;
     }
 
-  if (! STORE_BY_PIECES_P (len, align))
-    abort ();
-  to = protect_from_queue (to, 1);
+  gcc_assert (STORE_BY_PIECES_P (len, align));
   data.constfun = constfun;
   data.constfundata = constfundata;
   data.len = len;
@@ -2334,8 +2096,7 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
     {
       rtx to1;
 
-      if (data.reverse)
-       abort ();
+      gcc_assert (!data.reverse);
       if (data.autinc_to)
        {
          if (endp == 2)
@@ -2362,8 +2123,7 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
 }
 
 /* Generate several move instructions to clear LEN bytes of block TO.  (A MEM
-   rtx with BLKmode).  The caller must pass TO through protect_from_queue
-   before calling. ALIGN is maximum alignment we can assume.  */
+   rtx with BLKmode).  ALIGN is maximum alignment we can assume.  */
 
 static void
 clear_by_pieces (rtx to, unsigned HOST_WIDE_INT len, unsigned int align)
@@ -2393,15 +2153,14 @@ clear_by_pieces_1 (void *data ATTRIBUTE_UNUSED,
 
 /* Subroutine of clear_by_pieces and store_by_pieces.
    Generate several move instructions to store LEN bytes of block TO.  (A MEM
-   rtx with BLKmode).  The caller must pass TO through protect_from_queue
-   before calling.  ALIGN is maximum alignment we can assume.  */
+   rtx with BLKmode).  ALIGN is maximum alignment we can assume.  */
 
 static void
 store_by_pieces_1 (struct store_by_pieces *data ATTRIBUTE_UNUSED,
                   unsigned int align ATTRIBUTE_UNUSED)
 {
   rtx to_addr = XEXP (data->to, 0);
-  unsigned HOST_WIDE_INT max_size = STORE_MAX_PIECES + 1;
+  unsigned int max_size = STORE_MAX_PIECES + 1;
   enum machine_mode mode = VOIDmode, tmode;
   enum insn_code icode;
 
@@ -2421,7 +2180,7 @@ store_by_pieces_1 (struct store_by_pieces *data ATTRIBUTE_UNUSED,
      copy addresses to registers (to make displacements shorter)
      and use post-increment if available.  */
   if (!data->autinc_to
-      && move_by_pieces_ninsns (data->len, align) > 2)
+      && move_by_pieces_ninsns (data->len, align, max_size) > 2)
     {
       /* Determine the main mode we'll be using.  */
       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
@@ -2448,9 +2207,22 @@ store_by_pieces_1 (struct store_by_pieces *data ATTRIBUTE_UNUSED,
        data->to_addr = copy_addr_to_reg (to_addr);
     }
 
-  if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-    align = MOVE_MAX * BITS_PER_UNIT;
+  tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
+  if (align >= GET_MODE_ALIGNMENT (tmode))
+    align = GET_MODE_ALIGNMENT (tmode);
+  else
+    {
+      enum machine_mode xmode;
+
+      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
+          tmode != VOIDmode;
+          xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
+       if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES
+           || SLOW_UNALIGNED_ACCESS (tmode, align))
+         break;
+
+      align = MAX (align, GET_MODE_ALIGNMENT (xmode));
+    }
 
   /* First store what we can in the largest integer mode, then go to
      successively smaller modes.  */
@@ -2473,8 +2245,7 @@ store_by_pieces_1 (struct store_by_pieces *data ATTRIBUTE_UNUSED,
     }
 
   /* The code above should have handled everything.  */
-  if (data->len != 0)
-    abort ();
+  gcc_assert (!data->len);
 }
 
 /* Subroutine of store_by_pieces_1.  Store as many bytes as appropriate
@@ -2534,9 +2305,6 @@ clear_storage (rtx object, rtx size)
     emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
   else
     {
-      object = protect_from_queue (object, 1);
-      size = protect_from_queue (size, 0);
-
       if (size == const0_rtx)
        ;
       else if (GET_CODE (size) == CONST_INT
@@ -2617,24 +2385,8 @@ clear_storage_via_libcall (rtx object, rtx size)
   enum machine_mode size_mode;
   rtx retval;
 
-  /* OBJECT or SIZE may have been passed through protect_from_queue.
-
-     It is unsafe to save the value generated by protect_from_queue
-     and reuse it later.  Consider what happens if emit_queue is
-     called before the return value from protect_from_queue is used.
-
-     Expansion of the CALL_EXPR below will call emit_queue before
-     we are finished emitting RTL for argument setup.  So if we are
-     not careful we could get the wrong value for an argument.
-
-     To avoid this problem we go ahead and emit code to copy OBJECT
-     and SIZE into new pseudos.
-
-     Note this is not strictly needed for library calls since they
-     do not call emit_queue before loading their arguments.  However,
-     we may need to have library calls call emit_queue in the future
-     since failing to do so could cause problems for targets which
-     define SMALL_REGISTER_CLASSES and pass arguments in registers.  */
+  /* Emit code to copy OBJECT and SIZE into new pseudos.  We can then
+     place those into new pseudos into a VAR_DECL and use them later.  */
 
   object = copy_to_mode_reg (Pmode, XEXP (object, 0));
 
@@ -2658,17 +2410,11 @@ clear_storage_via_libcall (rtx object, rtx size)
 
   /* Now we have to build up the CALL_EXPR itself.  */
   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
-  call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
-                    call_expr, arg_list, NULL_TREE);
+  call_expr = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+                     call_expr, arg_list, NULL_TREE);
 
   retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 
-  /* If we are initializing a readonly value, show the above call
-     clobbered it.  Otherwise, a load from it may erroneously be
-     hoisted from a loop.  */
-  if (RTX_UNCHANGING_P (object))
-    emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
-
   return retval;
 }
 
@@ -2700,10 +2446,7 @@ init_block_clear_fn (const char *asmspec)
     }
 
   if (asmspec)
-    {
-      SET_DECL_RTL (block_clear_fn, NULL_RTX);
-      SET_DECL_ASSEMBLER_NAME (block_clear_fn, get_identifier (asmspec));
-    }
+    set_user_assembler_name (block_clear_fn, asmspec);
 }
 
 static tree
@@ -2717,7 +2460,7 @@ clear_storage_libcall_fn (int for_call)
   if (for_call && !emitted_extern)
     {
       emitted_extern = true;
-      make_decl_rtl (block_clear_fn, NULL);
+      make_decl_rtl (block_clear_fn);
       assemble_external (block_clear_fn);
     }
 
@@ -2738,11 +2481,8 @@ emit_move_insn (rtx x, rtx y)
   rtx y_cst = NULL_RTX;
   rtx last_insn, set;
 
-  x = protect_from_queue (x, 1);
-  y = protect_from_queue (y, 0);
-
-  if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
-    abort ();
+  gcc_assert (mode != BLKmode
+             && (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode));
 
   if (CONSTANT_P (y))
     {
@@ -2780,8 +2520,7 @@ emit_move_insn (rtx x, rtx y)
              && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
     y = validize_mem (y);
 
-  if (mode == BLKmode)
-    abort ();
+  gcc_assert (mode != BLKmode);
 
   last_insn = emit_move_insn_1 (x, y);
 
@@ -2805,8 +2544,7 @@ emit_move_insn_1 (rtx x, rtx y)
   enum machine_mode submode;
   enum mode_class class = GET_MODE_CLASS (mode);
 
-  if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
-    abort ();
+  gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
 
   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
     return
@@ -2986,8 +2724,7 @@ emit_move_insn_1 (rtx x, rtx y)
          if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
            break;
 
-      if (tmode == VOIDmode)
-       abort ();
+      gcc_assert (tmode != VOIDmode);
 
       /* Get X and Y in TMODE.  We can't use gen_lowpart here because it
         may call change_address which is not appropriate if we were
@@ -3036,13 +2773,15 @@ emit_move_insn_1 (rtx x, rtx y)
   /* This will handle any multi-word or full-word mode that lacks a move_insn
      pattern.  However, you will get better code if you define such patterns,
      even if they must turn into multiple assembler instructions.  */
-  else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
+  else
     {
       rtx last_insn = 0;
       rtx seq, inner;
       int need_clobber;
       int i;
-
+      
+      gcc_assert (GET_MODE_SIZE (mode) >= UNITS_PER_WORD);
+      
 #ifdef PUSH_ROUNDING
 
       /* If X is a push on the stack, do the push now and replace
@@ -3116,8 +2855,7 @@ emit_move_insn_1 (rtx x, rtx y)
          else if (ypart == 0)
            ypart = operand_subword_force (y, i, mode);
 
-         if (xpart == 0 || ypart == 0)
-           abort ();
+         gcc_assert (xpart && ypart);
 
          need_clobber |= (GET_CODE (xpart) == SUBREG);
 
@@ -3140,8 +2878,6 @@ emit_move_insn_1 (rtx x, rtx y)
 
       return last_insn;
     }
-  else
-    abort ();
 }
 
 /* If Y is representable exactly in a narrower mode, and the target can
@@ -3204,7 +2940,6 @@ compress_float_constant (rtx x, rtx y)
 
 /* Push a block of length SIZE (perhaps variable)
    and return an rtx to address the beginning of the block.
-   Note that it is not possible for the value returned to be a QUEUED.
    The value may be virtual_outgoing_args_rtx.
 
    EXTRA is the number of bytes of padding to push in addition to SIZE.
@@ -3405,7 +3140,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
     if (where_pad != none)
       where_pad = (where_pad == downward ? upward : downward);
 
-  xinner = x = protect_from_queue (x, 0);
+  xinner = x;
 
   if (mode == BLKmode)
     {
@@ -3426,8 +3161,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
       else
        offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
 
-      if (size == 0)
-       abort ();
+      gcc_assert (size);
 
       used -= offset;
 
@@ -3522,16 +3256,11 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
 
          target = gen_rtx_MEM (BLKmode, temp);
 
-         if (type != 0)
-           {
-             set_mem_attributes (target, type, 1);
-             /* Function incoming arguments may overlap with sibling call
-                outgoing arguments and we cannot allow reordering of reads
-                from function arguments with stores to outgoing arguments
-                of sibling calls.  */
-             set_mem_alias_set (target, 0);
-           }
-
+         /* We do *not* set_mem_attributes here, because incoming arguments
+            may overlap with sibling call outgoing arguments and we cannot
+            allow reordering of reads from function arguments with stores
+            to outgoing arguments of sibling calls.  We do, however, want
+            to record the alignment of the stack slot.  */
          /* ALIGN may well be better aligned than TYPE, e.g. due to
             PARM_BOUNDARY.  Assume the caller isn't lying.  */
          set_mem_align (target, align);
@@ -3627,15 +3356,15 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
            addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
                                                       args_so_far));
          dest = gen_rtx_MEM (mode, addr);
-         if (type != 0)
-           {
-             set_mem_attributes (dest, type, 1);
-             /* Function incoming arguments may overlap with sibling call
-                outgoing arguments and we cannot allow reordering of reads
-                from function arguments with stores to outgoing arguments
-                of sibling calls.  */
-             set_mem_alias_set (dest, 0);
-           }
+
+         /* We do *not* set_mem_attributes here, because incoming arguments
+            may overlap with sibling call outgoing arguments and we cannot
+            allow reordering of reads from function arguments with stores
+            to outgoing arguments of sibling calls.  We do, however, want
+            to record the alignment of the stack slot.  */
+         /* ALIGN may well be better aligned than TYPE, e.g. due to
+            PARM_BOUNDARY.  Assume the caller isn't lying.  */
+         set_mem_align (dest, align);
 
          emit_move_insn (dest, x);
        }
@@ -3667,23 +3396,18 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
 static rtx
 get_subtarget (rtx x)
 {
-  return ((x == 0
+  return (optimize
+          || x == 0
           /* Only registers can be subtargets.  */
           || !REG_P (x)
-          /* If the register is readonly, it can't be set more than once.  */
-          || RTX_UNCHANGING_P (x)
           /* Don't use hard regs to avoid extending their life.  */
           || REGNO (x) < FIRST_PSEUDO_REGISTER
-          /* Avoid subtargets inside loops,
-             since they hide some invariant expressions.  */
-          || preserve_subexpressions_p ())
          ? 0 : x);
 }
 
 /* Expand an assignment that stores the value of FROM into TO.
    If WANT_VALUE is nonzero, return an rtx for the value of TO.
-   (This may contain a QUEUED rtx;
-   if the value is constant, this rtx is a constant.)
+   (If the value is constant, this rtx is a constant.)
    Otherwise, the returned value is NULL_RTX.  */
 
 rtx
@@ -3734,8 +3458,7 @@ expand_assignment (tree to, tree from, int want_value)
        {
          rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
 
-         if (!MEM_P (to_rtx))
-           abort ();
+         gcc_assert (MEM_P (to_rtx));
 
 #ifdef POINTERS_EXTEND_UNSIGNED
          if (GET_MODE (offset_rtx) != Pmode)
@@ -3782,18 +3505,6 @@ expand_assignment (tree to, tree from, int want_value)
          MEM_VOLATILE_P (to_rtx) = 1;
        }
 
-      if (TREE_CODE (to) == COMPONENT_REF
-         && TREE_READONLY (TREE_OPERAND (to, 1))
-         /* We can't assert that a MEM won't be set more than once
-            if the component is not addressable because another
-            non-addressable component may be referenced by the same MEM.  */
-         && ! (MEM_P (to_rtx) && ! can_address_p (to)))
-       {
-         if (to_rtx == orig_to_rtx)
-           to_rtx = copy_rtx (to_rtx);
-         RTX_UNCHANGING_P (to_rtx) = 1;
-       }
-
       if (MEM_P (to_rtx) && ! can_address_p (to))
        {
          if (to_rtx == orig_to_rtx)
@@ -3801,18 +3512,16 @@ expand_assignment (tree to, tree from, int want_value)
          MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
        }
 
-      /* Disabled temporarily.  GET_MODE (to_rtx) is often not the right
-        mode.  */
-      while (0 && mode1 == VOIDmode && !want_value
-            && bitpos + bitsize <= BITS_PER_WORD
-            && bitsize < BITS_PER_WORD
+      /* Optimize bitfld op= val in certain cases.  */
+      while (mode1 == VOIDmode && !want_value
+            && bitsize > 0 && bitsize < BITS_PER_WORD
             && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD
             && !TREE_SIDE_EFFECTS (to)
             && !TREE_THIS_VOLATILE (to))
        {
          tree src, op0, op1;
-         rtx value;
-         HOST_WIDE_INT count = bitpos;
+         rtx value, str_rtx = to_rtx;
+         HOST_WIDE_INT bitpos1 = bitpos;
          optab binop;
 
          src = from;
@@ -3828,47 +3537,87 @@ expand_assignment (tree to, tree from, int want_value)
          if (! operand_equal_p (to, op0, 0))
            break;
 
+         if (MEM_P (str_rtx))
+           {
+             enum machine_mode mode = GET_MODE (str_rtx);
+             HOST_WIDE_INT offset1;
+
+             if (GET_MODE_BITSIZE (mode) == 0
+                 || GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
+               mode = word_mode;
+             mode = get_best_mode (bitsize, bitpos1, MEM_ALIGN (str_rtx),
+                                   mode, 0);
+             if (mode == VOIDmode)
+               break;
+
+             offset1 = bitpos1;
+             bitpos1 %= GET_MODE_BITSIZE (mode);
+             offset1 = (offset1 - bitpos1) / BITS_PER_UNIT;
+             str_rtx = adjust_address (str_rtx, mode, offset1);
+           }
+         else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG)
+           break;
+
+         /* If the bit field covers the whole REG/MEM, store_field
+            will likely generate better code.  */
+         if (bitsize >= GET_MODE_BITSIZE (GET_MODE (str_rtx)))
+           break;
+
+         /* We can't handle fields split across multiple entities.  */
+         if (bitpos1 + bitsize > GET_MODE_BITSIZE (GET_MODE (str_rtx)))
+           break;
+
          if (BYTES_BIG_ENDIAN)
-           count = GET_MODE_BITSIZE (GET_MODE (to_rtx)) - bitpos - bitsize;
+           bitpos1 = GET_MODE_BITSIZE (GET_MODE (str_rtx)) - bitpos1
+                     - bitsize;
 
          /* Special case some bitfield op= exp.  */
          switch (TREE_CODE (src))
            {
            case PLUS_EXPR:
            case MINUS_EXPR:
-             if (count <= 0)
-               break;
-
              /* For now, just optimize the case of the topmost bitfield
                 where we don't need to do any masking and also
                 1 bit bitfields where xor can be used.
                 We might win by one instruction for the other bitfields
                 too if insv/extv instructions aren't used, so that
                 can be added later.  */
-             if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx))
+             if (bitpos1 + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx))
                  && (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
                break;
-             value = expand_expr (op1, NULL_RTX, VOIDmode, 0);
-             value = protect_from_queue (value, 0);
-             to_rtx = protect_from_queue (to_rtx, 1);
+             value = expand_expr (op1, NULL_RTX, GET_MODE (str_rtx), 0);
+             value = convert_modes (GET_MODE (str_rtx),
+                                    TYPE_MODE (TREE_TYPE (op1)), value,
+                                    TYPE_UNSIGNED (TREE_TYPE (op1)));
+
+             /* We may be accessing data outside the field, which means
+                we can alias adjacent data.  */
+             if (MEM_P (str_rtx))
+               {
+                 str_rtx = shallow_copy_rtx (str_rtx);
+                 set_mem_alias_set (str_rtx, 0);
+                 set_mem_expr (str_rtx, 0);
+               }
+
              binop = TREE_CODE (src) == PLUS_EXPR ? add_optab : sub_optab;
              if (bitsize == 1
-                 && count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+                 && bitpos1 + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx)))
                {
-                 value = expand_and (GET_MODE (to_rtx), value, const1_rtx,
+                 value = expand_and (GET_MODE (str_rtx), value, const1_rtx,
                                      NULL_RTX);
                  binop = xor_optab;
                }
-             value = expand_shift (LSHIFT_EXPR, GET_MODE (to_rtx),
-                                   value, build_int_2 (count, 0),
+             value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx), value,
+                                   build_int_cst (NULL_TREE, bitpos1),
                                    NULL_RTX, 1);
-             result = expand_binop (GET_MODE (to_rtx), binop, to_rtx,
-                                    value, to_rtx, 1, OPTAB_WIDEN);
-             if (result != to_rtx)
-               emit_move_insn (to_rtx, result);
+             result = expand_binop (GET_MODE (str_rtx), binop, str_rtx,
+                                    value, str_rtx, 1, OPTAB_WIDEN);
+             if (result != str_rtx)
+               emit_move_insn (str_rtx, result);
              free_temp_slots ();
              pop_temp_slots ();
              return NULL_RTX;
+
            default:
              break;
            }
@@ -4003,7 +3752,6 @@ expand_assignment (tree to, tree from, int want_value)
 
 /* Generate code for computing expression EXP,
    and storing the value into TARGET.
-   TARGET may contain a QUEUED rtx.
 
    If WANT_VALUE & 1 is nonzero, return a copy of the value
    not in TARGET, so that we can be sure to use the proper
@@ -4032,7 +3780,6 @@ store_expr (tree exp, rtx target, int want_value)
 {
   rtx temp;
   rtx alt_rtl = NULL_RTX;
-  rtx mark = mark_queue ();
   int dont_return_target = 0;
   int dont_store_target = 0;
 
@@ -4041,8 +3788,7 @@ store_expr (tree exp, rtx target, int want_value)
       /* C++ can generate ?: expressions with a throw expression in one
         branch and an rvalue in the other. Here, we resolve attempts to
         store the throw expression's nonexistent result.  */
-      if (want_value)
-       abort ();
+      gcc_assert (!want_value);
       expand_expr (exp, const0_rtx, VOIDmode, 0);
       return NULL_RTX;
     }
@@ -4052,7 +3798,6 @@ store_expr (tree exp, rtx target, int want_value)
         part.  */
       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
                   want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-      emit_queue ();
       return store_expr (TREE_OPERAND (exp, 1), target, want_value);
     }
   else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
@@ -4064,47 +3809,19 @@ store_expr (tree exp, rtx target, int want_value)
 
       rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
 
-      emit_queue ();
-      target = protect_from_queue (target, 1);
-
       do_pending_stack_adjust ();
       NO_DEFER_POP;
       jumpifnot (TREE_OPERAND (exp, 0), lab1);
       store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
-      emit_queue ();
       emit_jump_insn (gen_jump (lab2));
       emit_barrier ();
       emit_label (lab1);
       store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
-      emit_queue ();
       emit_label (lab2);
       OK_DEFER_POP;
 
       return want_value & 1 ? target : NULL_RTX;
     }
-  else if (queued_subexp_p (target))
-    /* If target contains a postincrement, let's not risk
-       using it as the place to generate the rhs.  */
-    {
-      if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
-       {
-         /* Expand EXP into a new pseudo.  */
-         temp = gen_reg_rtx (GET_MODE (target));
-         temp = expand_expr (exp, temp, GET_MODE (target),
-                             (want_value & 2
-                              ? EXPAND_STACK_PARM : EXPAND_NORMAL));
-       }
-      else
-       temp = expand_expr (exp, NULL_RTX, GET_MODE (target),
-                           (want_value & 2
-                            ? EXPAND_STACK_PARM : EXPAND_NORMAL));
-
-      /* If target is volatile, ANSI requires accessing the value
-        *from* the target, if it is accessed.  So make that happen.
-        In no case return the target itself.  */
-      if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0)
-       dont_return_target = 1;
-    }
   else if ((want_value & 1) != 0
           && MEM_P (target)
           && ! MEM_VOLATILE_P (target)
@@ -4146,7 +3863,10 @@ store_expr (tree exp, rtx target, int want_value)
         more than just converting modes.  */
       if ((want_value & 1) == 0
          && INTEGRAL_TYPE_P (TREE_TYPE (exp))
-         && TREE_TYPE (TREE_TYPE (exp)) == 0)
+         && TREE_TYPE (TREE_TYPE (exp)) == 0
+         && (!lang_hooks.reduce_bit_field_operations
+             || (GET_MODE_PRECISION (GET_MODE (target))
+                 == TYPE_PRECISION (TREE_TYPE (exp)))))
        {
          if (TYPE_UNSIGNED (TREE_TYPE (exp))
              != SUBREG_PROMOTED_UNSIGNED_P (target))
@@ -4211,7 +3931,7 @@ store_expr (tree exp, rtx target, int want_value)
   else
     {
       temp = expand_expr_real (exp, target, GET_MODE (target),
-                              (want_value & 2 
+                              (want_value & 2
                                ? EXPAND_STACK_PARM : EXPAND_NORMAL),
                               &alt_rtl);
       /* Return TARGET if it's a specified hardware register.
@@ -4272,9 +3992,6 @@ store_expr (tree exp, rtx target, int want_value)
         bit-initialized.  */
       && expr_size (exp) != const0_rtx)
     {
-      emit_insns_enqueued_after_mark (mark);
-      target = protect_from_queue (target, 1);
-      temp = protect_from_queue (temp, 0);
       if (GET_MODE (temp) != GET_MODE (target)
          && GET_MODE (temp) != VOIDmode)
        {
@@ -4408,7 +4125,7 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
 
   nz_elts = 0;
   nc_elts = 0;
-  
+
   for (list = CONSTRUCTOR_ELTS (ctor); list; list = TREE_CHAIN (list))
     {
       tree value = TREE_VALUE (list);
@@ -4534,8 +4251,7 @@ count_type_elements (tree type)
       return 2;
 
     case VECTOR_TYPE:
-      /* ??? This is broke.  We should encode the vector width in the tree.  */
-      return GET_MODE_NUNITS (TYPE_MODE (type));
+      return TYPE_VECTOR_SUBPARTS (type);
 
     case INTEGER_TYPE:
     case REAL_TYPE:
@@ -4554,7 +4270,7 @@ count_type_elements (tree type)
     case FUNCTION_TYPE:
     case LANG_TYPE:
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -4564,7 +4280,7 @@ int
 mostly_zeros_p (tree exp)
 {
   if (TREE_CODE (exp) == CONSTRUCTOR)
-    
+
     {
       HOST_WIDE_INT nz_elts, nc_elts, elts;
 
@@ -4647,665 +4363,731 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
   HOST_WIDE_INT exp_size = int_size_in_bytes (type);
 #endif
 
-  if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
-      || TREE_CODE (type) == QUAL_UNION_TYPE)
+  switch (TREE_CODE (type))
     {
-      tree elt;
-
-      /* If size is zero or the target is already cleared, do nothing.  */
-      if (size == 0 || cleared)
-       cleared = 1;
-      /* We either clear the aggregate or indicate the value is dead.  */
-      else if ((TREE_CODE (type) == UNION_TYPE
-               || TREE_CODE (type) == QUAL_UNION_TYPE)
-              && ! CONSTRUCTOR_ELTS (exp))
-       /* If the constructor is empty, clear the union.  */
-       {
-         clear_storage (target, expr_size (exp));
-         cleared = 1;
-       }
-
-      /* If we are building a static constructor into a register,
-        set the initial value as zero so we can fold the value into
-        a constant.  But if more than one register is involved,
-        this probably loses.  */
-      else if (REG_P (target) && TREE_STATIC (exp)
-              && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
-       {
-         emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
-         cleared = 1;
-       }
-
-      /* If the constructor has fewer fields than the structure
-        or if we are initializing the structure to mostly zeros,
-        clear the whole structure first.  Don't do this if TARGET is a
-        register whose mode size isn't equal to SIZE since clear_storage
-        can't handle this case.  */
-      else if (size > 0
-              && ((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
-                  || mostly_zeros_p (exp))
-              && (!REG_P (target)
-                  || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
-                      == size)))
-       {
-         rtx xtarget = target;
-
-         if (readonly_fields_p (type))
-           {
-             xtarget = copy_rtx (xtarget);
-             RTX_UNCHANGING_P (xtarget) = 1;
-           }
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+       tree elt;
 
-         clear_storage (xtarget, GEN_INT (size));
+       /* If size is zero or the target is already cleared, do nothing.  */
+       if (size == 0 || cleared)
          cleared = 1;
-       }
-
-      if (! cleared)
-       emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-
-      /* Store each element of the constructor into
-        the corresponding field of TARGET.  */
-
-      for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-       {
-         tree field = TREE_PURPOSE (elt);
-         tree value = TREE_VALUE (elt);
-         enum machine_mode mode;
-         HOST_WIDE_INT bitsize;
-         HOST_WIDE_INT bitpos = 0;
-         tree offset;
-         rtx to_rtx = target;
-
-         /* Just ignore missing fields.
-            We cleared the whole structure, above,
-            if any fields are missing.  */
-         if (field == 0)
-           continue;
-
-         if (cleared && initializer_zerop (value))
-           continue;
-
-         if (host_integerp (DECL_SIZE (field), 1))
-           bitsize = tree_low_cst (DECL_SIZE (field), 1);
-         else
-           bitsize = -1;
-
-         mode = DECL_MODE (field);
-         if (DECL_BIT_FIELD (field))
-           mode = VOIDmode;
+       /* We either clear the aggregate or indicate the value is dead.  */
+       else if ((TREE_CODE (type) == UNION_TYPE
+                 || TREE_CODE (type) == QUAL_UNION_TYPE)
+                && ! CONSTRUCTOR_ELTS (exp))
+         /* If the constructor is empty, clear the union.  */
+         {
+           clear_storage (target, expr_size (exp));
+           cleared = 1;
+         }
 
-         offset = DECL_FIELD_OFFSET (field);
-         if (host_integerp (offset, 0)
-             && host_integerp (bit_position (field), 0))
-           {
-             bitpos = int_bit_position (field);
-             offset = 0;
-           }
-         else
-           bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
+       /* If we are building a static constructor into a register,
+          set the initial value as zero so we can fold the value into
+          a constant.  But if more than one register is involved,
+          this probably loses.  */
+       else if (REG_P (target) && TREE_STATIC (exp)
+                && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
+         {
+           emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
+           cleared = 1;
+         }
 
-         if (offset)
-           {
-             rtx offset_rtx;
+        /* If the constructor has fewer fields than the structure or
+          if we are initializing the structure to mostly zeros, clear
+          the whole structure first.  Don't do this if TARGET is a
+          register whose mode size isn't equal to SIZE since
+          clear_storage can't handle this case.  */
+       else if (size > 0
+                && ((list_length (CONSTRUCTOR_ELTS (exp))
+                     != fields_length (type))
+                    || mostly_zeros_p (exp))
+                && (!REG_P (target)
+                    || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
+                        == size)))
+         {
+           clear_storage (target, GEN_INT (size));
+           cleared = 1;
+         }
 
-             offset
-               = SUBSTITUTE_PLACEHOLDER_IN_EXPR (offset,
-                                                 make_tree (TREE_TYPE (exp),
-                                                            target));
+       if (! cleared)
+         emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
 
-             offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
-             if (!MEM_P (to_rtx))
-               abort ();
+       /* Store each element of the constructor into the
+          corresponding field of TARGET.  */
 
+       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
+         {
+           tree field = TREE_PURPOSE (elt);
+           tree value = TREE_VALUE (elt);
+           enum machine_mode mode;
+           HOST_WIDE_INT bitsize;
+           HOST_WIDE_INT bitpos = 0;
+           tree offset;
+           rtx to_rtx = target;
+           
+           /* Just ignore missing fields.  We cleared the whole
+              structure, above, if any fields are missing.  */
+           if (field == 0)
+             continue;
+           
+           if (cleared && initializer_zerop (value))
+             continue;
+           
+           if (host_integerp (DECL_SIZE (field), 1))
+             bitsize = tree_low_cst (DECL_SIZE (field), 1);
+           else
+             bitsize = -1;
+           
+           mode = DECL_MODE (field);
+           if (DECL_BIT_FIELD (field))
+             mode = VOIDmode;
+           
+           offset = DECL_FIELD_OFFSET (field);
+           if (host_integerp (offset, 0)
+               && host_integerp (bit_position (field), 0))
+             {
+               bitpos = int_bit_position (field);
+               offset = 0;
+             }
+           else
+             bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
+           
+           if (offset)
+             {
+               rtx offset_rtx;
+               
+               offset
+                 = SUBSTITUTE_PLACEHOLDER_IN_EXPR (offset,
+                                                   make_tree (TREE_TYPE (exp),
+                                                              target));
+
+               offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+               gcc_assert (MEM_P (to_rtx));
+               
 #ifdef POINTERS_EXTEND_UNSIGNED
-             if (GET_MODE (offset_rtx) != Pmode)
-               offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
+               if (GET_MODE (offset_rtx) != Pmode)
+                 offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
 #else
-             if (GET_MODE (offset_rtx) != ptr_mode)
-               offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+               if (GET_MODE (offset_rtx) != ptr_mode)
+                 offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
 #endif
 
-             to_rtx = offset_address (to_rtx, offset_rtx,
-                                      highest_pow2_factor (offset));
-           }
+               to_rtx = offset_address (to_rtx, offset_rtx,
+                                        highest_pow2_factor (offset));
+             }
 
-         if (TREE_READONLY (field))
-           {
-             if (MEM_P (to_rtx))
+#ifdef WORD_REGISTER_OPERATIONS
+           /* If this initializes a field that is smaller than a
+              word, at the start of a word, try to widen it to a full
+              word.  This special case allows us to output C++ member
+              function initializations in a form that the optimizers
+              can understand.  */
+           if (REG_P (target)
+               && bitsize < BITS_PER_WORD
+               && bitpos % BITS_PER_WORD == 0
+               && GET_MODE_CLASS (mode) == MODE_INT
+               && TREE_CODE (value) == INTEGER_CST
+               && exp_size >= 0
+               && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
+             {
+               tree type = TREE_TYPE (value);
+               
+               if (TYPE_PRECISION (type) < BITS_PER_WORD)
+                 {
+                   type = lang_hooks.types.type_for_size
+                     (BITS_PER_WORD, TYPE_UNSIGNED (type));
+                   value = convert (type, value);
+                 }
+               
+               if (BYTES_BIG_ENDIAN)
+                 value
+                   = fold (build2 (LSHIFT_EXPR, type, value,
+                                   build_int_cst (NULL_TREE,
+                                                  BITS_PER_WORD - bitsize)));
+               bitsize = BITS_PER_WORD;
+               mode = word_mode;
+             }
+#endif
+
+           if (MEM_P (to_rtx) && !MEM_KEEP_ALIAS_SET_P (to_rtx)
+               && DECL_NONADDRESSABLE_P (field))
+             {
                to_rtx = copy_rtx (to_rtx);
+               MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
+             }
+           
+           store_constructor_field (to_rtx, bitsize, bitpos, mode,
+                                    value, type, cleared,
+                                    get_alias_set (TREE_TYPE (field)));
+         }
+       break;
+      }
+    case ARRAY_TYPE:
+      {
+       tree elt;
+       int i;
+       int need_to_clear;
+       tree domain;
+       tree elttype = TREE_TYPE (type);
+       int const_bounds_p;
+       HOST_WIDE_INT minelt = 0;
+       HOST_WIDE_INT maxelt = 0;
 
-             RTX_UNCHANGING_P (to_rtx) = 1;
-           }
+       domain = TYPE_DOMAIN (type);
+       const_bounds_p = (TYPE_MIN_VALUE (domain)
+                         && TYPE_MAX_VALUE (domain)
+                         && host_integerp (TYPE_MIN_VALUE (domain), 0)
+                         && host_integerp (TYPE_MAX_VALUE (domain), 0));
 
-#ifdef WORD_REGISTER_OPERATIONS
-         /* If this initializes a field that is smaller than a word, at the
-            start of a word, try to widen it to a full word.
-            This special case allows us to output C++ member function
-            initializations in a form that the optimizers can understand.  */
-         if (REG_P (target)
-             && bitsize < BITS_PER_WORD
-             && bitpos % BITS_PER_WORD == 0
-             && GET_MODE_CLASS (mode) == MODE_INT
-             && TREE_CODE (value) == INTEGER_CST
-             && exp_size >= 0
-             && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
-           {
-             tree type = TREE_TYPE (value);
+       /* If we have constant bounds for the range of the type, get them.  */
+       if (const_bounds_p)
+         {
+           minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
+           maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
+         }
 
-             if (TYPE_PRECISION (type) < BITS_PER_WORD)
-               {
-                 type = lang_hooks.types.type_for_size
-                   (BITS_PER_WORD, TYPE_UNSIGNED (type));
-                 value = convert (type, value);
-               }
-
-             if (BYTES_BIG_ENDIAN)
-               value
-                 = fold (build (LSHIFT_EXPR, type, value,
-                                build_int_2 (BITS_PER_WORD - bitsize, 0)));
-             bitsize = BITS_PER_WORD;
-             mode = word_mode;
-           }
-#endif
-
-         if (MEM_P (to_rtx) && !MEM_KEEP_ALIAS_SET_P (to_rtx)
-             && DECL_NONADDRESSABLE_P (field))
-           {
-             to_rtx = copy_rtx (to_rtx);
-             MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
-           }
-
-         store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                  value, type, cleared,
-                                  get_alias_set (TREE_TYPE (field)));
-       }
-    }
-  else if (TREE_CODE (type) == ARRAY_TYPE
-          || TREE_CODE (type) == VECTOR_TYPE)
-    {
-      tree elt;
-      int i;
-      int need_to_clear;
-      tree domain;
-      tree elttype = TREE_TYPE (type);
-      int const_bounds_p;
-      HOST_WIDE_INT minelt = 0;
-      HOST_WIDE_INT maxelt = 0;
-      int icode = 0;
-      rtx *vector = NULL;
-      int elt_size = 0;
-      unsigned n_elts = 0;
-
-      if (TREE_CODE (type) == ARRAY_TYPE)
-       domain = TYPE_DOMAIN (type);
-      else
-       /* Vectors do not have domains; look up the domain of
-          the array embedded in the debug representation type.
-          FIXME Would probably be more efficient to treat vectors
-          separately from arrays.  */
-       {
-         domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-         domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
-         if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
-           {
-             enum machine_mode mode = GET_MODE (target);
-
-             icode = (int) vec_init_optab->handlers[mode].insn_code;
-             if (icode != CODE_FOR_nothing)
-               {
-                 unsigned int i;
+       /* If the constructor has fewer elements than the array, clear
+           the whole array first.  Similarly if this is static
+           constructor of a non-BLKmode object.  */
+       if (cleared)
+         need_to_clear = 0;
+       else if (REG_P (target) && TREE_STATIC (exp))
+         need_to_clear = 1;
+       else
+         {
+           HOST_WIDE_INT count = 0, zero_count = 0;
+           need_to_clear = ! const_bounds_p;
+           
+           /* This loop is a more accurate version of the loop in
+              mostly_zeros_p (it handles RANGE_EXPR in an index).  It
+              is also needed to check for missing elements.  */
+           for (elt = CONSTRUCTOR_ELTS (exp);
+                elt != NULL_TREE && ! need_to_clear;
+                elt = TREE_CHAIN (elt))
+             {
+               tree index = TREE_PURPOSE (elt);
+               HOST_WIDE_INT this_node_count;
+               
+               if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
+                 {
+                   tree lo_index = TREE_OPERAND (index, 0);
+                   tree hi_index = TREE_OPERAND (index, 1);
+                   
+                   if (! host_integerp (lo_index, 1)
+                       || ! host_integerp (hi_index, 1))
+                     {
+                       need_to_clear = 1;
+                       break;
+                     }
+                   
+                   this_node_count = (tree_low_cst (hi_index, 1)
+                                      - tree_low_cst (lo_index, 1) + 1);
+                 }
+               else
+                 this_node_count = 1;
+               
+               count += this_node_count;
+               if (mostly_zeros_p (TREE_VALUE (elt)))
+                 zero_count += this_node_count;
+             }
+           
+           /* Clear the entire array first if there are any missing
+              elements, or if the incidence of zero elements is >=
+              75%.  */
+           if (! need_to_clear
+               && (count < maxelt - minelt + 1
+                   || 4 * zero_count >= 3 * count))
+             need_to_clear = 1;
+         }
+       
+       if (need_to_clear && size > 0)
+         {
+           if (REG_P (target))
+             emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
+           else
+             clear_storage (target, GEN_INT (size));
+           cleared = 1;
+         }
 
-                 elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
-                 n_elts = (GET_MODE_SIZE (mode) / elt_size);
-                 vector = alloca (n_elts);
-                 for (i = 0; i < n_elts; i++)
-                   vector [i] = CONST0_RTX (GET_MODE_INNER (mode));
-               }
-           }
-       }
+       if (!cleared && REG_P (target))
+         /* Inform later passes that the old value is dead.  */
+         emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
 
-      const_bounds_p = (TYPE_MIN_VALUE (domain)
-                       && TYPE_MAX_VALUE (domain)
-                       && host_integerp (TYPE_MIN_VALUE (domain), 0)
-                       && host_integerp (TYPE_MAX_VALUE (domain), 0));
+       /* Store each element of the constructor into the
+          corresponding element of TARGET, determined by counting the
+          elements.  */
+       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
+            elt;
+            elt = TREE_CHAIN (elt), i++)
+         {
+           enum machine_mode mode;
+           HOST_WIDE_INT bitsize;
+           HOST_WIDE_INT bitpos;
+           int unsignedp;
+           tree value = TREE_VALUE (elt);
+           tree index = TREE_PURPOSE (elt);
+           rtx xtarget = target;
+           
+           if (cleared && initializer_zerop (value))
+             continue;
+           
+           unsignedp = TYPE_UNSIGNED (elttype);
+           mode = TYPE_MODE (elttype);
+           if (mode == BLKmode)
+             bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
+                        ? tree_low_cst (TYPE_SIZE (elttype), 1)
+                        : -1);
+           else
+             bitsize = GET_MODE_BITSIZE (mode);
+           
+           if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
+             {
+               tree lo_index = TREE_OPERAND (index, 0);
+               tree hi_index = TREE_OPERAND (index, 1);
+               rtx index_r, pos_rtx;
+               HOST_WIDE_INT lo, hi, count;
+               tree position;
+               
+               /* If the range is constant and "small", unroll the loop.  */
+               if (const_bounds_p
+                   && host_integerp (lo_index, 0)
+                   && host_integerp (hi_index, 0)
+                   && (lo = tree_low_cst (lo_index, 0),
+                       hi = tree_low_cst (hi_index, 0),
+                       count = hi - lo + 1,
+                       (!MEM_P (target)
+                        || count <= 2
+                        || (host_integerp (TYPE_SIZE (elttype), 1)
+                            && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
+                                <= 40 * 8)))))
+                 {
+                   lo -= minelt;  hi -= minelt;
+                   for (; lo <= hi; lo++)
+                     {
+                       bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
+                       
+                       if (MEM_P (target)
+                           && !MEM_KEEP_ALIAS_SET_P (target)
+                           && TREE_CODE (type) == ARRAY_TYPE
+                           && TYPE_NONALIASED_COMPONENT (type))
+                         {
+                           target = copy_rtx (target);
+                           MEM_KEEP_ALIAS_SET_P (target) = 1;
+                         }
+                       
+                       store_constructor_field
+                         (target, bitsize, bitpos, mode, value, type, cleared,
+                          get_alias_set (elttype));
+                     }
+                 }
+               else
+                 {
+                   rtx loop_start = gen_label_rtx ();
+                   rtx loop_end = gen_label_rtx ();
+                   tree exit_cond;
+                   
+                   expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
+                   unsignedp = TYPE_UNSIGNED (domain);
+                   
+                   index = build_decl (VAR_DECL, NULL_TREE, domain);
+                   
+                   index_r
+                     = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
+                                                  &unsignedp, 0));
+                   SET_DECL_RTL (index, index_r);
+                   store_expr (lo_index, index_r, 0);
+                   
+                   /* Build the head of the loop.  */
+                   do_pending_stack_adjust ();
+                   emit_label (loop_start);
+
+                   /* Assign value to element index.  */
+                   position
+                     = convert (ssizetype,
+                                fold (build2 (MINUS_EXPR, TREE_TYPE (index),
+                                              index, TYPE_MIN_VALUE (domain))));
+                   position = size_binop (MULT_EXPR, position,
+                                          convert (ssizetype,
+                                                   TYPE_SIZE_UNIT (elttype)));
+                   
+                   pos_rtx = expand_expr (position, 0, VOIDmode, 0);
+                   xtarget = offset_address (target, pos_rtx,
+                                             highest_pow2_factor (position));
+                   xtarget = adjust_address (xtarget, mode, 0);
+                   if (TREE_CODE (value) == CONSTRUCTOR)
+                     store_constructor (value, xtarget, cleared,
+                                        bitsize / BITS_PER_UNIT);
+                   else
+                     store_expr (value, xtarget, 0);
 
-      /* If we have constant bounds for the range of the type, get them.  */
-      if (const_bounds_p)
-       {
-         minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
-         maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
-       }
+                   /* Generate a conditional jump to exit the loop.  */
+                   exit_cond = build2 (LT_EXPR, integer_type_node,
+                                       index, hi_index);
+                   jumpif (exit_cond, loop_end);
+                   
+                   /* Update the loop counter, and jump to the head of
+                      the loop.  */
+                   expand_assignment (index,
+                                      build2 (PLUS_EXPR, TREE_TYPE (index),
+                                              index, integer_one_node), 0);
+                   
+                   emit_jump (loop_start);
+                   
+                   /* Build the end of the loop.  */
+                   emit_label (loop_end);
+                 }
+             }
+           else if ((index != 0 && ! host_integerp (index, 0))
+                    || ! host_integerp (TYPE_SIZE (elttype), 1))
+             {
+               tree position;
+               
+               if (index == 0)
+                 index = ssize_int (1);
+               
+               if (minelt)
+                 index = fold_convert (ssizetype,
+                                       fold (build2 (MINUS_EXPR,
+                                                     TREE_TYPE (index),
+                                                     index,
+                                                     TYPE_MIN_VALUE (domain))));
+               
+               position = size_binop (MULT_EXPR, index,
+                                      convert (ssizetype,
+                                               TYPE_SIZE_UNIT (elttype)));
+               xtarget = offset_address (target,
+                                         expand_expr (position, 0, VOIDmode, 0),
+                                         highest_pow2_factor (position));
+               xtarget = adjust_address (xtarget, mode, 0);
+               store_expr (value, xtarget, 0);
+             }
+           else
+             {
+               if (index != 0)
+                 bitpos = ((tree_low_cst (index, 0) - minelt)
+                           * tree_low_cst (TYPE_SIZE (elttype), 1));
+               else
+                 bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
+               
+               if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
+                   && TREE_CODE (type) == ARRAY_TYPE
+                   && TYPE_NONALIASED_COMPONENT (type))
+                 {
+                   target = copy_rtx (target);
+                   MEM_KEEP_ALIAS_SET_P (target) = 1;
+                 }
+               store_constructor_field (target, bitsize, bitpos, mode, value,
+                                        type, cleared, get_alias_set (elttype));
+             }
+         }
+       break;
+      }
 
-      /* If the constructor has fewer elements than the array,
-         clear the whole array first.  Similarly if this is
-         static constructor of a non-BLKmode object.  */
-      if (cleared || (REG_P (target) && TREE_STATIC (exp)))
-       need_to_clear = 1;
-      else
-       {
-         HOST_WIDE_INT count = 0, zero_count = 0;
-         need_to_clear = ! const_bounds_p;
-
-         /* This loop is a more accurate version of the loop in
-            mostly_zeros_p (it handles RANGE_EXPR in an index).
-            It is also needed to check for missing elements.  */
-         for (elt = CONSTRUCTOR_ELTS (exp);
-              elt != NULL_TREE && ! need_to_clear;
-              elt = TREE_CHAIN (elt))
-           {
-             tree index = TREE_PURPOSE (elt);
-             HOST_WIDE_INT this_node_count;
+    case VECTOR_TYPE:
+      {
+       tree elt;
+       int i;
+       int need_to_clear;
+       int icode = 0;
+       tree elttype = TREE_TYPE (type);
+       int elt_size = tree_low_cst (TYPE_SIZE (elttype), 1);
+       enum machine_mode eltmode = TYPE_MODE (elttype);
+       HOST_WIDE_INT bitsize;
+       HOST_WIDE_INT bitpos;
+       rtx *vector = NULL;
+       unsigned n_elts;
+       
+       gcc_assert (eltmode != BLKmode);
+       
+       n_elts = TYPE_VECTOR_SUBPARTS (type);
+       if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
+         {
+           enum machine_mode mode = GET_MODE (target);
+           
+           icode = (int) vec_init_optab->handlers[mode].insn_code;
+           if (icode != CODE_FOR_nothing)
+             {
+               unsigned int i;
+               
+               vector = alloca (n_elts);
+               for (i = 0; i < n_elts; i++)
+                 vector [i] = CONST0_RTX (GET_MODE_INNER (mode));
+             }
+         }
+       
+       /* If the constructor has fewer elements than the vector,
+          clear the whole array first.  Similarly if this is static
+          constructor of a non-BLKmode object.  */
+       if (cleared)
+         need_to_clear = 0;
+       else if (REG_P (target) && TREE_STATIC (exp))
+         need_to_clear = 1;
+       else
+         {
+           unsigned HOST_WIDE_INT count = 0, zero_count = 0;
+           
+           for (elt = CONSTRUCTOR_ELTS (exp);
+                elt != NULL_TREE;
+                elt = TREE_CHAIN (elt))
+             {
+               int n_elts_here = tree_low_cst
+                 (int_const_binop (TRUNC_DIV_EXPR,
+                                   TYPE_SIZE (TREE_TYPE (TREE_VALUE (elt))),
+                                   TYPE_SIZE (elttype), 0), 1);
+               
+               count += n_elts_here;
+               if (mostly_zeros_p (TREE_VALUE (elt)))
+                 zero_count += n_elts_here;
+             }
 
-             if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
-               {
-                 tree lo_index = TREE_OPERAND (index, 0);
-                 tree hi_index = TREE_OPERAND (index, 1);
+           /* Clear the entire vector first if there are any missing elements,
+              or if the incidence of zero elements is >= 75%.  */
+           need_to_clear = (count < n_elts || 4 * zero_count >= 3 * count);
+         }
+       
+       if (need_to_clear && size > 0 && !vector)
+         {
+           if (REG_P (target))
+             emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
+           else
+             clear_storage (target, GEN_INT (size));
+           cleared = 1;
+         }
+       
+       if (!cleared && REG_P (target))
+         /* Inform later passes that the old value is dead.  */
+         emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+
+        /* Store each element of the constructor into the corresponding
+          element of TARGET, determined by counting the elements.  */
+       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
+            elt;
+            elt = TREE_CHAIN (elt), i += bitsize / elt_size)
+         {
+           tree value = TREE_VALUE (elt);
+           tree index = TREE_PURPOSE (elt);
+           HOST_WIDE_INT eltpos;
+           
+           bitsize = tree_low_cst (TYPE_SIZE (TREE_TYPE (value)), 1);
+           if (cleared && initializer_zerop (value))
+             continue;
+           
+           if (index != 0)
+             eltpos = tree_low_cst (index, 1);
+           else
+             eltpos = i;
+           
+           if (vector)
+             {
+               /* Vector CONSTRUCTORs should only be built from smaller
+                  vectors in the case of BLKmode vectors.  */
+               gcc_assert (TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE);
+               vector[eltpos] = expand_expr (value, NULL_RTX, VOIDmode, 0);
+             }
+           else
+             {
+               enum machine_mode value_mode =
+                 TREE_CODE (TREE_TYPE (value)) == VECTOR_TYPE
+                 ? TYPE_MODE (TREE_TYPE (value))
+                 : eltmode;
+               bitpos = eltpos * elt_size;
+               store_constructor_field (target, bitsize, bitpos,
+                                        value_mode, value, type,
+                                        cleared, get_alias_set (elttype));
+             }
+         }
+       
+       if (vector)
+         emit_insn (GEN_FCN (icode)
+                    (target,
+                     gen_rtx_PARALLEL (GET_MODE (target),
+                                       gen_rtvec_v (n_elts, vector))));
+       break;
+      }
 
-                 if (! host_integerp (lo_index, 1)
-                     || ! host_integerp (hi_index, 1))
-                   {
-                     need_to_clear = 1;
+      /* Set constructor assignments.  */
+    case SET_TYPE:
+      {
+       tree elt = CONSTRUCTOR_ELTS (exp);
+       unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
+       tree domain = TYPE_DOMAIN (type);
+       tree domain_min, domain_max, bitlength;
+       
+       /* The default implementation strategy is to extract the
+          constant parts of the constructor, use that to initialize
+          the target, and then "or" in whatever non-constant ranges
+          we need in addition.
+
+          If a large set is all zero or all ones, it is probably
+          better to set it using memset.  Also, if a large set has
+          just a single range, it may also be better to first clear
+          all the first clear the set (using memset), and set the
+          bits we want.  */
+
+       /* Check for all zeros.  */
+       if (elt == NULL_TREE && size > 0)
+         {
+           if (!cleared)
+             clear_storage (target, GEN_INT (size));
+           return;
+         }
+       
+       domain_min = convert (sizetype, TYPE_MIN_VALUE (domain));
+       domain_max = convert (sizetype, TYPE_MAX_VALUE (domain));
+       bitlength = size_binop (PLUS_EXPR,
+                               size_diffop (domain_max, domain_min),
+                               ssize_int (1));
+       
+       nbits = tree_low_cst (bitlength, 1);
+
+        /* For "small" sets, or "medium-sized" (up to 32 bytes) sets
+          that are "complicated" (more than one range), initialize
+          (the constant parts) by copying from a constant.  */
+       if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
+           || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
+         {
+           unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
+           enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
+           char *bit_buffer = alloca (nbits);
+           HOST_WIDE_INT word = 0;
+           unsigned int bit_pos = 0;
+           unsigned int ibit = 0;
+           unsigned int offset = 0;  /* In bytes from beginning of set.  */
+           
+           elt = get_set_constructor_bits (exp, bit_buffer, nbits);
+           for (;;)
+             {
+               if (bit_buffer[ibit])
+                 {
+                   if (BYTES_BIG_ENDIAN)
+                     word |= (1 << (set_word_size - 1 - bit_pos));
+                   else
+                     word |= 1 << bit_pos;
+                 }
+               
+               bit_pos++;  ibit++;
+               if (bit_pos >= set_word_size || ibit == nbits)
+                 {
+                   if (word != 0 || ! cleared)
+                     {
+                       rtx datum = gen_int_mode (word, mode);
+                       rtx to_rtx;
+                       
+                       /* The assumption here is that it is safe to
+                          use XEXP if the set is multi-word, but not
+                          if it's single-word.  */
+                       if (MEM_P (target))
+                         to_rtx = adjust_address (target, mode, offset);
+                       else
+                         {
+                           gcc_assert (!offset);
+                           to_rtx = target;
+                         }
+                       emit_move_insn (to_rtx, datum);
+                     }
+                   
+                   if (ibit == nbits)
                      break;
-                   }
-
-                 this_node_count = (tree_low_cst (hi_index, 1)
-                                    - tree_low_cst (lo_index, 1) + 1);
-               }
-             else
-               this_node_count = 1;
-
-             count += this_node_count;
-             if (mostly_zeros_p (TREE_VALUE (elt)))
-               zero_count += this_node_count;
-           }
-
-         /* Clear the entire array first if there are any missing elements,
-            or if the incidence of zero elements is >= 75%.  */
-         if (! need_to_clear
-             && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
-           need_to_clear = 1;
-       }
-
-      if (need_to_clear && size > 0 && !vector)
-       {
-         if (! cleared)
-           {
-             if (REG_P (target))
-               emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
-             else
-               clear_storage (target, GEN_INT (size));
-           }
-         cleared = 1;
-       }
-      else if (REG_P (target))
-       /* Inform later passes that the old value is dead.  */
-       emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-
-      /* Store each element of the constructor into
-        the corresponding element of TARGET, determined
-        by counting the elements.  */
-      for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
-          elt;
-          elt = TREE_CHAIN (elt), i++)
-       {
-         enum machine_mode mode;
-         HOST_WIDE_INT bitsize;
-         HOST_WIDE_INT bitpos;
-         int unsignedp;
-         tree value = TREE_VALUE (elt);
-         tree index = TREE_PURPOSE (elt);
-         rtx xtarget = target;
-
-         if (cleared && initializer_zerop (value))
-           continue;
-
-         unsignedp = TYPE_UNSIGNED (elttype);
-         mode = TYPE_MODE (elttype);
-         if (mode == BLKmode)
-           bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
-                      ? tree_low_cst (TYPE_SIZE (elttype), 1)
-                      : -1);
-         else
-           bitsize = GET_MODE_BITSIZE (mode);
-
-         if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
-           {
-             tree lo_index = TREE_OPERAND (index, 0);
-             tree hi_index = TREE_OPERAND (index, 1);
-             rtx index_r, pos_rtx;
-             HOST_WIDE_INT lo, hi, count;
-             tree position;
-
-             if (vector)
-               abort ();
-
-             /* If the range is constant and "small", unroll the loop.  */
-             if (const_bounds_p
-                 && host_integerp (lo_index, 0)
-                 && host_integerp (hi_index, 0)
-                 && (lo = tree_low_cst (lo_index, 0),
-                     hi = tree_low_cst (hi_index, 0),
-                     count = hi - lo + 1,
-                     (!MEM_P (target)
-                      || count <= 2
-                      || (host_integerp (TYPE_SIZE (elttype), 1)
-                          && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
-                              <= 40 * 8)))))
-               {
-                 lo -= minelt;  hi -= minelt;
-                 for (; lo <= hi; lo++)
-                   {
-                     bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
-
-                     if (MEM_P (target)
-                         && !MEM_KEEP_ALIAS_SET_P (target)
-                         && TREE_CODE (type) == ARRAY_TYPE
-                         && TYPE_NONALIASED_COMPONENT (type))
-                       {
-                         target = copy_rtx (target);
-                         MEM_KEEP_ALIAS_SET_P (target) = 1;
-                       }
-
-                     store_constructor_field
-                       (target, bitsize, bitpos, mode, value, type, cleared,
-                        get_alias_set (elttype));
-                   }
-               }
-             else
-               {
-                 rtx loop_start = gen_label_rtx ();
-                 rtx loop_end = gen_label_rtx ();
-                 tree exit_cond;
-
-                 expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
-                 unsignedp = TYPE_UNSIGNED (domain);
-
-                 index = build_decl (VAR_DECL, NULL_TREE, domain);
-
-                 index_r
-                   = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
-                                                &unsignedp, 0));
-                 SET_DECL_RTL (index, index_r);
-                 store_expr (lo_index, index_r, 0);
-
-                 /* Build the head of the loop.  */
-                 do_pending_stack_adjust ();
-                 emit_queue ();
-                 emit_label (loop_start);
-
-                 /* Assign value to element index.  */
-                 position
-                   = convert (ssizetype,
-                              fold (build (MINUS_EXPR, TREE_TYPE (index),
-                                           index, TYPE_MIN_VALUE (domain))));
-                 position = size_binop (MULT_EXPR, position,
-                                        convert (ssizetype,
-                                                 TYPE_SIZE_UNIT (elttype)));
-
-                 pos_rtx = expand_expr (position, 0, VOIDmode, 0);
-                 xtarget = offset_address (target, pos_rtx,
-                                           highest_pow2_factor (position));
-                 xtarget = adjust_address (xtarget, mode, 0);
-                 if (TREE_CODE (value) == CONSTRUCTOR)
-                   store_constructor (value, xtarget, cleared,
-                                      bitsize / BITS_PER_UNIT);
-                 else
-                   store_expr (value, xtarget, 0);
-
-                 /* Generate a conditional jump to exit the loop.  */
-                 exit_cond = build (LT_EXPR, integer_type_node,
-                                    index, hi_index);
-                 jumpif (exit_cond, loop_end);
-
-                 /* Update the loop counter, and jump to the head of
-                    the loop.  */
-                 expand_increment (build (PREINCREMENT_EXPR,
-                                          TREE_TYPE (index),
-                                          index, integer_one_node), 0, 0);
-                 emit_jump (loop_start);
-
-                 /* Build the end of the loop.  */
-                 emit_label (loop_end);
-               }
-           }
-         else if ((index != 0 && ! host_integerp (index, 0))
-                  || ! host_integerp (TYPE_SIZE (elttype), 1))
-           {
-             tree position;
-
-             if (vector)
-               abort ();
-
-             if (index == 0)
-               index = ssize_int (1);
-
-             if (minelt)
-               index = convert (ssizetype,
-                                fold (build (MINUS_EXPR, index,
-                                             TYPE_MIN_VALUE (domain))));
-
-             position = size_binop (MULT_EXPR, index,
-                                    convert (ssizetype,
-                                             TYPE_SIZE_UNIT (elttype)));
-             xtarget = offset_address (target,
-                                       expand_expr (position, 0, VOIDmode, 0),
-                                       highest_pow2_factor (position));
-             xtarget = adjust_address (xtarget, mode, 0);
-             store_expr (value, xtarget, 0);
-           }
-         else if (vector)
-           {
-             int pos;
-
-             if (index != 0)
-               pos = tree_low_cst (index, 0) - minelt;
-             else
-               pos = i;
-             vector[pos] = expand_expr (value, NULL_RTX, VOIDmode, 0);
-           }
-         else
-           {
-             if (index != 0)
-               bitpos = ((tree_low_cst (index, 0) - minelt)
-                         * tree_low_cst (TYPE_SIZE (elttype), 1));
-             else
-               bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
-
-             if (MEM_P (target) && !MEM_KEEP_ALIAS_SET_P (target)
-                 && TREE_CODE (type) == ARRAY_TYPE
-                 && TYPE_NONALIASED_COMPONENT (type))
-               {
-                 target = copy_rtx (target);
-                 MEM_KEEP_ALIAS_SET_P (target) = 1;
-               }
-             store_constructor_field (target, bitsize, bitpos, mode, value,
-                                      type, cleared, get_alias_set (elttype));
-           }
-       }
-      if (vector)
-       {
-         emit_insn (GEN_FCN (icode) (target,
-                                     gen_rtx_PARALLEL (GET_MODE (target),
-                                                       gen_rtvec_v (n_elts, vector))));
-       }
-    }
-
-  /* Set constructor assignments.  */
-  else if (TREE_CODE (type) == SET_TYPE)
-    {
-      tree elt = CONSTRUCTOR_ELTS (exp);
-      unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
-      tree domain = TYPE_DOMAIN (type);
-      tree domain_min, domain_max, bitlength;
-
-      /* The default implementation strategy is to extract the constant
-        parts of the constructor, use that to initialize the target,
-        and then "or" in whatever non-constant ranges we need in addition.
-
-        If a large set is all zero or all ones, it is
-        probably better to set it using memset.
-        Also, if a large set has just a single range, it may also be
-        better to first clear all the first clear the set (using
-        memset), and set the bits we want.  */
-
-      /* Check for all zeros.  */
-      if (elt == NULL_TREE && size > 0)
-       {
-         if (!cleared)
-           clear_storage (target, GEN_INT (size));
-         return;
-       }
-
-      domain_min = convert (sizetype, TYPE_MIN_VALUE (domain));
-      domain_max = convert (sizetype, TYPE_MAX_VALUE (domain));
-      bitlength = size_binop (PLUS_EXPR,
-                             size_diffop (domain_max, domain_min),
-                             ssize_int (1));
-
-      nbits = tree_low_cst (bitlength, 1);
-
-      /* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
-        are "complicated" (more than one range), initialize (the
-        constant parts) by copying from a constant.  */
-      if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
-         || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
-       {
-         unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
-         enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
-         char *bit_buffer = alloca (nbits);
-         HOST_WIDE_INT word = 0;
-         unsigned int bit_pos = 0;
-         unsigned int ibit = 0;
-         unsigned int offset = 0;  /* In bytes from beginning of set.  */
-
-         elt = get_set_constructor_bits (exp, bit_buffer, nbits);
-         for (;;)
-           {
-             if (bit_buffer[ibit])
-               {
-                 if (BYTES_BIG_ENDIAN)
-                   word |= (1 << (set_word_size - 1 - bit_pos));
-                 else
-                   word |= 1 << bit_pos;
-               }
-
-             bit_pos++;  ibit++;
-             if (bit_pos >= set_word_size || ibit == nbits)
-               {
-                 if (word != 0 || ! cleared)
-                   {
-                     rtx datum = gen_int_mode (word, mode);
-                     rtx to_rtx;
-
-                     /* The assumption here is that it is safe to use
-                        XEXP if the set is multi-word, but not if
-                        it's single-word.  */
-                     if (MEM_P (target))
-                       to_rtx = adjust_address (target, mode, offset);
-                     else if (offset == 0)
-                       to_rtx = target;
-                     else
-                       abort ();
-                     emit_move_insn (to_rtx, datum);
-                   }
-
-                 if (ibit == nbits)
-                   break;
-                 word = 0;
-                 bit_pos = 0;
-                 offset += set_word_size / BITS_PER_UNIT;
-               }
-           }
-       }
-      else if (!cleared)
-       /* Don't bother clearing storage if the set is all ones.  */
-       if (TREE_CHAIN (elt) != NULL_TREE
-           || (TREE_PURPOSE (elt) == NULL_TREE
-               ? nbits != 1
-               : ( ! host_integerp (TREE_VALUE (elt), 0)
-                  || ! host_integerp (TREE_PURPOSE (elt), 0)
-                  || (tree_low_cst (TREE_VALUE (elt), 0)
-                      - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
-                      != (HOST_WIDE_INT) nbits))))
-         clear_storage (target, expr_size (exp));
-
-      for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
-       {
-         /* Start of range of element or NULL.  */
-         tree startbit = TREE_PURPOSE (elt);
-         /* End of range of element, or element value.  */
-         tree endbit   = TREE_VALUE (elt);
-         HOST_WIDE_INT startb, endb;
-         rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
-
-         bitlength_rtx = expand_expr (bitlength,
-                                      NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
-
-         /* Handle non-range tuple element like [ expr ].  */
-         if (startbit == NULL_TREE)
-           {
-             startbit = save_expr (endbit);
-             endbit = startbit;
-           }
-
-         startbit = convert (sizetype, startbit);
-         endbit = convert (sizetype, endbit);
-         if (! integer_zerop (domain_min))
-           {
-             startbit = size_binop (MINUS_EXPR, startbit, domain_min);
-             endbit = size_binop (MINUS_EXPR, endbit, domain_min);
-           }
-         startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
+                   word = 0;
+                   bit_pos = 0;
+                   offset += set_word_size / BITS_PER_UNIT;
+                 }
+             }
+         }
+       else if (!cleared)
+         /* Don't bother clearing storage if the set is all ones.  */
+         if (TREE_CHAIN (elt) != NULL_TREE
+             || (TREE_PURPOSE (elt) == NULL_TREE
+                 ? nbits != 1
+                 : ( ! host_integerp (TREE_VALUE (elt), 0)
+                     || ! host_integerp (TREE_PURPOSE (elt), 0)
+                     || (tree_low_cst (TREE_VALUE (elt), 0)
+                         - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
+                         != (HOST_WIDE_INT) nbits))))
+           clear_storage (target, expr_size (exp));
+       
+       for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
+         {
+           /* Start of range of element or NULL.  */
+           tree startbit = TREE_PURPOSE (elt);
+           /* End of range of element, or element value.  */
+           tree endbit   = TREE_VALUE (elt);
+           HOST_WIDE_INT startb, endb;
+           rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
+           
+           bitlength_rtx = expand_expr (bitlength,
+                                        NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
+           
+           /* Handle non-range tuple element like [ expr ].  */
+           if (startbit == NULL_TREE)
+             {
+               startbit = save_expr (endbit);
+               endbit = startbit;
+             }
+           
+           startbit = convert (sizetype, startbit);
+           endbit = convert (sizetype, endbit);
+           if (! integer_zerop (domain_min))
+             {
+               startbit = size_binop (MINUS_EXPR, startbit, domain_min);
+               endbit = size_binop (MINUS_EXPR, endbit, domain_min);
+             }
+           startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
+                                       EXPAND_CONST_ADDRESS);
+           endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
                                      EXPAND_CONST_ADDRESS);
-         endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
-                                   EXPAND_CONST_ADDRESS);
-
-         if (REG_P (target))
-           {
-             targetx
-               = assign_temp
+           
+           if (REG_P (target))
+             {
+               targetx
+                 = assign_temp
                  ((build_qualified_type (lang_hooks.types.type_for_mode
                                          (GET_MODE (target), 0),
                                          TYPE_QUAL_CONST)),
                   0, 1, 1);
-             emit_move_insn (targetx, target);
-           }
+               emit_move_insn (targetx, target);
+             }
+           
+           else
+             {
+               gcc_assert (MEM_P (target));
+               targetx = target;
+             }
 
-         else if (MEM_P (target))
-           targetx = target;
-         else
-           abort ();
-
-         /* Optimization:  If startbit and endbit are constants divisible
-            by BITS_PER_UNIT, call memset instead.  */
-         if (TREE_CODE (startbit) == INTEGER_CST
-             && TREE_CODE (endbit) == INTEGER_CST
-             && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
-             && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
-           {
-             emit_library_call (memset_libfunc, LCT_NORMAL,
-                                VOIDmode, 3,
-                                plus_constant (XEXP (targetx, 0),
-                                               startb / BITS_PER_UNIT),
-                                Pmode,
-                                constm1_rtx, TYPE_MODE (integer_type_node),
-                                GEN_INT ((endb - startb) / BITS_PER_UNIT),
-                                TYPE_MODE (sizetype));
-           }
-         else
-           emit_library_call (setbits_libfunc, LCT_NORMAL,
-                              VOIDmode, 4, XEXP (targetx, 0),
-                              Pmode, bitlength_rtx, TYPE_MODE (sizetype),
-                              startbit_rtx, TYPE_MODE (sizetype),
-                              endbit_rtx, TYPE_MODE (sizetype));
-
-         if (REG_P (target))
-           emit_move_insn (target, targetx);
-       }
+           /* Optimization:  If startbit and endbit are constants divisible
+              by BITS_PER_UNIT, call memset instead.  */
+           if (TREE_CODE (startbit) == INTEGER_CST
+               && TREE_CODE (endbit) == INTEGER_CST
+               && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
+               && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
+             {
+               emit_library_call (memset_libfunc, LCT_NORMAL,
+                                  VOIDmode, 3,
+                                  plus_constant (XEXP (targetx, 0),
+                                                 startb / BITS_PER_UNIT),
+                                  Pmode,
+                                  constm1_rtx, TYPE_MODE (integer_type_node),
+                                  GEN_INT ((endb - startb) / BITS_PER_UNIT),
+                                  TYPE_MODE (sizetype));
+             }
+           else
+             emit_library_call (setbits_libfunc, LCT_NORMAL,
+                                VOIDmode, 4, XEXP (targetx, 0),
+                                Pmode, bitlength_rtx, TYPE_MODE (sizetype),
+                                startbit_rtx, TYPE_MODE (sizetype),
+                                endbit_rtx, TYPE_MODE (sizetype));
+           
+           if (REG_P (target))
+             emit_move_insn (target, targetx);
+         }
+       break;
+      }
+    default:
+      gcc_unreachable ();
     }
-
-  else
-    abort ();
 }
 
 /* Store the value of EXP (an expression tree)
@@ -5377,8 +5159,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
     {
       /* We're storing into a struct containing a single __complex.  */
 
-      if (bitpos != 0)
-       abort ();
+      gcc_assert (!bitpos);
       return store_expr (exp, target, value_mode != VOIDmode);
     }
 
@@ -5431,9 +5212,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
         boundary.  If so, we simply do a block copy.  */
       if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
        {
-         if (!MEM_P (target) || !MEM_P (temp)
-             || bitpos % BITS_PER_UNIT != 0)
-           abort ();
+         gcc_assert (MEM_P (target) && MEM_P (temp)
+                     && !(bitpos % BITS_PER_UNIT));
 
          target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
          emit_block_move (target, temp,
@@ -5445,8 +5225,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
        }
 
       /* Store the value in the bitfield.  */
-      store_bit_field (target, bitsize, bitpos, mode, temp,
-                      int_size_in_bytes (type));
+      store_bit_field (target, bitsize, bitpos, mode, temp);
 
       if (value_mode != VOIDmode)
        {
@@ -5467,14 +5246,14 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
                                   gen_int_mode (width_mask, tmode),
                                   NULL_RTX);
 
-             count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
+             count = build_int_cst (NULL_TREE,
+                                    GET_MODE_BITSIZE (tmode) - bitsize);
              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
            }
 
          return extract_bit_field (target, bitsize, bitpos, unsignedp,
-                                   NULL_RTX, value_mode, VOIDmode,
-                                   int_size_in_bytes (type));
+                                   NULL_RTX, value_mode, VOIDmode);
        }
       return const0_rtx;
     }
@@ -5614,8 +5393,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
             index, then convert to sizetype and multiply by the size of the
             array element.  */
          if (! integer_zerop (low_bound))
-           index = fold (build (MINUS_EXPR, TREE_TYPE (index),
-                                index, low_bound));
+           index = fold (build2 (MINUS_EXPR, TREE_TYPE (index),
+                                 index, low_bound));
 
          offset = size_binop (PLUS_EXPR, offset,
                               size_binop (MULT_EXPR,
@@ -5676,10 +5455,16 @@ array_ref_element_size (tree exp)
   /* If a size was specified in the ARRAY_REF, it's the size measured
      in alignment units of the element type.  So multiply by that value.  */
   if (aligned_size)
-    return size_binop (MULT_EXPR, aligned_size,
-                      size_int (TYPE_ALIGN (elmt_type) / BITS_PER_UNIT));
+    {
+      /* ??? tree_ssa_useless_type_conversion will eliminate casts to
+        sizetype from another type of the same width and signedness.  */
+      if (TREE_TYPE (aligned_size) != sizetype)
+       aligned_size = fold_convert (sizetype, aligned_size);
+      return size_binop (MULT_EXPR, aligned_size,
+                        size_int (TYPE_ALIGN_UNIT (elmt_type)));
+    }
 
-  /* Otherwise, take the size from that of the element type.  Substitute 
+  /* Otherwise, take the size from that of the element type.  Substitute
      any PLACEHOLDER_EXPR that we have.  */
   else
     return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
@@ -5703,7 +5488,24 @@ array_ref_low_bound (tree exp)
     return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
 
   /* Otherwise, return a zero of the appropriate type.  */
-  return fold_convert (TREE_TYPE (TREE_OPERAND (exp, 1)), integer_zero_node);
+  return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
+}
+
+/* Return a tree representing the upper bound of the array mentioned in
+   EXP, an ARRAY_REF.  */
+
+tree
+array_ref_up_bound (tree exp)
+{
+  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+  /* If there is a domain type and it has an upper bound, use it, substituting
+     for a PLACEHOLDER_EXPR as needed.  */
+  if (domain_type && TYPE_MAX_VALUE (domain_type))
+    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
+
+  /* Otherwise fail.  */
+  return NULL_TREE;
 }
 
 /* Return a tree representing the offset, in bytes, of the field referenced
@@ -5719,10 +5521,16 @@ component_ref_field_offset (tree exp)
      in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT.  So multiply by that
      value.  */
   if (aligned_offset)
-    return size_binop (MULT_EXPR, aligned_offset,
-                      size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
+    {
+      /* ??? tree_ssa_useless_type_conversion will eliminate casts to
+        sizetype from another type of the same width and signedness.  */
+      if (TREE_TYPE (aligned_offset) != sizetype)
+       aligned_offset = fold_convert (sizetype, aligned_offset);
+      return size_binop (MULT_EXPR, aligned_offset,
+                        size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT));
+    }
 
-  /* Otherwise, take the offset from that of the field.  Substitute 
+  /* Otherwise, take the offset from that of the field.  Substitute
      any PLACEHOLDER_EXPR that we have.  */
   else
     return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
@@ -6039,16 +5847,11 @@ safe_from_p (rtx x, tree exp, int top_p)
        case WITH_CLEANUP_EXPR:
        case CLEANUP_POINT_EXPR:
          /* Lowered by gimplify.c.  */
-         abort ();
+         gcc_unreachable ();
 
        case SAVE_EXPR:
          return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
 
-       case BIND_EXPR:
-         /* The only operand we look at is operand 1.  The rest aren't
-            part of the expression.  */
-         return safe_from_p (x, TREE_OPERAND (exp, 1), 0);
-
        default:
          break;
        }
@@ -6095,22 +5898,6 @@ safe_from_p (rtx x, tree exp, int top_p)
   return 1;
 }
 
-/* Subroutine of expand_expr: return rtx if EXP is a
-   variable or parameter; else return 0.  */
-
-static rtx
-var_rtx (tree exp)
-{
-  STRIP_NOPS (exp);
-  switch (TREE_CODE (exp))
-    {
-    case PARM_DECL:
-    case VAR_DECL:
-      return DECL_RTL (exp);
-    default:
-      return 0;
-    }
-}
 \f
 /* Return the highest power of two that EXP is known to be a multiple of.
    This is used in updating alignment of MEMs in array references.  */
@@ -6193,9 +5980,9 @@ highest_pow2_factor_for_target (tree target, tree exp)
 
   factor = highest_pow2_factor (exp);
   if (TREE_CODE (target) == COMPONENT_REF)
-    target_align = DECL_ALIGN (TREE_OPERAND (target, 1)) / BITS_PER_UNIT;
+    target_align = DECL_ALIGN_UNIT (TREE_OPERAND (target, 1));
   else
-    target_align = TYPE_ALIGN (TREE_TYPE (target)) / BITS_PER_UNIT;
+    target_align = TYPE_ALIGN_UNIT (TREE_TYPE (target));
   return MAX (factor, target_align);
 }
 \f
@@ -6216,50 +6003,20 @@ expand_var (tree var)
       ? !TREE_ASM_WRITTEN (var)
       : !DECL_RTL_SET_P (var))
     {
-      if (TREE_CODE (var) == VAR_DECL && DECL_DEFER_OUTPUT (var))
-       {
-         /* Prepare a mem & address for the decl.  */
-         rtx x;
-                   
-         if (TREE_STATIC (var))
-           abort ();
-
-         x = gen_rtx_MEM (DECL_MODE (var),
-                          gen_reg_rtx (Pmode));
-
-         set_mem_attributes (x, var, 1);
-         SET_DECL_RTL (var, x);
-       }
+      if (TREE_CODE (var) == VAR_DECL && DECL_VALUE_EXPR (var))
+       /* Should be ignored.  */;
       else if (lang_hooks.expand_decl (var))
        /* OK.  */;
       else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
        expand_decl (var);
       else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var))
-       rest_of_decl_compilation (var, NULL, 0, 0);
-      else if (TREE_CODE (var) == TYPE_DECL
-              || TREE_CODE (var) == CONST_DECL
-              || TREE_CODE (var) == FUNCTION_DECL
-              || TREE_CODE (var) == LABEL_DECL)
-       /* No expansion needed.  */;
+       rest_of_decl_compilation (var, 0, 0);
       else
-       abort ();
-    }
-}
-
-/* Expands declarations of variables in list VARS.  */
-
-static void
-expand_vars (tree vars)
-{
-  for (; vars; vars = TREE_CHAIN (vars))
-    {
-      tree var = vars;
-
-      if (DECL_EXTERNAL (var))
-       continue;
-
-      expand_var (var);
-      expand_decl_init (var);
+       /* No expansion needed.  */
+       gcc_assert (TREE_CODE (var) == TYPE_DECL
+                   || TREE_CODE (var) == CONST_DECL
+                   || TREE_CODE (var) == FUNCTION_DECL
+                   || TREE_CODE (var) == LABEL_DECL);
     }
 }
 
@@ -6291,6 +6048,139 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
 }
 
 \f
+/* A subroutine of expand_expr.  Evaluate the address of EXP.
+   The TARGET, TMODE and MODIFIER arguments are as for expand_expr.  */
+
+static rtx
+expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
+                      enum expand_modifier modifier)
+{
+  rtx result, subtarget;
+  tree inner, offset;
+  HOST_WIDE_INT bitsize, bitpos;
+  int volatilep, unsignedp;
+  enum machine_mode mode1;
+
+  /* If we are taking the address of a constant and are at the top level,
+     we have to use output_constant_def since we can't call force_const_mem
+     at top level.  */
+  /* ??? This should be considered a front-end bug.  We should not be
+     generating ADDR_EXPR of something that isn't an LVALUE.  The only
+     exception here is STRING_CST.  */
+  if (TREE_CODE (exp) == CONSTRUCTOR
+      || TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
+    return XEXP (output_constant_def (exp, 0), 0);
+
+  /* Everything must be something allowed by is_gimple_addressable.  */
+  switch (TREE_CODE (exp))
+    {
+    case INDIRECT_REF:
+      /* This case will happen via recursion for &a->b.  */
+      return expand_expr (TREE_OPERAND (exp, 0), target, tmode, EXPAND_NORMAL);
+
+    case CONST_DECL:
+      /* Recurse and make the output_constant_def clause above handle this.  */
+      return expand_expr_addr_expr (DECL_INITIAL (exp), target,
+                                   tmode, modifier);
+
+    case REALPART_EXPR:
+      /* The real part of the complex number is always first, therefore
+        the address is the same as the address of the parent object.  */
+      offset = 0;
+      bitpos = 0;
+      inner = TREE_OPERAND (exp, 0);
+      break;
+
+    case IMAGPART_EXPR:
+      /* The imaginary part of the complex number is always second.
+        The expression is therefore always offset by the size of the
+        scalar type.  */
+      offset = 0;
+      bitpos = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)));
+      inner = TREE_OPERAND (exp, 0);
+      break;
+
+    default:
+      /* If the object is a DECL, then expand it for its rtl.  Don't bypass
+        expand_expr, as that can have various side effects; LABEL_DECLs for
+        example, may not have their DECL_RTL set yet.  Assume language
+        specific tree nodes can be expanded in some interesting way.  */
+      if (DECL_P (exp)
+         || TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE)
+       {
+         result = expand_expr (exp, target, tmode,
+                               modifier == EXPAND_INITIALIZER
+                               ? EXPAND_INITIALIZER : EXPAND_CONST_ADDRESS);
+
+         /* If the DECL isn't in memory, then the DECL wasn't properly
+            marked TREE_ADDRESSABLE, which will be either a front-end
+            or a tree optimizer bug.  */
+         gcc_assert (GET_CODE (result) == MEM);
+         result = XEXP (result, 0);
+
+         /* ??? Is this needed anymore?  */
+         if (!TREE_USED (exp) == 0)
+           {
+             assemble_external (exp);
+             TREE_USED (exp) = 1;
+           }
+
+         if (modifier != EXPAND_INITIALIZER
+             && modifier != EXPAND_CONST_ADDRESS)
+           result = force_operand (result, target);
+         return result;
+       }
+
+      inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+                                  &mode1, &unsignedp, &volatilep);
+      break;
+    }
+
+  /* We must have made progress.  */
+  gcc_assert (inner != exp);
+
+  subtarget = offset || bitpos ? NULL_RTX : target;
+  result = expand_expr_addr_expr (inner, subtarget, tmode, modifier);
+
+  if (tmode == VOIDmode)
+    {
+      tmode = GET_MODE (result);
+      if (tmode == VOIDmode)
+       tmode = Pmode;
+    }
+
+  if (offset)
+    {
+      rtx tmp;
+
+      if (modifier != EXPAND_NORMAL)
+       result = force_operand (result, NULL);
+      tmp = expand_expr (offset, NULL, tmode, EXPAND_NORMAL);
+
+      if (modifier == EXPAND_SUM)
+       result = gen_rtx_PLUS (tmode, result, tmp);
+      else
+       {
+         subtarget = bitpos ? NULL_RTX : target;
+         result = expand_simple_binop (tmode, PLUS, result, tmp, subtarget,
+                                       1, OPTAB_LIB_WIDEN);
+       }
+    }
+
+  if (bitpos)
+    {
+      /* Someone beforehand should have rejected taking the address
+        of such an object.  */
+      gcc_assert (!(bitpos % BITS_PER_UNIT));
+
+      result = plus_constant (result, bitpos / BITS_PER_UNIT);
+      if (modifier < EXPAND_SUM)
+       result = force_operand (result, target);
+    }
+
+  return result;
+}
+
 /* expand_expr: generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.
    In the case of a void EXP, const0_rtx is returned.
@@ -6331,7 +6221,7 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
    marked TARGET so that it's safe from being trashed by libcalls.  We
    don't want to use TARGET for anything but the final result;
    Intermediate values must go elsewhere.   Additionally, calls to
-   emit_block_move will be flagged with BLOCK_OP_CALL_PARM.  
+   emit_block_move will be flagged with BLOCK_OP_CALL_PARM.
 
    If EXP is a VAR_DECL whose DECL_RTL was a MEM with an invalid
    address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the
@@ -6366,11 +6256,11 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
     }
 
   /* If this is an expression of some kind and it has an associated line
-     number, then emit the line number before expanding the expression. 
+     number, then emit the line number before expanding the expression.
 
      We need to save and restore the file and line information so that
      errors discovered during expansion are emitted with the right
-     information.  It would be better of the diagnostic routines 
+     information.  It would be better of the diagnostic routines
      used the file/line information embedded in the tree nodes rather
      than globals.  */
   if (cfun && EXPR_HAS_LOCATION (exp))
@@ -6378,7 +6268,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
       location_t saved_location = input_location;
       input_location = EXPR_LOCATION (exp);
       emit_line_note (input_location);
-      
+
       /* Record where the insns produced belong.  */
       record_block_change (TREE_BLOCK (exp));
 
@@ -6395,9 +6285,9 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
      expand_call() will mark CALL_INSNs before we get to this code,
      but it doesn't handle libcalls, and these may trap.  */
   if (rn >= 0)
-    {  
+    {
       rtx insn;
-      for (insn = next_real_insn (last); insn; 
+      for (insn = next_real_insn (last); insn;
           insn = next_real_insn (insn))
        {
          if (! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
@@ -6542,15 +6432,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        return temp;
       }
 
-    case PARM_DECL:
-      if (!DECL_RTL_SET_P (exp))
-       {
-         error ("%Jprior parameter's size depends on '%D'", exp, exp);
-         return CONST0_RTX (mode);
-       }
-
-      /* ... fall through ...  */
+    case SSA_NAME:
+      return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
+                                NULL);
 
+    case PARM_DECL:
     case VAR_DECL:
       /* If a static var's type was incomplete when the decl was written,
         but the type is complete now, lay out the decl now.  */
@@ -6563,8 +6449,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case FUNCTION_DECL:
     case RESULT_DECL:
-      if (DECL_RTL (exp) == 0)
-       abort ();
+      gcc_assert (DECL_RTL (exp));
 
       /* Ensure variable marked as used even if it doesn't go through
         a parser.  If it hasn't be used yet, write out an external
@@ -6578,39 +6463,20 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Show we haven't gotten RTL for this yet.  */
       temp = 0;
 
-      /* Handle variables inherited from containing functions.  */
+      /* Variables inherited from containing functions should have
+        been lowered by this point.  */
       context = decl_function_context (exp);
-
-      if (context != 0 && context != current_function_decl
-         /* If var is static, we don't need a static chain to access it.  */
-         && ! (MEM_P (DECL_RTL (exp))
-               && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
-       {
-         rtx addr;
-
-         /* Mark as non-local and addressable.  */
-         DECL_NONLOCAL (exp) = 1;
-         if (DECL_NO_STATIC_CHAIN (current_function_decl))
-           abort ();
-         lang_hooks.mark_addressable (exp);
-         if (!MEM_P (DECL_RTL (exp)))
-           abort ();
-         addr = XEXP (DECL_RTL (exp), 0);
-         if (MEM_P (addr))
-           addr
-             = replace_equiv_address (addr,
-                                      fix_lexical_addr (XEXP (addr, 0), exp));
-         else
-           addr = fix_lexical_addr (addr, exp);
-
-         temp = replace_equiv_address (DECL_RTL (exp), addr);
-       }
+      gcc_assert (!context
+                 || context == current_function_decl
+                 || TREE_STATIC (exp)
+                 /* ??? C++ creates functions that are not TREE_STATIC.  */
+                 || TREE_CODE (exp) == FUNCTION_DECL);
 
       /* This is the case of an array whose size is to be determined
         from its initializer, while the initializer is still being parsed.
         See expand_decl.  */
 
-      else if (MEM_P (DECL_RTL (exp))
+      if (MEM_P (DECL_RTL (exp))
               && REG_P (XEXP (DECL_RTL (exp), 0)))
        temp = validize_mem (DECL_RTL (exp));
 
@@ -6650,12 +6516,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (REG_P (DECL_RTL (exp))
          && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
        {
+         enum machine_mode pmode;
+         
          /* Get the signedness used for this variable.  Ensure we get the
             same mode we got when the variable was declared.  */
-         if (GET_MODE (DECL_RTL (exp))
-             != promote_mode (type, DECL_MODE (exp), &unsignedp,
-                              (TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
-           abort ();
+         pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
+                               (TREE_CODE (exp) == RESULT_DECL ? 1 : 0));
+         gcc_assert (GET_MODE (DECL_RTL (exp)) == pmode);
 
          temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
          SUBREG_PROMOTED_VAR_P (temp) = 1;
@@ -6681,7 +6548,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return temp;
 
     case VECTOR_CST:
-      return const_vector_from_tree (exp);
+      if (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_INT
+         || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
+       return const_vector_from_tree (exp);
+      else
+       return expand_expr (build1 (CONSTRUCTOR, TREE_TYPE (exp),
+                                   TREE_VECTOR_CST_ELTS (exp)),
+                           ignore ? const0_rtx : target, tmode, modifier);
 
     case CONST_DECL:
       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
@@ -6744,18 +6617,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        tree val = TREE_OPERAND (exp, 0);
        rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
 
-       if (TREE_CODE (val) != VAR_DECL || !DECL_ARTIFICIAL (val))
+       if (!SAVE_EXPR_RESOLVED_P (exp))
          {
            /* We can indeed still hit this case, typically via builtin
               expanders calling save_expr immediately before expanding
               something.  Assume this means that we only have to deal
               with non-BLKmode values.  */
-           if (GET_MODE (ret) == BLKmode)
-             abort ();
+           gcc_assert (GET_MODE (ret) != BLKmode);
 
            val = build_decl (VAR_DECL, NULL, TREE_TYPE (exp));
            DECL_ARTIFICIAL (val) = 1;
+           DECL_IGNORED_P (val) = 1;
            TREE_OPERAND (exp, 0) = val;
+           SAVE_EXPR_RESOLVED_P (exp) = 1;
 
            if (!CONSTANT_P (ret))
              ret = copy_to_reg (ret);
@@ -6765,15 +6639,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         return ret;
       }
 
-    case UNSAVE_EXPR:
-      {
-       rtx temp;
-       temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-       TREE_OPERAND (exp, 0)
-         = lang_hooks.unsave_expr_now (TREE_OPERAND (exp, 0));
-       return temp;
-      }
-
     case GOTO_EXPR:
       if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
        expand_goto (TREE_OPERAND (exp, 0));
@@ -6781,51 +6646,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        expand_computed_goto (TREE_OPERAND (exp, 0));
       return const0_rtx;
 
-    /* These are lowered during gimplification, so we should never ever
-       see them here.  */
-    case LOOP_EXPR:
-    case EXIT_EXPR:
-      abort ();
-
-    case LABELED_BLOCK_EXPR:
-      if (LABELED_BLOCK_BODY (exp))
-       expand_expr_stmt (LABELED_BLOCK_BODY (exp));
-      /* Should perhaps use expand_label, but this is simpler and safer.  */
-      do_pending_stack_adjust ();
-      emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
-      return const0_rtx;
-
-    case EXIT_BLOCK_EXPR:
-      if (EXIT_BLOCK_RETURN (exp))
-       sorry ("returned value in block_exit_expr");
-      expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
-      return const0_rtx;
-
-    case BIND_EXPR:
-      {
-       tree block = BIND_EXPR_BLOCK (exp);
-       int mark_ends;
-
-       /* If we're in functions-as-trees mode, this BIND_EXPR represents
-          the block, so we need to emit NOTE_INSN_BLOCK_* notes.  */
-       mark_ends = (block != NULL_TREE);
-       expand_start_bindings_and_block (mark_ends ? 0 : 2, block);
-
-       /* If VARS have not yet been expanded, expand them now.  */
-       expand_vars (BIND_EXPR_VARS (exp));
-
-       /* TARGET was clobbered early in this function.  The correct
-          indicator or whether or not we need the value of this 
-          expression is the IGNORE variable.  */
-       temp = expand_expr (BIND_EXPR_BODY (exp),
-                           ignore ? const0_rtx : target,
-                           tmode, modifier);
-
-       expand_end_bindings (BIND_EXPR_VARS (exp), mark_ends, 0);
-
-       return temp;
-      }
-
     case CONSTRUCTOR:
       /* If we don't need the result, just ensure we evaluate any
         subexpressions.  */
@@ -6895,6 +6715,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case INDIRECT_REF:
       {
        tree exp1 = TREE_OPERAND (exp, 0);
+       tree orig;
 
        if (modifier != EXPAND_WRITE)
          {
@@ -6908,30 +6729,25 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address (mode, op0);
        temp = gen_rtx_MEM (mode, op0);
-       set_mem_attributes (temp, exp, 0);
 
-       /* If we are writing to this object and its type is a record with
-          readonly fields, we must mark it as readonly so it will
-          conflict with readonly references to those fields.  */
-       if (modifier == EXPAND_WRITE && readonly_fields_p (type))
-         RTX_UNCHANGING_P (temp) = 1;
+       orig = REF_ORIGINAL (exp);
+       if (!orig)
+         orig = exp;
+       set_mem_attributes (temp, orig, 0);
 
        return temp;
       }
 
     case ARRAY_REF:
 
-#ifdef ENABLE_CHECKING
-      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
-       abort ();
-#endif
-
       {
        tree array = TREE_OPERAND (exp, 0);
        tree low_bound = array_ref_low_bound (exp);
        tree index = convert (sizetype, TREE_OPERAND (exp, 1));
        HOST_WIDE_INT i;
 
+       gcc_assert (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE);
+
        /* Optimize the special-case of a zero lower bound.
 
           We convert the low_bound to sizetype to avoid some problems
@@ -7071,8 +6887,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    else
                      {
                        tree count
-                         = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
-                                        0);
+                         = build_int_cst (NULL_TREE,
+                                          GET_MODE_BITSIZE (imode) - bitsize);
 
                        op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
                                            target, 0);
@@ -7101,8 +6917,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        /* If we got back the original object, something is wrong.  Perhaps
           we are evaluating an expression too early.  In any event, don't
           infinitely recurse.  */
-       if (tem == exp)
-         abort ();
+       gcc_assert (tem != exp);
 
        /* If TEM's type is a union of variable size, pass TARGET to the inner
           computation, since it will need a temporary and TARGET is known
@@ -7156,8 +6971,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
                                          EXPAND_SUM);
 
-           if (!MEM_P (op0))
-             abort ();
+           gcc_assert (MEM_P (op0));
 
 #ifdef POINTERS_EXTEND_UNSIGNED
            if (GET_MODE (offset_rtx) != Pmode)
@@ -7204,8 +7018,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
           one element arrays having the same mode as its element.  */
        if (GET_CODE (op0) == CONCAT)
          {
-           if (bitpos != 0 || bitsize != GET_MODE_BITSIZE (GET_MODE (op0)))
-             abort ();
+           gcc_assert (bitpos == 0
+                       && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)));
            return op0;
          }
 
@@ -7239,8 +7053,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
               size of the type isn't the same size as the bitfield,
               we must use bitfield operations.  */
            || (bitsize >= 0
-               && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
-                   == INTEGER_CST)
+               && TYPE_SIZE (TREE_TYPE (exp))
+               && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
                && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
                                          bitsize)))
          {
@@ -7262,10 +7076,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
                /* In this case, BITPOS must start at a byte boundary and
                   TARGET, if specified, must be a MEM.  */
-               if (!MEM_P (op0)
-                   || (target != 0 && !MEM_P (target))
-                   || bitpos % BITS_PER_UNIT != 0)
-                 abort ();
+               gcc_assert (MEM_P (op0)
+                           && (!target || MEM_P (target))
+                           && !(bitpos % BITS_PER_UNIT));
 
                emit_block_move (target,
                                 adjust_address (op0, VOIDmode,
@@ -7286,8 +7099,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
                                     (modifier == EXPAND_STACK_PARM
                                      ? NULL_RTX : target),
-                                    ext_mode, ext_mode,
-                                    int_size_in_bytes (TREE_TYPE (tem)));
+                                    ext_mode, ext_mode);
 
            /* If the result is a record type and BITSIZE is narrower than
               the mode of OP0, an integral mode, and this is a big endian
@@ -7411,17 +7223,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                        adjust_address (target, TYPE_MODE (valtype), 0),
                        modifier == EXPAND_STACK_PARM ? 2 : 0);
 
-         else if (REG_P (target))
-           /* Store this field into a union of the proper type.  */
-           store_field (target,
-                        MIN ((int_size_in_bytes (TREE_TYPE
-                                                 (TREE_OPERAND (exp, 0)))
-                              * BITS_PER_UNIT),
-                             (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
-                        0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
-                        VOIDmode, 0, type, 0);
          else
-           abort ();
+           {
+             gcc_assert (REG_P (target));
+             
+             /* Store this field into a union of the proper type.  */
+             store_field (target,
+                          MIN ((int_size_in_bytes (TREE_TYPE
+                                                   (TREE_OPERAND (exp, 0)))
+                                * BITS_PER_UNIT),
+                               (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
+                          0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
+                          VOIDmode, 0, type, 0);
+           }
 
          /* Return the entire union.  */
          return target;
@@ -7497,8 +7311,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
             constants to change mode.  */
          tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
 
-         if (TREE_ADDRESSABLE (exp))
-           abort ();
+         gcc_assert (!TREE_ADDRESSABLE (exp));
 
          if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
            target
@@ -7531,8 +7344,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                                                    temp_size, 0, type);
              rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
 
-             if (TREE_ADDRESSABLE (exp))
-               abort ();
+             gcc_assert (!TREE_ADDRESSABLE (exp));
 
              if (GET_MODE (op0) == BLKmode)
                emit_block_move (new_with_op0_mode, op0,
@@ -7551,10 +7363,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return op0;
 
     case PLUS_EXPR:
-      this_optab = ! unsignedp && flag_trapv
-                   && (GET_MODE_CLASS (mode) == MODE_INT)
-                   ? addv_optab : add_optab;
-
       /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
         something else, make sure we add the register to the constant and
         then to the other thing.  This case can occur during strength
@@ -7689,10 +7497,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            return REDUCE_BIT_FIELD (gen_rtx_MINUS (mode, op0, op1));
        }
 
-      this_optab = ! unsignedp && flag_trapv
-                   && (GET_MODE_CLASS(mode) == MODE_INT)
-                   ? subv_optab : sub_optab;
-
       /* No sense saving up arithmetic to be done
         if it's all in the wrong mode to form part of an address.
         And force_operand won't know whether to sign-extend or
@@ -7796,7 +7600,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    expand_operands (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                                     TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
                                     NULL_RTX, &op0, &op1, 0);
-                 goto binop2;
+                 goto binop3;
                }
              else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
                       && innermode == word_mode)
@@ -7849,12 +7653,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (flag_unsafe_math_optimizations && optimize && !optimize_size
          && TREE_CODE (type) == REAL_TYPE
          && !real_onep (TREE_OPERAND (exp, 0)))
-        return expand_expr (build (MULT_EXPR, type, TREE_OPERAND (exp, 0),
-                                  build (RDIV_EXPR, type,
-                                         build_real (type, dconst1),
-                                         TREE_OPERAND (exp, 1))),
+        return expand_expr (build2 (MULT_EXPR, type, TREE_OPERAND (exp, 0),
+                                   build2 (RDIV_EXPR, type,
+                                           build_real (type, dconst1),
+                                           TREE_OPERAND (exp, 1))),
                            target, tmode, modifier);
-      this_optab = sdiv_optab;
+
       goto binop;
 
     case TRUNC_MOD_EXPR:
@@ -7870,7 +7674,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case FIX_ROUND_EXPR:
     case FIX_FLOOR_EXPR:
     case FIX_CEIL_EXPR:
-      abort ();                        /* Not used for C.  */
+      gcc_unreachable ();                      /* Not used for C.  */
 
     case FIX_TRUNC_EXPR:
       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
@@ -7897,11 +7701,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (modifier == EXPAND_STACK_PARM)
        target = 0;
       temp = expand_unop (mode,
-                         ! unsignedp && flag_trapv
-                         && (GET_MODE_CLASS(mode) == MODE_INT)
-                         ? negv_optab : neg_optab, op0, target, 0);
-      if (temp == 0)
-       abort ();
+                         optab_for_tree_code (NEGATE_EXPR, type),
+                         op0, target, 0);
+      gcc_assert (temp);
       return REDUCE_BIT_FIELD (temp);
 
     case ABS_EXPR:
@@ -7910,9 +7712,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        target = 0;
 
       /* ABS_EXPR is not valid for complex arguments.  */
-      if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-         || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
-       abort ();
+      gcc_assert (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
+                 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT);
 
       /* Unsigned abs is simply the operand.  Testing here means we don't
         risk generating incorrect code below.  */
@@ -7938,10 +7739,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* First try to do it with a special MIN or MAX instruction.
         If that does not win, use a conditional jump to select the proper
         value.  */
-      this_optab = (unsignedp
-                   ? (code == MIN_EXPR ? umin_optab : umax_optab)
-                   : (code == MIN_EXPR ? smin_optab : smax_optab));
-
+      this_optab = optab_for_tree_code (code, type);
       temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
                           OPTAB_WIDEN);
       if (temp != 0)
@@ -7992,8 +7790,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (modifier == EXPAND_STACK_PARM)
        target = 0;
       temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
-      if (temp == 0)
-       abort ();
+      gcc_assert (temp);
       return temp;
 
       /* ??? Can optimize bitwise operations with one arg constant.
@@ -8010,18 +7807,18 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         how to recognize those cases.  */
 
     case TRUTH_AND_EXPR:
+      code = BIT_AND_EXPR;
     case BIT_AND_EXPR:
-      this_optab = and_optab;
       goto binop;
 
     case TRUTH_OR_EXPR:
+      code = BIT_IOR_EXPR;
     case BIT_IOR_EXPR:
-      this_optab = ior_optab;
       goto binop;
 
     case TRUTH_XOR_EXPR:
+      code = BIT_XOR_EXPR;
     case BIT_XOR_EXPR:
-      this_optab = xor_optab;
       goto binop;
 
     case LSHIFT_EXPR:
@@ -8096,12 +7893,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          return temp;
        }
 
-      /* If no set-flag instruction, must generate a conditional
-        store into a temporary variable.  Drop through
-        and handle this like && and ||.  */
+      /* If no set-flag instruction, must generate a conditional store
+        into a temporary variable.  Drop through and handle this
+        like && and ||.  */
 
-    case TRUTH_ANDIF_EXPR:
-    case TRUTH_ORIF_EXPR:
       if (! ignore
          && (target == 0
              || modifier == EXPAND_STACK_PARM
@@ -8113,13 +7908,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
 
       if (target)
-       emit_clr_insn (target);
+       emit_move_insn (target, const0_rtx);
 
       op1 = gen_label_rtx ();
       jumpifnot (exp, op1);
 
       if (target)
-       emit_0_to_1_insn (target);
+       emit_move_insn (target, const1_rtx);
 
       emit_label (op1);
       return ignore ? const0_rtx : target;
@@ -8132,23 +7927,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         only with operands that are always zero or one.  */
       temp = expand_binop (mode, xor_optab, op0, const1_rtx,
                           target, 1, OPTAB_LIB_WIDEN);
-      if (temp == 0)
-       abort ();
+      gcc_assert (temp);
       return temp;
 
-    case COMPOUND_EXPR:
-      expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
-      emit_queue ();
-      return expand_expr_real (TREE_OPERAND (exp, 1),
-                              (ignore ? const0_rtx : target),
-                              VOIDmode, modifier, alt_rtl);
-
     case STATEMENT_LIST:
       {
        tree_stmt_iterator iter;
 
-       if (!ignore)
-         abort ();
+       gcc_assert (ignore);
 
        for (iter = tsi_start (exp); !tsi_end_p (iter); tsi_next (&iter))
          expand_expr (tsi_stmt (iter), const0_rtx, VOIDmode, modifier);
@@ -8160,351 +7946,63 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       if (VOID_TYPE_P (TREE_TYPE (exp)))
        {
          tree pred = TREE_OPERAND (exp, 0);
-         tree then_ = TREE_OPERAND (exp, 1);
-         tree else_ = TREE_OPERAND (exp, 2);
-
-         if (TREE_CODE (then_) == GOTO_EXPR
-             && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
-           {
-             jumpif (pred, label_rtx (GOTO_DESTINATION (then_)));
-             return expand_expr (else_, const0_rtx, VOIDmode, 0);
-           }
-         else if (TREE_CODE (else_) == GOTO_EXPR
-                  && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL)
-           {
-             jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_)));
-             return expand_expr (then_, const0_rtx, VOIDmode, 0);
-           }
-
-         /* Just use the 'if' machinery.  */
-         expand_start_cond (pred, 0);
-         expand_expr (then_, const0_rtx, VOIDmode, 0);
-
-         exp = else_;
-
-         /* Iterate over 'else if's instead of recursing.  */
-         for (; TREE_CODE (exp) == COND_EXPR; exp = TREE_OPERAND (exp, 2))
-           {
-             expand_start_else ();
-             if (EXPR_HAS_LOCATION (exp))
-               {
-                 emit_line_note (EXPR_LOCATION (exp));
-                 record_block_change (TREE_BLOCK (exp));
-               }
-             expand_elseif (TREE_OPERAND (exp, 0));
-             expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, 0);
-           }
-         /* Don't emit the jump and label if there's no 'else' clause.  */
-         if (TREE_SIDE_EFFECTS (exp))
-           {
-             expand_start_else ();
-             expand_expr (exp, const0_rtx, VOIDmode, 0);
-           }
-         expand_end_cond ();
-         return const0_rtx;
-       }
-
-      /* If we would have a "singleton" (see below) were it not for a
-        conversion in each arm, bring that conversion back out.  */
-      if (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
-         && TREE_CODE (TREE_OPERAND (exp, 2)) == NOP_EXPR
-         && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))
-             == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 2), 0))))
-       {
-         tree iftrue = TREE_OPERAND (TREE_OPERAND (exp, 1), 0);
-         tree iffalse = TREE_OPERAND (TREE_OPERAND (exp, 2), 0);
-
-         if ((TREE_CODE_CLASS (TREE_CODE (iftrue)) == '2'
-              && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
-             || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '2'
-                 && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0))
-             || (TREE_CODE_CLASS (TREE_CODE (iftrue)) == '1'
-                 && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
-             || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '1'
-                 && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0)))
-           return expand_expr (build1 (NOP_EXPR, type,
-                                       build (COND_EXPR, TREE_TYPE (iftrue),
-                                              TREE_OPERAND (exp, 0),
-                                              iftrue, iffalse)),
-                               target, tmode, modifier);
-       }
-
-      {
-       /* Note that COND_EXPRs whose type is a structure or union
-          are required to be constructed to contain assignments of
-          a temporary variable, so that we can evaluate them here
-          for side effect only.  If type is void, we must do likewise.  */
-
-       /* If an arm of the branch requires a cleanup,
-          only that cleanup is performed.  */
-
-       tree singleton = 0;
-       tree binary_op = 0, unary_op = 0;
-
-       /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and
-          convert it to our mode, if necessary.  */
-       if (integer_onep (TREE_OPERAND (exp, 1))
-           && integer_zerop (TREE_OPERAND (exp, 2))
-           && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
-         {
-           if (ignore)
-             {
-               expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                            modifier);
-               return const0_rtx;
-             }
-
-           if (modifier == EXPAND_STACK_PARM)
-             target = 0;
-           op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
-           if (GET_MODE (op0) == mode)
-             return op0;
-
-           if (target == 0)
-             target = gen_reg_rtx (mode);
-           convert_move (target, op0, unsignedp);
-           return target;
-         }
-
-       /* Check for X ? A + B : A.  If we have this, we can copy A to the
-          output and conditionally add B.  Similarly for unary operations.
-          Don't do this if X has side-effects because those side effects
-          might affect A or B and the "?" operation is a sequence point in
-          ANSI.  (operand_equal_p tests for side effects.)  */
-
-       if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2'
-           && operand_equal_p (TREE_OPERAND (exp, 2),
-                               TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
-         singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1);
-       else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2'
-                && operand_equal_p (TREE_OPERAND (exp, 1),
-                                    TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
-         singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2);
-       else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1'
-                && operand_equal_p (TREE_OPERAND (exp, 2),
-                                    TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
-         singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1);
-       else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1'
-                && operand_equal_p (TREE_OPERAND (exp, 1),
-                                    TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
-         singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2);
-
-       /* If we are not to produce a result, we have no target.  Otherwise,
-          if a target was specified use it; it will not be used as an
-          intermediate target unless it is safe.  If no target, use a
-          temporary.  */
-
-       if (ignore)
-         temp = 0;
-       else if (modifier == EXPAND_STACK_PARM)
-         temp = assign_temp (type, 0, 0, 1);
-       else if (original_target
-                && (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
-                    || (singleton && REG_P (original_target)
-                        && REGNO (original_target) >= FIRST_PSEUDO_REGISTER
-                        && original_target == var_rtx (singleton)))
-                && GET_MODE (original_target) == mode
+         tree then_ = TREE_OPERAND (exp, 1);
+         tree else_ = TREE_OPERAND (exp, 2);
+
+         gcc_assert (TREE_CODE (then_) == GOTO_EXPR
+                     && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL
+                     && TREE_CODE (else_) == GOTO_EXPR
+                     && TREE_CODE (GOTO_DESTINATION (else_)) == LABEL_DECL);
+
+         jumpif (pred, label_rtx (GOTO_DESTINATION (then_)));
+         return expand_expr (else_, const0_rtx, VOIDmode, 0);
+       }
+
+        /* Note that COND_EXPRs whose type is a structure or union
+        are required to be constructed to contain assignments of
+        a temporary variable, so that we can evaluate them here
+        for side effect only.  If type is void, we must do likewise.  */
+
+        gcc_assert (!TREE_ADDRESSABLE (type)
+                   && !ignore
+                   && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node
+                   && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node);
+
+       /* If we are not to produce a result, we have no target.  Otherwise,
+        if a target was specified use it; it will not be used as an
+        intermediate target unless it is safe.  If no target, use a
+        temporary.  */
+
+       if (modifier != EXPAND_STACK_PARM
+         && original_target
+         && safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
+         && GET_MODE (original_target) == mode
 #ifdef HAVE_conditional_move
-                && (! can_conditionally_move_p (mode)
-                    || REG_P (original_target)
-                    || TREE_ADDRESSABLE (type))
+         && (! can_conditionally_move_p (mode)
+             || REG_P (original_target))
 #endif
-                && (!MEM_P (original_target)
-                    || TREE_ADDRESSABLE (type)))
-         temp = original_target;
-       else if (TREE_ADDRESSABLE (type))
-         abort ();
-       else
-         temp = assign_temp (type, 0, 0, 1);
-
-       /* If we had X ? A + C : A, with C a constant power of 2, and we can
-          do the test of X as a store-flag operation, do this as
-          A + ((X != 0) << log C).  Similarly for other simple binary
-          operators.  Only do for C == 1 if BRANCH_COST is low.  */
-       if (temp && singleton && binary_op
-           && (TREE_CODE (binary_op) == PLUS_EXPR
-               || TREE_CODE (binary_op) == MINUS_EXPR
-               || TREE_CODE (binary_op) == BIT_IOR_EXPR
-               || TREE_CODE (binary_op) == BIT_XOR_EXPR)
-           && (BRANCH_COST >= 3 ? integer_pow2p (TREE_OPERAND (binary_op, 1))
-               : integer_onep (TREE_OPERAND (binary_op, 1)))
-           && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
-         {
-           rtx result;
-           tree cond;
-           optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
-                           ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
-                              ? addv_optab : add_optab)
-                           : TREE_CODE (binary_op) == MINUS_EXPR
-                           ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
-                              ? subv_optab : sub_optab)
-                           : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
-                           : xor_optab);
-
-           /* If we had X ? A : A + 1, do this as A + (X == 0).  */
-           if (singleton == TREE_OPERAND (exp, 1))
-             cond = invert_truthvalue (TREE_OPERAND (exp, 0));
-           else
-             cond = TREE_OPERAND (exp, 0);
-
-           result = do_store_flag (cond, (safe_from_p (temp, singleton, 1)
-                                          ? temp : NULL_RTX),
-                                   mode, BRANCH_COST <= 1);
-
-           if (result != 0 && ! integer_onep (TREE_OPERAND (binary_op, 1)))
-             result = expand_shift (LSHIFT_EXPR, mode, result,
-                                    build_int_2 (tree_log2
-                                                 (TREE_OPERAND
-                                                  (binary_op, 1)),
-                                                 0),
-                                    (safe_from_p (temp, singleton, 1)
-                                     ? temp : NULL_RTX), 0);
-
-           if (result)
-             {
-               op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0);
-               return expand_binop (mode, boptab, op1, result, temp,
-                                    unsignedp, OPTAB_LIB_WIDEN);
-             }
-         }
-
-       do_pending_stack_adjust ();
-       NO_DEFER_POP;
-       op0 = gen_label_rtx ();
-
-       if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
-         {
-           if (temp != 0)
-             {
-               /* If the target conflicts with the other operand of the
-                  binary op, we can't use it.  Also, we can't use the target
-                  if it is a hard register, because evaluating the condition
-                  might clobber it.  */
-               if ((binary_op
-                    && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1), 1))
-                   || (REG_P (temp)
-                       && REGNO (temp) < FIRST_PSEUDO_REGISTER))
-                 temp = gen_reg_rtx (mode);
-               store_expr (singleton, temp,
-                           modifier == EXPAND_STACK_PARM ? 2 : 0);
-             }
-           else
-             expand_expr (singleton,
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           if (singleton == TREE_OPERAND (exp, 1))
-             jumpif (TREE_OPERAND (exp, 0), op0);
-           else
-             jumpifnot (TREE_OPERAND (exp, 0), op0);
-
-           if (binary_op && temp == 0)
-             /* Just touch the other operand.  */
-             expand_expr (TREE_OPERAND (binary_op, 1),
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           else if (binary_op)
-             store_expr (build (TREE_CODE (binary_op), type,
-                                make_tree (type, temp),
-                                TREE_OPERAND (binary_op, 1)),
-                         temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
-           else
-             store_expr (build1 (TREE_CODE (unary_op), type,
-                                 make_tree (type, temp)),
-                         temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
-           op1 = op0;
-         }
-       /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
-          comparison operator.  If we have one of these cases, set the
-          output to A, branch on A (cse will merge these two references),
-          then set the output to FOO.  */
-       else if (temp
-                && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
-                && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
-                && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-                                    TREE_OPERAND (exp, 1), 0)
-                && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
-                    || TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR)
-                && safe_from_p (temp, TREE_OPERAND (exp, 2), 1))
-         {
-           if (REG_P (temp)
-               && REGNO (temp) < FIRST_PSEUDO_REGISTER)
-             temp = gen_reg_rtx (mode);
-           store_expr (TREE_OPERAND (exp, 1), temp,
-                       modifier == EXPAND_STACK_PARM ? 2 : 0);
-           jumpif (TREE_OPERAND (exp, 0), op0);
-
-           if (TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
-             store_expr (TREE_OPERAND (exp, 2), temp,
-                         modifier == EXPAND_STACK_PARM ? 2 : 0);
-           else
-             expand_expr (TREE_OPERAND (exp, 2),
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           op1 = op0;
-         }
-       else if (temp
-                && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
-                && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
-                && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-                                    TREE_OPERAND (exp, 2), 0)
-                && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
-                    || TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR)
-                && safe_from_p (temp, TREE_OPERAND (exp, 1), 1))
-         {
-           if (REG_P (temp)
-               && REGNO (temp) < FIRST_PSEUDO_REGISTER)
-             temp = gen_reg_rtx (mode);
-           store_expr (TREE_OPERAND (exp, 2), temp,
-                       modifier == EXPAND_STACK_PARM ? 2 : 0);
-           jumpifnot (TREE_OPERAND (exp, 0), op0);
-
-           if (TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
-             store_expr (TREE_OPERAND (exp, 1), temp,
-                         modifier == EXPAND_STACK_PARM ? 2 : 0);
-           else
-             expand_expr (TREE_OPERAND (exp, 1),
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           op1 = op0;
-         }
-       else
-         {
-           op1 = gen_label_rtx ();
-           jumpifnot (TREE_OPERAND (exp, 0), op0);
-
-           /* One branch of the cond can be void, if it never returns. For
-              example A ? throw : E  */
-           if (temp != 0
-               && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
-             store_expr (TREE_OPERAND (exp, 1), temp,
-                         modifier == EXPAND_STACK_PARM ? 2 : 0);
-           else
-             expand_expr (TREE_OPERAND (exp, 1),
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-           emit_queue ();
-           emit_jump_insn (gen_jump (op1));
-           emit_barrier ();
-           emit_label (op0);
-           if (temp != 0
-               && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
-             store_expr (TREE_OPERAND (exp, 2), temp,
-                         modifier == EXPAND_STACK_PARM ? 2 : 0);
-           else
-             expand_expr (TREE_OPERAND (exp, 2),
-                          ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-         }
-
-       emit_queue ();
-       emit_label (op1);
-       OK_DEFER_POP;
-
-       return temp;
-      }
-
-    case INIT_EXPR:
-      {
-       tree lhs = TREE_OPERAND (exp, 0);
-       tree rhs = TREE_OPERAND (exp, 1);
-
-       temp = expand_assignment (lhs, rhs, ! ignore);
-       return temp;
-      }
+         && !MEM_P (original_target))
+       temp = original_target;
+       else
+       temp = assign_temp (type, 0, 0, 1);
+
+       do_pending_stack_adjust ();
+       NO_DEFER_POP;
+       op0 = gen_label_rtx ();
+       op1 = gen_label_rtx ();
+       jumpifnot (TREE_OPERAND (exp, 0), op0);
+       store_expr (TREE_OPERAND (exp, 1), temp,
+                 modifier == EXPAND_STACK_PARM ? 2 : 0);
+
+       emit_jump_insn (gen_jump (op1));
+       emit_barrier ();
+       emit_label (op0);
+       store_expr (TREE_OPERAND (exp, 2), temp,
+                 modifier == EXPAND_STACK_PARM ? 2 : 0);
+
+       emit_label (op1);
+       OK_DEFER_POP;
+       return temp;
 
     case MODIFY_EXPR:
       {
@@ -8565,152 +8063,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        expand_return (TREE_OPERAND (exp, 0));
       return const0_rtx;
 
-    case PREINCREMENT_EXPR:
-    case PREDECREMENT_EXPR:
-      return REDUCE_BIT_FIELD (expand_increment (exp, 0, ignore));
-
-    case POSTINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-      /* Faster to treat as pre-increment if result is not used.  */
-      return REDUCE_BIT_FIELD (expand_increment (exp, ! ignore, ignore));
-
     case ADDR_EXPR:
-      if (modifier == EXPAND_STACK_PARM)
-       target = 0;
-      /* If we are taking the address of something erroneous, just
-        return a zero.  */
-      if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
-       return const0_rtx;
-      /* If we are taking the address of a constant and are at the
-        top level, we have to use output_constant_def since we can't
-        call force_const_mem at top level.  */
-      else if (cfun == 0
-              && (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
-                  || (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0)))
-                      == 'c')))
-       op0 = XEXP (output_constant_def (TREE_OPERAND (exp, 0), 0), 0);
-      else
-       {
-         /* We make sure to pass const0_rtx down if we came in with
-            ignore set, to avoid doing the cleanups twice for something.  */
-         op0 = expand_expr (TREE_OPERAND (exp, 0),
-                            ignore ? const0_rtx : NULL_RTX, VOIDmode,
-                            (modifier == EXPAND_INITIALIZER
-                             ? modifier : EXPAND_CONST_ADDRESS));
-
-         /* If we are going to ignore the result, OP0 will have been set
-            to const0_rtx, so just return it.  Don't get confused and
-            think we are taking the address of the constant.  */
-         if (ignore)
-           return op0;
-
-         /* Pass 1 for MODIFY, so that protect_from_queue doesn't get
-            clever and returns a REG when given a MEM.  */
-         op0 = protect_from_queue (op0, 1);
-
-         /* We would like the object in memory.  If it is a constant, we can
-            have it be statically allocated into memory.  For a non-constant,
-            we need to allocate some memory and store the value into it.  */
-
-         if (CONSTANT_P (op0))
-           op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
-                                  op0);
-         else if (REG_P (op0) || GET_CODE (op0) == SUBREG
-                  || GET_CODE (op0) == CONCAT || GET_CODE (op0) == PARALLEL
-                  || GET_CODE (op0) == LO_SUM)
-           {
-             /* If this object is in a register, it can't be BLKmode.  */
-             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-             rtx memloc = assign_temp (inner_type, 1, 1, 1);
-
-             if (GET_CODE (op0) == PARALLEL)
-               /* Handle calls that pass values in multiple
-                  non-contiguous locations.  The Irix 6 ABI has examples
-                  of this.  */
-               emit_group_store (memloc, op0, inner_type,
-                                 int_size_in_bytes (inner_type));
-             else
-               emit_move_insn (memloc, op0);
-
-             op0 = memloc;
-           }
-
-         if (!MEM_P (op0))
-           abort ();
-
-         mark_temp_addr_taken (op0);
-         if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-           {
-             op0 = XEXP (op0, 0);
-             if (GET_MODE (op0) == Pmode && mode == ptr_mode)
-               op0 = convert_memory_address (ptr_mode, op0);
-             return op0;
-           }
-
-         /* If OP0 is not aligned as least as much as the type requires, we
-            need to make a temporary, copy OP0 to it, and take the address of
-            the temporary.  We want to use the alignment of the type, not of
-            the operand.  Note that this is incorrect for FUNCTION_TYPE, but
-            the test for BLKmode means that can't happen.  The test for
-            BLKmode is because we never make mis-aligned MEMs with
-            non-BLKmode.
-
-            We don't need to do this at all if the machine doesn't have
-            strict alignment.  */
-         if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
-             && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
-                 > MEM_ALIGN (op0))
-             && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
-           {
-             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-             rtx new;
-
-             if (TYPE_ALIGN_OK (inner_type))
-               abort ();
-
-             if (TREE_ADDRESSABLE (inner_type))
-               {
-                 /* We can't make a bitwise copy of this object, so fail.  */
-                 error ("cannot take the address of an unaligned member");
-                 return const0_rtx;
-               }
-
-             new = assign_stack_temp_for_type
-               (TYPE_MODE (inner_type),
-                MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
-                : int_size_in_bytes (inner_type),
-                1, build_qualified_type (inner_type,
-                                         (TYPE_QUALS (inner_type)
-                                          | TYPE_QUAL_CONST)));
-
-             emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)),
-                              (modifier == EXPAND_STACK_PARM
-                               ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-
-             op0 = new;
-           }
-
-         op0 = force_operand (XEXP (op0, 0), target);
-       }
-
-      if (flag_force_addr
-         && !REG_P (op0)
-         && modifier != EXPAND_CONST_ADDRESS
-         && modifier != EXPAND_INITIALIZER
-         && modifier != EXPAND_SUM)
-       op0 = force_reg (Pmode, op0);
-
-      if (REG_P (op0)
-         && ! REG_USERVAR_P (op0))
-       mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
-
-      if (GET_MODE (op0) == Pmode && mode == ptr_mode)
-       op0 = convert_memory_address (ptr_mode, op0);
-
-      return op0;
-
-    case ENTRY_VALUE_EXPR:
-      abort ();
+      return expand_expr_addr_expr (TREE_OPERAND (exp, 0), target,
+                                   tmode, modifier);
 
     /* COMPLEX type for Extended Pascal & Fortran  */
     case COMPLEX_EXPR:
@@ -8754,47 +8109,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
       return gen_imagpart (mode, op0);
 
-    case CONJ_EXPR:
-      {
-       enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
-       rtx imag_t;
-       rtx insns;
-
-       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-
-       if (! target)
-         target = gen_reg_rtx (mode);
-
-       start_sequence ();
-
-       /* Store the realpart and the negated imagpart to target.  */
-       emit_move_insn (gen_realpart (partmode, target),
-                       gen_realpart (partmode, op0));
-
-       imag_t = gen_imagpart (partmode, target);
-       temp = expand_unop (partmode,
-                           ! unsignedp && flag_trapv
-                           && (GET_MODE_CLASS(partmode) == MODE_INT)
-                           ? negv_optab : neg_optab,
-                           gen_imagpart (partmode, op0), imag_t, 0);
-       if (temp != imag_t)
-         emit_move_insn (imag_t, temp);
-
-       insns = get_insns ();
-       end_sequence ();
-
-       /* Conjugate should appear as a single unit
-          If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
-          each with a separate pseudo as destination.
-          It's not correct for flow to treat them as a unit.  */
-       if (GET_CODE (target) != CONCAT)
-         emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
-       else
-         emit_insn (insns);
-
-       return target;
-      }
-
     case RESX_EXPR:
       expand_resx_expr (exp);
       return const0_rtx;
@@ -8804,16 +8118,29 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case EH_FILTER_EXPR:
     case TRY_FINALLY_EXPR:
       /* Lowered by tree-eh.c.  */
-      abort ();
+      gcc_unreachable ();
 
     case WITH_CLEANUP_EXPR:
     case CLEANUP_POINT_EXPR:
     case TARGET_EXPR:
-      /* Lowered by gimplify.c.  */
-      abort ();
-
+    case CASE_LABEL_EXPR:
     case VA_ARG_EXPR:
-      return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
+    case BIND_EXPR:
+    case INIT_EXPR:
+    case CONJ_EXPR:
+    case COMPOUND_EXPR:
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case LOOP_EXPR:
+    case EXIT_EXPR:
+    case LABELED_BLOCK_EXPR:
+    case EXIT_BLOCK_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+      /* Lowered by gimplify.c.  */
+      gcc_unreachable ();
 
     case EXC_PTR_EXPR:
       return get_exception_pointer (cfun);
@@ -8824,114 +8151,43 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case FDESC_EXPR:
       /* Function descriptors are not valid except for as
         initialization constants, and should not be expanded.  */
-      abort ();
+      gcc_unreachable ();
 
     case SWITCH_EXPR:
-      expand_start_case (0, SWITCH_COND (exp), integer_type_node,
-                        "switch");
-      if (SWITCH_BODY (exp))
-        expand_expr_stmt (SWITCH_BODY (exp));
-      if (SWITCH_LABELS (exp))
-       {
-         tree duplicate = 0;
-         tree vec = SWITCH_LABELS (exp);
-         size_t i, n = TREE_VEC_LENGTH (vec);
-
-         for (i = 0; i < n; ++i)
-           {
-             tree elt = TREE_VEC_ELT (vec, i);
-             tree controlling_expr_type = TREE_TYPE (SWITCH_COND (exp));
-             tree min_value = TYPE_MIN_VALUE (controlling_expr_type);
-             tree max_value = TYPE_MAX_VALUE (controlling_expr_type);
-             
-             tree case_low = CASE_LOW (elt);
-             tree case_high = CASE_HIGH (elt) ? CASE_HIGH (elt) : case_low;
-             if (case_low && case_high)
-               {
-                 /* Case label is less than minimum for type.  */
-                 if (TREE_CODE (min_value) == INTEGER_CST
-                     && tree_int_cst_compare (case_low, min_value) < 0
-                     && tree_int_cst_compare (case_high, min_value) < 0)
-                   {
-                     warning ("case label value %d is less than minimum value for type",
-                              TREE_INT_CST (case_low));
-                     continue;
-                   }
-                 
-                 /* Case value is greater than maximum for type.  */
-                 if (TREE_CODE (max_value) == INTEGER_CST
-                     && tree_int_cst_compare (case_low, max_value) > 0
-                     && tree_int_cst_compare (case_high, max_value) > 0)
-                   {
-                     warning ("case label value %d exceeds maximum value for type",
-                              TREE_INT_CST (case_high));
-                     continue;
-                   }
-                 
-                 /* Saturate lower case label value to minimum.  */
-                 if (TREE_CODE (min_value) == INTEGER_CST
-                     && tree_int_cst_compare (case_high, min_value) >= 0
-                     && tree_int_cst_compare (case_low, min_value) < 0)
-                   {
-                     warning ("lower value %d in case label range less than minimum value for type",
-                              TREE_INT_CST (case_low));
-                     case_low = min_value;
-                   }
-                 
-                 /* Saturate upper case label value to maximum.  */
-                 if (TREE_CODE (max_value) == INTEGER_CST
-                     && tree_int_cst_compare (case_low, max_value) <= 0
-                     && tree_int_cst_compare (case_high, max_value) > 0)
-                   {
-                     warning ("upper value %d in case label range exceeds maximum value for type",
-                              TREE_INT_CST (case_high));
-                     case_high = max_value;
-                   }
-               }
-             
-             add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate, true);
-             if (duplicate)
-               abort ();
-           }
-       }
-      expand_end_case_type (SWITCH_COND (exp), TREE_TYPE (exp));
+      expand_case (exp);
       return const0_rtx;
 
     case LABEL_EXPR:
       expand_label (TREE_OPERAND (exp, 0));
       return const0_rtx;
 
-    case CASE_LABEL_EXPR:
-      {
-       tree duplicate = 0;
-       add_case_node (CASE_LOW (exp), CASE_HIGH (exp), CASE_LABEL (exp),
-                      &duplicate, false);
-       if (duplicate)
-         abort ();
-       return const0_rtx;
-      }
-
     case ASM_EXPR:
       expand_asm_expr (exp);
       return const0_rtx;
 
+    case WITH_SIZE_EXPR:
+      /* WITH_SIZE_EXPR expands to its first argument.  The caller should
+        have pulled out the size to use in whatever context it needed.  */
+      return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
+                              modifier, alt_rtl);
+
     default:
       return lang_hooks.expand_expr (exp, original_target, tmode,
                                     modifier, alt_rtl);
     }
 
-  /* Here to do an ordinary binary operator, generating an instruction
-     from the optab already placed in `this_optab'.  */
+  /* Here to do an ordinary binary operator.  */
  binop:
   expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
                   subtarget, &op0, &op1, 0);
  binop2:
+  this_optab = optab_for_tree_code (code, type);
+ binop3:
   if (modifier == EXPAND_STACK_PARM)
     target = 0;
   temp = expand_binop (mode, this_optab, op0, op1, target,
                       unsignedp, OPTAB_LIB_WIDEN);
-  if (temp == 0)
-    abort ();
+  gcc_assert (temp);
   return REDUCE_BIT_FIELD (temp);
 }
 #undef REDUCE_BIT_FIELD
@@ -8959,7 +8215,8 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
     }
   else
     {
-      tree count = build_int_2 (GET_MODE_BITSIZE (GET_MODE (exp)) - prec, 0);
+      tree count = build_int_cst (NULL_TREE,
+                                 GET_MODE_BITSIZE (GET_MODE (exp)) - prec);
       exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
       return expand_shift (RSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
     }
@@ -8982,7 +8239,7 @@ is_aligning_offset (tree offset, tree exp)
      power of 2 and which is larger than BIGGEST_ALIGNMENT.  */
   if (TREE_CODE (offset) != BIT_AND_EXPR
       || !host_integerp (TREE_OPERAND (offset, 1), 1)
-      || compare_tree_int (TREE_OPERAND (offset, 1), 
+      || compare_tree_int (TREE_OPERAND (offset, 1),
                           BIGGEST_ALIGNMENT / BITS_PER_UNIT) <= 0
       || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
     return 0;
@@ -9056,209 +8313,6 @@ string_constant (tree arg, tree *ptr_offset)
   return 0;
 }
 \f
-/* Expand code for a post- or pre- increment or decrement
-   and return the RTX for the result.
-   POST is 1 for postinc/decrements and 0 for preinc/decrements.  */
-
-static rtx
-expand_increment (tree exp, int post, int ignore)
-{
-  rtx op0, op1;
-  rtx temp, value;
-  tree incremented = TREE_OPERAND (exp, 0);
-  optab this_optab = add_optab;
-  int icode;
-  enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-  int op0_is_copy = 0;
-  int single_insn = 0;
-  /* 1 means we can't store into OP0 directly,
-     because it is a subreg narrower than a word,
-     and we don't dare clobber the rest of the word.  */
-  int bad_subreg = 0;
-
-  /* Stabilize any component ref that might need to be
-     evaluated more than once below.  */
-  if (!post
-      || TREE_CODE (incremented) == BIT_FIELD_REF
-      || (TREE_CODE (incremented) == COMPONENT_REF
-         && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
-             || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
-    incremented = stabilize_reference (incremented);
-  /* Nested *INCREMENT_EXPRs can happen in C++.  We must force innermost
-     ones into save exprs so that they don't accidentally get evaluated
-     more than once by the code below.  */
-  if (TREE_CODE (incremented) == PREINCREMENT_EXPR
-      || TREE_CODE (incremented) == PREDECREMENT_EXPR)
-    incremented = save_expr (incremented);
-
-  /* Compute the operands as RTX.
-     Note whether OP0 is the actual lvalue or a copy of it:
-     I believe it is a copy iff it is a register or subreg
-     and insns were generated in computing it.  */
-
-  temp = get_last_insn ();
-  op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
-
-  /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
-     in place but instead must do sign- or zero-extension during assignment,
-     so we copy it into a new register and let the code below use it as
-     a copy.
-
-     Note that we can safely modify this SUBREG since it is know not to be
-     shared (it was made by the expand_expr call above).  */
-
-  if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
-    {
-      if (post)
-       SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
-      else
-       bad_subreg = 1;
-    }
-  else if (GET_CODE (op0) == SUBREG
-          && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD)
-    {
-      /* We cannot increment this SUBREG in place.  If we are
-        post-incrementing, get a copy of the old value.  Otherwise,
-        just mark that we cannot increment in place.  */
-      if (post)
-       op0 = copy_to_reg (op0);
-      else
-       bad_subreg = 1;
-    }
-
-  op0_is_copy = ((GET_CODE (op0) == SUBREG || REG_P (op0))
-                && temp != get_last_insn ());
-  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-
-  /* Decide whether incrementing or decrementing.  */
-  if (TREE_CODE (exp) == POSTDECREMENT_EXPR
-      || TREE_CODE (exp) == PREDECREMENT_EXPR)
-    this_optab = sub_optab;
-
-  /* Convert decrement by a constant into a negative increment.  */
-  if (this_optab == sub_optab
-      && GET_CODE (op1) == CONST_INT)
-    {
-      op1 = GEN_INT (-INTVAL (op1));
-      this_optab = add_optab;
-    }
-
-  if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
-    this_optab = this_optab == add_optab ? addv_optab : subv_optab;
-
-  /* For a preincrement, see if we can do this with a single instruction.  */
-  if (!post)
-    {
-      icode = (int) this_optab->handlers[(int) mode].insn_code;
-      if (icode != (int) CODE_FOR_nothing
-         /* Make sure that OP0 is valid for operands 0 and 1
-            of the insn we want to queue.  */
-         && (*insn_data[icode].operand[0].predicate) (op0, mode)
-         && (*insn_data[icode].operand[1].predicate) (op0, mode)
-         && (*insn_data[icode].operand[2].predicate) (op1, mode))
-       single_insn = 1;
-    }
-
-  /* If OP0 is not the actual lvalue, but rather a copy in a register,
-     then we cannot just increment OP0.  We must therefore contrive to
-     increment the original value.  Then, for postincrement, we can return
-     OP0 since it is a copy of the old value.  For preincrement, expand here
-     unless we can do it with a single insn.
-
-     Likewise if storing directly into OP0 would clobber high bits
-     we need to preserve (bad_subreg).  */
-  if (op0_is_copy || (!post && !single_insn) || bad_subreg)
-    {
-      /* This is the easiest way to increment the value wherever it is.
-        Problems with multiple evaluation of INCREMENTED are prevented
-        because either (1) it is a component_ref or preincrement,
-        in which case it was stabilized above, or (2) it is an array_ref
-        with constant index in an array in a register, which is
-        safe to reevaluate.  */
-      tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR
-                            || TREE_CODE (exp) == PREDECREMENT_EXPR)
-                           ? MINUS_EXPR : PLUS_EXPR),
-                          TREE_TYPE (exp),
-                          incremented,
-                          TREE_OPERAND (exp, 1));
-
-      while (TREE_CODE (incremented) == NOP_EXPR
-            || TREE_CODE (incremented) == CONVERT_EXPR)
-       {
-         newexp = convert (TREE_TYPE (incremented), newexp);
-         incremented = TREE_OPERAND (incremented, 0);
-       }
-
-      temp = expand_assignment (incremented, newexp, ! post && ! ignore);
-      return post ? op0 : temp;
-    }
-
-  if (post)
-    {
-      /* We have a true reference to the value in OP0.
-        If there is an insn to add or subtract in this mode, queue it.
-        Queuing the increment insn avoids the register shuffling
-        that often results if we must increment now and first save
-        the old value for subsequent use.  */
-
-#if 0  /* Turned off to avoid making extra insn for indexed memref.  */
-      op0 = stabilize (op0);
-#endif
-
-      icode = (int) this_optab->handlers[(int) mode].insn_code;
-      if (icode != (int) CODE_FOR_nothing
-         /* Make sure that OP0 is valid for operands 0 and 1
-            of the insn we want to queue.  */
-         && (*insn_data[icode].operand[0].predicate) (op0, mode)
-         && (*insn_data[icode].operand[1].predicate) (op0, mode))
-       {
-         if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
-           op1 = force_reg (mode, op1);
-
-         return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
-       }
-      if (icode != (int) CODE_FOR_nothing && MEM_P (op0))
-       {
-         rtx addr = (general_operand (XEXP (op0, 0), mode)
-                     ? force_reg (Pmode, XEXP (op0, 0))
-                     : copy_to_reg (XEXP (op0, 0)));
-         rtx temp, result;
-
-         op0 = replace_equiv_address (op0, addr);
-         temp = force_reg (GET_MODE (op0), op0);
-         if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
-           op1 = force_reg (mode, op1);
-
-         /* The increment queue is LIFO, thus we have to `queue'
-            the instructions in reverse order.  */
-         enqueue_insn (op0, gen_move_insn (op0, temp));
-         result = enqueue_insn (temp, GEN_FCN (icode) (temp, temp, op1));
-         return result;
-       }
-    }
-
-  /* Preincrement, or we can't increment with one simple insn.  */
-  if (post)
-    /* Save a copy of the value before inc or dec, to return it later.  */
-    temp = value = copy_to_reg (op0);
-  else
-    /* Arrange to return the incremented value.  */
-    /* Copy the rtx because expand_binop will protect from the queue,
-       and the results of that would be invalid for us to return
-       if our caller does emit_queue before using our result.  */
-    temp = copy_rtx (value = op0);
-
-  /* Increment however we can.  */
-  op1 = expand_binop (mode, this_optab, value, op1, op0,
-                     TYPE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
-
-  /* Make sure the value is stored into OP0.  */
-  if (op1 != op0)
-    emit_move_insn (op0, op1);
-
-  return temp;
-}
-\f
 /* Generate code to calculate EXP using a store-flag instruction
    and return an rtx for the result.  EXP is either a comparison
    or a TRUTH_NOT_EXPR whose operand is a comparison.
@@ -9399,7 +8453,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Put a constant second.  */
@@ -9462,13 +8516,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
   if (target == 0)
     target = gen_reg_rtx (mode);
 
-  /* Pass copies of OP0 and OP1 in case they contain a QUEUED.  This is safe
-     because, if the emit_store_flag does anything it will succeed and
-     OP0 and OP1 will not be used subsequently.  */
-
-  result = emit_store_flag (target, code,
-                           queued_subexp_p (op0) ? copy_rtx (op0) : op0,
-                           queued_subexp_p (op1) ? copy_rtx (op1) : op1,
+  result = emit_store_flag (target, code, op0, op1,
                            operand_mode, unsignedp, 1);
 
   if (result)
@@ -9501,8 +8549,7 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
   code = GET_CODE (result);
 
   label = gen_label_rtx ();
-  if (bcc_gen_fctn[(int) code] == 0)
-    abort ();
+  gcc_assert (bcc_gen_fctn[(int) code]);
 
   emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
   emit_move_insn (target, invert ? const1_rtx : const0_rtx);
@@ -9553,8 +8600,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
       rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
 
       /* We must handle the endpoints in the original mode.  */
-      index_expr = build (MINUS_EXPR, index_type,
-                         index_expr, minval);
+      index_expr = build2 (MINUS_EXPR, index_type,
+                          index_expr, minval);
       minval = integer_zero_node;
       index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
       emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
@@ -9573,8 +8620,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
 
       index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
     }
-  emit_queue ();
-  index = protect_from_queue (index, 0);
+
   do_pending_stack_adjust ();
 
   op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
@@ -9674,9 +8720,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
 #endif
     index = memory_address_noforce (CASE_VECTOR_MODE, index);
   temp = gen_reg_rtx (CASE_VECTOR_MODE);
-  vector = gen_rtx_MEM (CASE_VECTOR_MODE, index);
-  RTX_UNCHANGING_P (vector) = 1;
-  MEM_NOTRAP_P (vector) = 1;
+  vector = gen_const_mem (CASE_VECTOR_MODE, index);
   convert_move (temp, vector, 0);
 
   emit_jump_insn (gen_tablejump (temp, table_label));
@@ -9696,12 +8740,10 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
   if (! HAVE_tablejump)
     return 0;
 
-  index_expr = fold (build (MINUS_EXPR, index_type,
-                           convert (index_type, index_expr),
-                           convert (index_type, minval)));
+  index_expr = fold (build2 (MINUS_EXPR, index_type,
+                            convert (index_type, index_expr),
+                            convert (index_type, minval)));
   index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
-  emit_queue ();
-  index = protect_from_queue (index, 0);
   do_pending_stack_adjust ();
 
   do_tablejump (index, TYPE_MODE (index_type),
@@ -9730,7 +8772,7 @@ vector_mode_valid_p (enum machine_mode mode)
     return 0;
 
   /* Hardware support.  Woo hoo!  */
-  if (VECTOR_MODE_SUPPORTED_P (mode))
+  if (targetm.vector_mode_supported_p (mode))
     return 1;
 
   innermode = GET_MODE_INNER (mode);
@@ -9740,7 +8782,7 @@ vector_mode_valid_p (enum machine_mode mode)
 
   /* If we have support for the inner mode, we can safely emulate it.
      We may not have V2DI, but me can emulate with a pair of DIs.  */
-  return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
+  return targetm.scalar_mode_supported_p (innermode);
 }
 
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
@@ -9780,6 +8822,6 @@ const_vector_from_tree (tree exp)
   for (; i < units; ++i)
     RTVEC_ELT (v, i) = CONST0_RTX (inner);
 
-  return gen_rtx_raw_CONST_VECTOR (mode, v);
+  return gen_rtx_CONST_VECTOR (mode, v);
 }
 #include "gt-expr.h"