OSDN Git Service

Add CONST1_RTX (vector mode) support.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index b3ef3ef..44f485b 100644 (file)
@@ -120,6 +120,7 @@ struct store_by_pieces
 };
 
 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 *);
@@ -144,7 +145,6 @@ 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);
@@ -175,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.  */
@@ -331,8 +335,7 @@ convert_move (rtx to, rtx from, int unsignedp)
                              : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
 
 
-  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.  */
@@ -349,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)))
@@ -361,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);
@@ -385,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.  */
 
@@ -405,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,
@@ -429,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);
@@ -444,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);
@@ -553,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);
@@ -642,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);
@@ -678,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
@@ -792,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);
     }
 
@@ -883,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);
@@ -921,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.  */
@@ -946,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)
@@ -984,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;
 
-  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 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;
+
+      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);
@@ -1013,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;
 }
 
@@ -1063,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
        }
 
@@ -1117,17 +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));
 
-  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.  */
@@ -1322,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;
 }
 
@@ -1368,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
@@ -1385,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);
     }
 
@@ -1511,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));
     }
@@ -1530,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);
@@ -1564,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.  */
@@ -1599,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
@@ -1649,14 +1651,15 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
                                             (bytepos % slen0) * BITS_PER_UNIT,
                                             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
@@ -1684,7 +1687,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
 
       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);
     }
 
   /* Copy the extracted pieces into the proper (probable) hard regs.  */
@@ -1700,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++)
@@ -1722,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.  */
@@ -1795,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;
        }
@@ -1809,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),
@@ -1818,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.  */
@@ -1927,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);
@@ -1944,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]);
@@ -1984,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;
@@ -1997,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.  */
@@ -2047,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;
@@ -2071,13 +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 ();
+  gcc_assert (STORE_BY_PIECES_P (len, align));
   data.constfun = constfun;
   data.constfundata = constfundata;
   data.len = len;
@@ -2087,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)
@@ -2152,7 +2160,7 @@ 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;
 
@@ -2172,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);
@@ -2199,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.  */
@@ -2224,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
@@ -2390,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;
 }
 
@@ -2432,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
@@ -2449,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);
     }
 
@@ -2470,8 +2481,8 @@ emit_move_insn (rtx x, rtx y)
   rtx y_cst = NULL_RTX;
   rtx last_insn, set;
 
-  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))
     {
@@ -2509,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);
 
@@ -2534,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
@@ -2715,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
@@ -2765,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
@@ -2845,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);
 
@@ -2869,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
@@ -3154,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;
 
@@ -3390,16 +3396,12 @@ 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);
 }
 
@@ -3456,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)
@@ -3504,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)
@@ -3574,7 +3563,7 @@ expand_assignment (tree to, tree from, int want_value)
          if (bitsize >= GET_MODE_BITSIZE (GET_MODE (str_rtx)))
            break;
 
-         /* We can't handle fields split accross multiple entities.  */
+         /* We can't handle fields split across multiple entities.  */
          if (bitpos1 + bitsize > GET_MODE_BITSIZE (GET_MODE (str_rtx)))
            break;
 
@@ -3618,8 +3607,8 @@ expand_assignment (tree to, tree from, int want_value)
                                      NULL_RTX);
                  binop = xor_optab;
                }
-             value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx),
-                                   value, build_int_2 (bitpos1, 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 (str_rtx), binop, str_rtx,
                                     value, str_rtx, 1, OPTAB_WIDEN);
@@ -3799,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;
     }
@@ -4282,7 +4270,7 @@ count_type_elements (tree type)
     case FUNCTION_TYPE:
     case LANG_TYPE:
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -4375,753 +4363,750 @@ 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;
+
+       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));
+
+       /* 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);
+         }
 
-             RTX_UNCHANGING_P (to_rtx) = 1;
-           }
+       /* 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;
+         }
 
-#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 (!cleared && REG_P (target))
+         /* Inform later passes that the old value is dead.  */
+         emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
 
-             if (TYPE_PRECISION (type) < BITS_PER_WORD)
-               {
-                 type = lang_hooks.types.type_for_size
-                   (BITS_PER_WORD, TYPE_UNSIGNED (type));
-                 value = convert (type, value);
-               }
+       /* 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);
+
+                   /* 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 (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
+    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 (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;
-           }
+           /* 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;
+      }
 
-         store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                  value, type, cleared,
-                                  get_alias_set (TREE_TYPE (field)));
-       }
+      /* 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;
+                   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);
+           
+           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);
+             }
+           
+           else
+             {
+               gcc_assert (MEM_P (target));
+               targetx = target;
+             }
+
+           /* 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 if (TREE_CODE (type) == 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;
-
-      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));
-
-      /* 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);
-       }
+/* Store the value of EXP (an expression tree)
+   into a subfield of TARGET which has mode MODE and occupies
+   BITSIZE bits, starting BITPOS bits from the start of TARGET.
+   If MODE is VOIDmode, it means that we are storing into a bit-field.
 
-      /* 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 VALUE_MODE is VOIDmode, return nothing in particular.
+   UNSIGNEDP is not used in this case.
 
-             if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
-               {
-                 tree lo_index = TREE_OPERAND (index, 0);
-                 tree hi_index = TREE_OPERAND (index, 1);
+   Otherwise, return an rtx for the value stored.  This rtx
+   has mode VALUE_MODE if that is convenient to do.
+   In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
 
-                 if (! host_integerp (lo_index, 1)
-                     || ! host_integerp (hi_index, 1))
-                   {
-                     need_to_clear = 1;
-                     break;
-                   }
+   TYPE is the type of the underlying object,
 
-                 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;
-       }
-
-      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++)
-       {
-         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 (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_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 (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 (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));
-           }
-       }
-    }
-
-  else if (TREE_CODE (type) == 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;
-
-      if (eltmode == BLKmode)
-       abort ();
-
-      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;
-           }
-
-         /* 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.  */
-             if (TREE_CODE (TREE_TYPE (value)) == VECTOR_TYPE)
-               abort ();
-             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))));
-    }
-
-  /* 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,
-                                     EXPAND_CONST_ADDRESS);
-         endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
-                                   EXPAND_CONST_ADDRESS);
-
-         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);
-           }
-
-         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);
-       }
-    }
-
-  else
-    abort ();
-}
-
-/* Store the value of EXP (an expression tree)
-   into a subfield of TARGET which has mode MODE and occupies
-   BITSIZE bits, starting BITPOS bits from the start of TARGET.
-   If MODE is VOIDmode, it means that we are storing into a bit-field.
-
-   If VALUE_MODE is VOIDmode, return nothing in particular.
-   UNSIGNEDP is not used in this case.
-
-   Otherwise, return an rtx for the value stored.  This rtx
-   has mode VALUE_MODE if that is convenient to do.
-   In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
-
-   TYPE is the type of the underlying object,
-
-   ALIAS_SET is the alias set for the destination.  This value will
-   (in general) be different from that for TARGET, since TARGET is a
-   reference to the containing structure.  */
+   ALIAS_SET is the alias set for the destination.  This value will
+   (in general) be different from that for TARGET, since TARGET is a
+   reference to the containing structure.  */
 
 static rtx
 store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
@@ -5174,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);
     }
 
@@ -5228,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,
@@ -5263,7 +5246,8 @@ 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);
            }
@@ -5409,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,
@@ -5471,8 +5455,14 @@ 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
      any PLACEHOLDER_EXPR that we have.  */
@@ -5498,7 +5488,7 @@ 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
@@ -5531,8 +5521,14 @@ 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
      any PLACEHOLDER_EXPR that we have.  */
@@ -5851,7 +5847,7 @@ 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);
@@ -5902,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.  */
@@ -6000,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
@@ -6023,33 +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 ();
+       /* 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);
     }
 }
 
@@ -6081,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.
@@ -6332,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.  */
@@ -6353,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
@@ -6371,18 +6466,17 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Variables inherited from containing functions should have
         been lowered by this point.  */
       context = decl_function_context (exp);
-      if (context != 0
-         && context != current_function_decl
-         && !TREE_STATIC (exp)
-         /* ??? C++ creates functions that are not TREE_STATIC.  */
-         && TREE_CODE (exp) != FUNCTION_DECL)
-       abort ();
+      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));
 
@@ -6422,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;
@@ -6522,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);
@@ -6543,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));
@@ -6559,26 +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 CONSTRUCTOR:
       /* If we don't need the result, just ensure we evaluate any
         subexpressions.  */
@@ -6648,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)
          {
@@ -6661,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
@@ -6824,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);
@@ -6854,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
@@ -6909,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)
@@ -6957,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;
          }
 
@@ -6992,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)))
          {
@@ -7015,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,
@@ -7163,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;
@@ -7249,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
@@ -7283,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,
@@ -7303,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
@@ -7441,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
@@ -7548,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)
@@ -7601,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:
@@ -7622,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);
@@ -7649,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:
@@ -7662,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.  */
@@ -7690,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)
@@ -7744,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.
@@ -7762,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:
@@ -7848,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
@@ -7865,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;
@@ -7884,22 +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);
-      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);
@@ -7911,349 +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_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_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:
       {
@@ -8315,138 +8064,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return const0_rtx;
 
     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;
-
-         /* 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:
@@ -8490,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;
@@ -8540,7 +8118,7 @@ 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:
@@ -8548,8 +8126,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case CASE_LABEL_EXPR:
     case VA_ARG_EXPR:
     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.  */
-      abort ();
+      gcc_unreachable ();
 
     case EXC_PTR_EXPR:
       return get_exception_pointer (cfun);
@@ -8557,37 +8148,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case FILTER_EXPR:
       return get_exception_filter (cfun);
 
-    case PREINCREMENT_EXPR:
-    case PREDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
     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 (SWITCH_COND (exp));
-      /* The switch body is lowered in gimplify.c, we should never have
-        switches with a non-NULL SWITCH_BODY here.  */
-      if (SWITCH_BODY (exp))
-        abort ();
-      if (SWITCH_LABELS (exp))
-       {
-         tree vec = SWITCH_LABELS (exp);
-         size_t i = TREE_VEC_LENGTH (vec);
-
-         do
-           {
-             tree elt = TREE_VEC_ELT (vec, --i);
-             add_case_node (CASE_LOW (elt), CASE_HIGH (elt),
-                            CASE_LABEL (elt));
-           }
-         while (i);
-       }
-      else
-       abort ();
-      expand_end_case_type (SWITCH_COND (exp), TREE_TYPE (exp));
+      expand_case (exp);
       return const0_rtx;
 
     case LABEL_EXPR:
@@ -8609,18 +8176,18 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode 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
@@ -8648,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);
     }
@@ -8885,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.  */
@@ -8981,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);
@@ -9033,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,
@@ -9153,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));
@@ -9175,9 +8740,9 @@ 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);
   do_pending_stack_adjust ();
 
@@ -9207,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);
@@ -9217,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.  */
@@ -9257,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"