OSDN Git Service

Index: gcc/ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 2652781..0691420 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001 Free Software Foundation, Inc.
+   2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "except.h"
 #include "function.h"
 #include "insn-config.h"
+#include "insn-attr.h"
 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
 #include "expr.h"
 #include "optabs.h"
@@ -41,6 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "typeclass.h"
 #include "toplev.h"
 #include "ggc.h"
+#include "langhooks.h"
 #include "intl.h"
 #include "tm_p.h"
 
@@ -71,15 +73,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define CASE_VECTOR_PC_RELATIVE 0
 #endif
 
-/* Hook called by safe_from_p for language-specific tree codes.  It is
-   up to the language front-end to install a hook if it has any such
-   codes that safe_from_p needs to know about.  Since same_from_p will
-   recursively explore the TREE_OPERANDs of an expression, this hook
-   should not reexamine those pieces.  This routine may recursively
-   call safe_from_p; it should always pass `0' as the TOP_P
-   parameter.  */
-int (*lang_safe_from_p) PARAMS ((rtx, tree));
-
 /* If this is nonzero, we do not bother generating VOLATILE
    around volatile memory references, and we are willing to
    output indirect addresses.  If cse is to follow, we reject
@@ -88,11 +81,6 @@ int (*lang_safe_from_p) PARAMS ((rtx, tree));
    the same indirect address eventually.  */
 int cse_not_expected;
 
-/* Don't check memory usage, since code is being emitted to check a memory
-   usage.  Used when current_function_check_memory_usage is true, to avoid
-   infinite recursion.  */
-static int in_check_memory_usage;
-
 /* Chain of pending expressions for PLACEHOLDER_EXPR to replace.  */
 static tree placeholder_list = 0;
 
@@ -131,8 +119,6 @@ struct store_by_pieces
 
 extern struct obstack permanent_obstack;
 
-static rtx get_push_address    PARAMS ((int));
-
 static rtx enqueue_insn                PARAMS ((rtx, rtx));
 static unsigned HOST_WIDE_INT move_by_pieces_ninsns
                                PARAMS ((unsigned HOST_WIDE_INT,
@@ -153,19 +139,14 @@ static int is_zeros_p             PARAMS ((tree));
 static int mostly_zeros_p      PARAMS ((tree));
 static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
                                             HOST_WIDE_INT, enum machine_mode,
-                                            tree, tree, unsigned int, int,
-                                            int));
-static void store_constructor  PARAMS ((tree, rtx, unsigned int, int,
-                                        HOST_WIDE_INT));
+                                            tree, tree, int, int));
+static void store_constructor  PARAMS ((tree, rtx, int, HOST_WIDE_INT));
 static rtx store_field         PARAMS ((rtx, HOST_WIDE_INT,
                                         HOST_WIDE_INT, enum machine_mode,
-                                        tree, enum machine_mode, int,
-                                        unsigned int, HOST_WIDE_INT, int));
-static enum memory_use_mode
-  get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
+                                        tree, enum machine_mode, int, tree,
+                                        int));
 static rtx var_rtx             PARAMS ((tree));
 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
-static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
 static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
@@ -878,7 +859,7 @@ convert_move (to, from, unsignedp)
              && STORE_FLAG_VALUE == -1)
            {
              emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
-                            lowpart_mode, 0, 0);
+                            lowpart_mode, 0);
              fill_value = gen_reg_rtx (word_mode);
              emit_insn (gen_slt (fill_value));
            }
@@ -1071,6 +1052,9 @@ convert_move (to, from, unsignedp)
       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
          != CODE_FOR_nothing)
        {
+         if (flag_force_mem)
+           from = force_not_mem (from);
+
          emit_unop_insn (code, to, from, equiv_code);
          return;
        }
@@ -1578,26 +1562,24 @@ move_by_pieces_1 (genfun, mode, data)
       if (data->to)
        {
          if (data->autinc_to)
-           {
-             to1 = replace_equiv_address (data->to, data->to_addr);
-             to1 = adjust_address (to1, mode, 0);
-           }
+           to1 = adjust_automodify_address (data->to, mode, data->to_addr,
+                                            data->offset);
          else
            to1 = adjust_address (data->to, mode, data->offset);
        }
 
       if (data->autinc_from)
-       {
-         from1 = replace_equiv_address (data->from, data->from_addr);
-         from1 = adjust_address (from1, mode, 0);
-       }
+       from1 = adjust_automodify_address (data->from, mode, data->from_addr,
+                                          data->offset);
       else
        from1 = adjust_address (data->from, mode, data->offset);
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-       emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
+       emit_insn (gen_add2_insn (data->to_addr,
+                                 GEN_INT (-(HOST_WIDE_INT)size)));
       if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
-       emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
+       emit_insn (gen_add2_insn (data->from_addr,
+                                 GEN_INT (-(HOST_WIDE_INT)size)));
 
       if (data->to)
        emit_insn ((*genfun) (to1, from1));
@@ -1812,6 +1794,12 @@ emit_block_move (x, y, size)
                                          TREE_UNSIGNED (integer_type_node)),
                         TYPE_MODE (integer_type_node));
 #endif
+
+      /* 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 (x))
+       emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
     }
 
   return retval;
@@ -1885,7 +1873,8 @@ move_block_from_reg (regno, x, nregs, size)
   /* If SIZE is that of a mode no bigger than a word, just use that
      mode's store operation.  */
   if (size <= UNITS_PER_WORD
-      && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
+      && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
     {
       emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
       return;
@@ -1894,7 +1883,9 @@ move_block_from_reg (regno, x, nregs, size)
   /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
      to the left before storing to memory.  Note that the previous test
      doesn't handle all cases (e.g. SIZE == 3).  */
-  if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
+  if (size < UNITS_PER_WORD
+      && BYTES_BIG_ENDIAN
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
     {
       rtx tem = operand_subword (x, 0, 1, BLKmode);
       rtx shift;
@@ -1940,9 +1931,8 @@ move_block_from_reg (regno, x, nregs, size)
 
 /* Emit code to move a block SRC to a block DST, where DST is non-consecutive
    registers represented by a PARALLEL.  SSIZE represents the total size of
-   block SRC in bytes, or -1 if not known.  ALIGN is the known alignment of
-   SRC in bits.  */
-/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatent assumption that
+   block SRC in bytes, or -1 if not known.  */
+/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatant assumption that
    the balance will be in what would be the low-order memory addresses, i.e.
    left justified for big endian, right justified for little endian.  This
    happens to be true for the targets currently using this support.  If this
@@ -1950,9 +1940,8 @@ move_block_from_reg (regno, x, nregs, size)
    would be needed.  */
 
 void
-emit_group_load (dst, orig_src, ssize, align)
+emit_group_load (dst, orig_src, ssize)
      rtx dst, orig_src;
-     unsigned int align;
      int ssize;
 {
   rtx *tmps, src;
@@ -2000,12 +1989,13 @@ emit_group_load (dst, orig_src, ssize, align)
            src = gen_reg_rtx (mode);
          else
            src = gen_reg_rtx (GET_MODE (orig_src));
+
          emit_move_insn (src, orig_src);
        }
 
       /* Optimize the access just a bit.  */
       if (GET_CODE (src) == MEM
-         && align >= GET_MODE_ALIGNMENT (mode)
+         && MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
        {
@@ -2022,11 +2012,10 @@ emit_group_load (dst, orig_src, ssize, align)
            tmps[i] = XEXP (src, 1);
          else if (bytepos == 0)
            {
-             rtx mem;
-             mem = assign_stack_temp (GET_MODE (src),
-                                      GET_MODE_SIZE (GET_MODE (src)), 0);
+             rtx mem = assign_stack_temp (GET_MODE (src),
+                                          GET_MODE_SIZE (GET_MODE (src)), 0);
              emit_move_insn (mem, src);
-             tmps[i] = change_address (mem, mode, XEXP (mem, 0));
+             tmps[i] = adjust_address (mem, mode, 0);
            }
          else
            abort ();
@@ -2037,7 +2026,7 @@ emit_group_load (dst, orig_src, ssize, align)
       else
        tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
                                     bytepos * BITS_PER_UNIT, 1, NULL_RTX,
-                                    mode, mode, align, ssize);
+                                    mode, mode, ssize);
 
       if (BYTES_BIG_ENDIAN && shift)
        expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
@@ -2053,13 +2042,12 @@ emit_group_load (dst, orig_src, ssize, align)
 
 /* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
    registers represented by a PARALLEL.  SSIZE represents the total size of
-   block DST, or -1 if not known.  ALIGN is the known alignment of DST.  */
+   block DST, or -1 if not known.  */
 
 void
-emit_group_store (orig_dst, src, ssize, align)
+emit_group_store (orig_dst, src, ssize)
      rtx orig_dst, src;
      int ssize;
-     unsigned int align;
 {
   rtx *tmps, dst;
   int start, i;
@@ -2103,8 +2091,8 @@ emit_group_store (orig_dst, src, ssize, align)
         the temporary.  */
 
       temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
-      emit_group_store (temp, src, ssize, align);
-      emit_group_load (dst, temp, ssize, align);
+      emit_group_store (temp, src, ssize);
+      emit_group_load (dst, temp, ssize);
       return;
     }
   else if (GET_CODE (dst) != MEM)
@@ -2135,13 +2123,13 @@ emit_group_store (orig_dst, src, ssize, align)
 
       /* Optimize the access just a bit.  */
       if (GET_CODE (dst) == MEM
-         && align >= GET_MODE_ALIGNMENT (mode)
+         && MEM_ALIGN (dst) >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
        emit_move_insn (adjust_address (dst, mode, bytepos), tmps[i]);
       else
        store_bit_field (dst, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
-                        mode, tmps[i], align, ssize);
+                        mode, tmps[i], ssize);
     }
 
   emit_queue ();
@@ -2180,17 +2168,28 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
       preserve_temp_slots (tgtblk);
     }
 
-  /* This code assumes srcreg is at least a full word.  If it isn't,
-     copy it into a new pseudo which is a full word.  */
+  /* This code assumes srcreg is at least a full word.  If it isn't, copy it
+     into a new pseudo which is a full word.
+
+     If FUNCTION_ARG_REG_LITTLE_ENDIAN is set and convert_to_mode does a copy,
+     the wrong part of the register gets copied so we fake a type conversion
+     in place.  */
   if (GET_MODE (srcreg) != BLKmode
       && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
-    srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
+    {
+      if (FUNCTION_ARG_REG_LITTLE_ENDIAN)
+       srcreg = simplify_gen_subreg (word_mode, srcreg, GET_MODE (srcreg), 0);
+      else
+       srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
+    }
 
   /* Structures whose size is not a multiple of a word are aligned
      to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
      machine, this means we must skip the empty high order bytes when
      calculating the bit offset.  */
-  if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+  if (BYTES_BIG_ENDIAN
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN
+      && bytes % UNITS_PER_WORD)
     big_endian_correction
       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
 
@@ -2222,8 +2221,8 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
                       extract_bit_field (src, bitsize,
                                          xbitpos % BITS_PER_WORD, 1,
                                          NULL_RTX, word_mode, word_mode,
-                                         bitsize, BITS_PER_WORD),
-                      bitsize, BITS_PER_WORD);
+                                         BITS_PER_WORD),
+                      BITS_PER_WORD);
     }
 
   return tgtblk;
@@ -2523,10 +2522,8 @@ store_by_pieces_2 (genfun, mode, data)
        data->offset -= size;
 
       if (data->autinc_to)
-       {
-         to1 = replace_equiv_address (data->to, data->to_addr);
-         to1 = adjust_address (to1, mode, 0);
-       }
+       to1 = adjust_automodify_address (data->to, mode, data->to_addr,
+                                        data->offset);
       else
        to1 = adjust_address (data->to, mode, data->offset);
 
@@ -2717,6 +2714,12 @@ clear_storage (object, size)
                             VOIDmode, 2, object, Pmode, size,
                             TYPE_MODE (integer_type_node));
 #endif
+
+         /* 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));
        }
     }
 
@@ -2790,7 +2793,6 @@ emit_move_insn_1 (x, y)
   enum machine_mode mode = GET_MODE (x);
   enum machine_mode submode;
   enum mode_class class = GET_MODE_CLASS (mode);
-  unsigned int i;
 
   if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
     abort ();
@@ -2816,10 +2818,11 @@ emit_move_insn_1 (x, y)
       /* In case we output to the stack, but the size is smaller machine can
         push exactly, we need to use move instructions.  */
       if (stack
-         && PUSH_ROUNDING (GET_MODE_SIZE (submode)) != GET_MODE_SIZE (submode))
+         && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
+             != GET_MODE_SIZE (submode)))
        {
          rtx temp;
-         int offset1, offset2;
+         HOST_WIDE_INT offset1, offset2;
 
          /* Do not use anti_adjust_stack, since we don't want to update
             stack_pointer_delta.  */
@@ -2831,12 +2834,13 @@ emit_move_insn_1 (x, y)
 #endif
                               stack_pointer_rtx,
                               GEN_INT
-                                (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
-                              stack_pointer_rtx,
-                              0,
-                              OPTAB_LIB_WIDEN);
+                                (PUSH_ROUNDING
+                                 (GET_MODE_SIZE (GET_MODE (x)))),
+                              stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
+
          if (temp != stack_pointer_rtx)
            emit_move_insn (stack_pointer_rtx, temp);
+
 #ifdef STACK_GROWS_DOWNWARD
          offset1 = 0;
          offset2 = GET_MODE_SIZE (submode);
@@ -2845,6 +2849,7 @@ emit_move_insn_1 (x, y)
          offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
                     + GET_MODE_SIZE (submode));
 #endif
+
          emit_move_insn (change_address (x, submode,
                                          gen_rtx_PLUS (Pmode,
                                                        stack_pointer_rtx,
@@ -2900,8 +2905,10 @@ emit_move_insn_1 (x, y)
          if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
              && (reload_in_progress | reload_completed) == 0)
            {
-             int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
-             int packed_src_p  = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
+             int packed_dest_p
+               = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
+             int packed_src_p
+               = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
 
              if (packed_dest_p || packed_src_p)
                {
@@ -2923,12 +2930,14 @@ emit_move_insn_1 (x, y)
                      if (packed_dest_p)
                        {
                          rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
+
                          emit_move_insn_1 (cmem, y);
                          return emit_move_insn_1 (sreg, mem);
                        }
                      else
                        {
                          rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
+
                          emit_move_insn_1 (mem, sreg);
                          return emit_move_insn_1 (x, cmem);
                        }
@@ -2949,9 +2958,7 @@ emit_move_insn_1 (x, y)
              && ! (reload_in_progress || reload_completed)
              && (GET_CODE (realpart_x) == SUBREG
                  || GET_CODE (imagpart_x) == SUBREG))
-           {
-             emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-           }
+           emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
 
          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                     (realpart_x, realpart_y));
@@ -2970,6 +2977,7 @@ emit_move_insn_1 (x, y)
       rtx last_insn = 0;
       rtx seq, inner;
       int need_clobber;
+      int i;
 
 #ifdef PUSH_ROUNDING
 
@@ -2990,19 +2998,20 @@ emit_move_insn_1 (x, y)
 #endif
                               stack_pointer_rtx,
                               GEN_INT
-                                (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
-                              stack_pointer_rtx,
-                              0,
-                              OPTAB_LIB_WIDEN);
+                                (PUSH_ROUNDING
+                                 (GET_MODE_SIZE (GET_MODE (x)))),
+                              stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
+
           if (temp != stack_pointer_rtx)
             emit_move_insn (stack_pointer_rtx, temp);
 
          code = GET_CODE (XEXP (x, 0));
+
          /* Just hope that small offsets off SP are OK.  */
          if (code == POST_INC)
            temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 
-                               GEN_INT (-(HOST_WIDE_INT)
-                                          GET_MODE_SIZE (GET_MODE (x))));
+                               GEN_INT (-((HOST_WIDE_INT)
+                                          GET_MODE_SIZE (GET_MODE (x)))));
          else if (code == POST_DEC)
            temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 
                                GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
@@ -3061,9 +3070,7 @@ emit_move_insn_1 (x, y)
       if (x != y
          && ! (reload_in_progress || reload_completed)
          && need_clobber != 0)
-       {
-         emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-       }
+       emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
 
       emit_insn (seq);
 
@@ -3131,26 +3138,6 @@ push_block (size, extra, below)
   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
 }
 
-
-/* Return an rtx for the address of the beginning of an as-if-it-was-pushed
-   block of SIZE bytes.  */
-
-static rtx
-get_push_address (size)
-     int size;
-{
-  rtx temp;
-
-  if (STACK_PUSH_CODE == POST_DEC)
-    temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (size));
-  else if (STACK_PUSH_CODE == POST_INC)
-    temp = gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (size));
-  else
-    temp = stack_pointer_rtx;
-
-  return copy_to_reg (temp);
-}
-
 #ifdef PUSH_ROUNDING
 
 /* Emit single push insn.  */
@@ -3174,7 +3161,7 @@ emit_single_push_insn (mode, x, type)
   if (icode != CODE_FOR_nothing)
     {
       if (((pred = insn_data[(int) icode].operand[0].predicate)
-         && !((*pred) (x, mode))))
+          && !((*pred) (x, mode))))
        x = force_reg (mode, x);
       emit_insn (GEN_FCN (icode) (x));
       return;
@@ -3185,7 +3172,7 @@ emit_single_push_insn (mode, x, type)
     {
 #ifdef STACK_GROWS_DOWNWARD
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               GEN_INT (-(HOST_WIDE_INT)rounded_size));
+                               GEN_INT (-(HOST_WIDE_INT) rounded_size));
 #else
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
                                GEN_INT (rounded_size));
@@ -3198,11 +3185,13 @@ emit_single_push_insn (mode, x, type)
   if (type != 0)
     {
       set_mem_attributes (dest, type, 1);
-      /* Function incoming arguments may overlap with sibling call
-         outgoing arguments and we cannot allow reordering of reads
-         from function arguments with stores to outgoing arguments
-         of sibling calls.  */
-      set_mem_alias_set (dest, 0);
+
+      if (flag_optimize_sibling_calls)
+       /* Function incoming arguments may overlap with sibling call
+          outgoing arguments and we cannot allow reordering of reads
+          from function arguments with stores to outgoing arguments
+          of sibling calls.  */
+       set_mem_alias_set (dest, 0);
     }
   emit_move_insn (dest, x);
 }
@@ -3330,28 +3319,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            anti_adjust_stack (GEN_INT (extra));
 
          move_by_pieces (NULL, xinner, INTVAL (size) - used, align);
-
-         if (current_function_check_memory_usage && ! in_check_memory_usage)
-           {
-             rtx temp;
-
-             in_check_memory_usage = 1;
-             temp = get_push_address (INTVAL (size) - used);
-             if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-               emit_library_call (chkr_copy_bitmap_libfunc,
-                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
-                                  Pmode, XEXP (xinner, 0), Pmode,
-                                  GEN_INT (INTVAL (size) - used),
-                                  TYPE_MODE (sizetype));
-             else
-               emit_library_call (chkr_set_right_libfunc,
-                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
-                                  Pmode, GEN_INT (INTVAL (size) - used),
-                                  TYPE_MODE (sizetype),
-                                  GEN_INT (MEMORY_USE_RW),
-                                  TYPE_MODE (integer_type_node));
-             in_check_memory_usage = 0;
-           }
        }
       else
 #endif /* PUSH_ROUNDING  */
@@ -3390,26 +3357,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                                                                args_addr,
                                                                args_so_far),
                                                  skip));
-         if (current_function_check_memory_usage && ! in_check_memory_usage)
-           {
-             in_check_memory_usage = 1;
-             target = copy_to_reg (temp);
-             if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-               emit_library_call (chkr_copy_bitmap_libfunc,
-                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
-                                  target, Pmode,
-                                  XEXP (xinner, 0), Pmode,
-                                  size, TYPE_MODE (sizetype));
-             else
-               emit_library_call (chkr_set_right_libfunc,
-                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
-                                  target, Pmode,
-                                  size, TYPE_MODE (sizetype),
-                                  GEN_INT (MEMORY_USE_RW),
-                                  TYPE_MODE (integer_type_node));
-             in_check_memory_usage = 0;
-           }
-
          target = gen_rtx_MEM (BLKmode, temp);
 
          if (type != 0)
@@ -3608,30 +3555,8 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            }
 
          emit_move_insn (dest, x);
-
        }
 
-      if (current_function_check_memory_usage && ! in_check_memory_usage)
-       {
-         in_check_memory_usage = 1;
-         if (target == 0)
-           target = get_push_address (GET_MODE_SIZE (mode));
-
-         if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-           emit_library_call (chkr_copy_bitmap_libfunc,
-                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
-                              Pmode, XEXP (x, 0), Pmode,
-                              GEN_INT (GET_MODE_SIZE (mode)),
-                              TYPE_MODE (sizetype));
-         else
-           emit_library_call (chkr_set_right_libfunc,
-                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
-                              Pmode, GEN_INT (GET_MODE_SIZE (mode)),
-                              TYPE_MODE (sizetype),
-                              GEN_INT (MEMORY_USE_RW),
-                              TYPE_MODE (integer_type_node));
-         in_check_memory_usage = 0;
-       }
     }
 
  ret:
@@ -3643,7 +3568,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
       /* Handle calls that pass values in multiple non-contiguous locations.
         The Irix 6 ABI has examples of this.  */
       if (GET_CODE (reg) == PARALLEL)
-       emit_group_load (reg, x, -1, align);  /* ??? size? */
+       emit_group_load (reg, x, -1);  /* ??? size? */
       else
        move_block_to_reg (REGNO (reg), x, partial, mode);
     }
@@ -3714,15 +3639,15 @@ expand_assignment (to, from, want_value, suggest_reg)
     {
       enum machine_mode mode1;
       HOST_WIDE_INT bitsize, bitpos;
+      rtx orig_to_rtx;
       tree offset;
       int unsignedp;
       int volatilep = 0;
       tree tem;
-      unsigned int alignment;
 
       push_temp_slots ();
       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
-                                &unsignedp, &volatilep, &alignment);
+                                &unsignedp, &volatilep);
 
       /* If we are going to use store_bit_field and extract_bit_field,
         make sure to_rtx will be safe for multiple use.  */
@@ -3730,7 +3655,8 @@ expand_assignment (to, from, want_value, suggest_reg)
       if (mode1 == VOIDmode && want_value)
        tem = stabilize_reference (tem);
 
-      to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_DONT);
+      orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
+
       if (offset != 0)
        {
          rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
@@ -3751,10 +3677,10 @@ expand_assignment (to, from, want_value, suggest_reg)
          if (GET_CODE (to_rtx) == MEM
              && GET_MODE (to_rtx) == BLKmode
              && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
-             && bitsize
+             && bitsize > 0
              && (bitpos % bitsize) == 0
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-             && alignment == GET_MODE_ALIGNMENT (mode1))
+             && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
            {
              rtx temp
                = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
@@ -3772,111 +3698,70 @@ expand_assignment (to, from, want_value, suggest_reg)
                                   highest_pow2_factor (offset));
        }
 
-      if (volatilep)
+      if (GET_CODE (to_rtx) == MEM)
        {
-         if (GET_CODE (to_rtx) == MEM)
-           {
-             /* When the offset is zero, to_rtx is the address of the
-                structure we are storing into, and hence may be shared.
-                We must make a new MEM before setting the volatile bit.  */
-             if (offset == 0)
-               to_rtx = copy_rtx (to_rtx);
+         tree old_expr = MEM_EXPR (to_rtx);
 
-             MEM_VOLATILE_P (to_rtx) = 1;
-           }
-#if 0  /* This was turned off because, when a field is volatile
-         in an object which is not volatile, the object may be in a register,
-         and then we would abort over here.  */
-         else
-           abort ();
-#endif
+         /* If the field is at offset zero, we could have been given the
+            DECL_RTX of the parent struct.  Don't munge it.  */
+         to_rtx = shallow_copy_rtx (to_rtx);
+
+         set_mem_attributes (to_rtx, to, 0);
+
+         /* If we changed MEM_EXPR, that means we're now referencing
+            the COMPONENT_REF, which means that MEM_OFFSET must be
+            relative to that field.  But we've not yet reflected BITPOS
+            in TO_RTX.  This will be done in store_field.  Adjust for
+            that by biasing MEM_OFFSET by -bitpos.  */
+         if (MEM_EXPR (to_rtx) != old_expr && MEM_OFFSET (to_rtx)
+             && (bitpos / BITS_PER_UNIT) != 0)
+           set_mem_offset (to_rtx, GEN_INT (INTVAL (MEM_OFFSET (to_rtx))
+                                            - (bitpos / BITS_PER_UNIT)));
        }
 
-      if (TREE_CODE (to) == COMPONENT_REF
-         && TREE_READONLY (TREE_OPERAND (to, 1)))
+      /* Deal with volatile and readonly fields.  The former is only done
+        for MEM.  Also set MEM_KEEP_ALIAS_SET_P if needed.  */
+      if (volatilep && GET_CODE (to_rtx) == MEM)
        {
-         if (offset == 0)
+         if (to_rtx == orig_to_rtx)
            to_rtx = copy_rtx (to_rtx);
-
-         RTX_UNCHANGING_P (to_rtx) = 1;
+         MEM_VOLATILE_P (to_rtx) = 1;
        }
 
-      /* Check the access.  */
-      if (current_function_check_memory_usage && GET_CODE (to_rtx) == MEM)
+      if (TREE_CODE (to) == COMPONENT_REF
+         && TREE_READONLY (TREE_OPERAND (to, 1)))
        {
-         rtx to_addr;
-         int size;
-         int best_mode_size;
-         enum machine_mode best_mode;
-
-         best_mode = get_best_mode (bitsize, bitpos,
-                                    TYPE_ALIGN (TREE_TYPE (tem)),
-                                    mode1, volatilep);
-         if (best_mode == VOIDmode)
-           best_mode = QImode;
-
-         best_mode_size = GET_MODE_BITSIZE (best_mode);
-         to_addr = plus_constant (XEXP (to_rtx, 0), (bitpos / BITS_PER_UNIT));
-         size = CEIL ((bitpos % best_mode_size) + bitsize, best_mode_size);
-         size *= GET_MODE_SIZE (best_mode);
-
-         /* Check the access right of the pointer.  */
-         in_check_memory_usage = 1;
-         if (size)
-           emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
-                              VOIDmode, 3, to_addr, Pmode,
-                              GEN_INT (size), TYPE_MODE (sizetype),
-                              GEN_INT (MEMORY_USE_WO),
-                              TYPE_MODE (integer_type_node));
-         in_check_memory_usage = 0;
+         if (to_rtx == orig_to_rtx)
+           to_rtx = copy_rtx (to_rtx);
+         RTX_UNCHANGING_P (to_rtx) = 1;
        }
 
-      /* If this is a varying-length object, we must get the address of
-        the source and do an explicit block move.  */
-      if (bitsize < 0)
+      if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
        {
-         unsigned int from_align;
-         rtx from_rtx = expand_expr_unaligned (from, &from_align);
-         rtx inner_to_rtx
-           = adjust_address (to_rtx, BLKmode, bitpos / BITS_PER_UNIT);
-
-         emit_block_move (inner_to_rtx, from_rtx, expr_size (from));
-
-         free_temp_slots ();
-         pop_temp_slots ();
-         return to_rtx;
+         if (to_rtx == orig_to_rtx)
+           to_rtx = copy_rtx (to_rtx);
+         MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
        }
-      else
-       {
-         if (! can_address_p (to))
-           {
-             to_rtx = copy_rtx (to_rtx);
-             MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
-           }
 
-         result = store_field (to_rtx, bitsize, bitpos, mode1, from,
-                               (want_value
-                                /* Spurious cast for HPUX compiler.  */
-                                ? ((enum machine_mode)
-                                   TYPE_MODE (TREE_TYPE (to)))
-                                : VOIDmode),
-                               unsignedp,
-                               alignment,
-                               int_size_in_bytes (TREE_TYPE (tem)),
-                               get_alias_set (to));
+      result = store_field (to_rtx, bitsize, bitpos, mode1, from,
+                           (want_value
+                            /* Spurious cast for HPUX compiler.  */
+                            ? ((enum machine_mode)
+                               TYPE_MODE (TREE_TYPE (to)))
+                            : VOIDmode),
+                           unsignedp, TREE_TYPE (tem), get_alias_set (to));
 
-         preserve_temp_slots (result);
-         free_temp_slots ();
-         pop_temp_slots ();
+      preserve_temp_slots (result);
+      free_temp_slots ();
+      pop_temp_slots ();
 
-         /* If the value is meaningful, convert RESULT to the proper mode.
-            Otherwise, return nothing.  */
-         return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
-                                             TYPE_MODE (TREE_TYPE (from)),
-                                             result,
-                                             TREE_UNSIGNED (TREE_TYPE (to)))
-                 : NULL_RTX);
-       }
+      /* If the value is meaningful, convert RESULT to the proper mode.
+        Otherwise, return nothing.  */
+      return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
+                                         TYPE_MODE (TREE_TYPE (from)),
+                                         result,
+                                         TREE_UNSIGNED (TREE_TYPE (to)))
+             : NULL_RTX);
     }
 
   /* If the rhs is a function call and its value is not an aggregate,
@@ -3899,13 +3784,12 @@ expand_assignment (to, from, want_value, suggest_reg)
       push_temp_slots ();
       value = expand_expr (from, NULL_RTX, VOIDmode, 0);
       if (to_rtx == 0)
-       to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
+       to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
       /* Handle calls that return values in multiple non-contiguous locations.
         The Irix 6 ABI has examples of this.  */
       if (GET_CODE (to_rtx) == PARALLEL)
-       emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)),
-                        TYPE_ALIGN (TREE_TYPE (from)));
+       emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
       else if (GET_MODE (to_rtx) == BLKmode)
        emit_block_move (to_rtx, value, expr_size (from));
       else
@@ -3927,7 +3811,7 @@ expand_assignment (to, from, want_value, suggest_reg)
      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
 
   if (to_rtx == 0)
-    to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
+    to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
   /* Don't move directly into a return register.  */
   if (TREE_CODE (to) == RESULT_DECL
@@ -3939,8 +3823,7 @@ expand_assignment (to, from, want_value, suggest_reg)
       temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
 
       if (GET_CODE (to_rtx) == PARALLEL)
-       emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)),
-                        TYPE_ALIGN (TREE_TYPE (from)));
+       emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)));
       else
        emit_move_insn (to_rtx, temp);
 
@@ -3961,17 +3844,7 @@ expand_assignment (to, from, want_value, suggest_reg)
 
       push_temp_slots ();
       size = expr_size (from);
-      from_rtx = expand_expr (from, NULL_RTX, VOIDmode,
-                             EXPAND_MEMORY_USE_DONT);
-
-      /* Copy the rights of the bitmap.  */
-      if (current_function_check_memory_usage)
-       emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
-                          VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
-                          XEXP (from_rtx, 0), Pmode,
-                          convert_to_mode (TYPE_MODE (sizetype),
-                                           size, TREE_UNSIGNED (sizetype)),
-                          TYPE_MODE (sizetype));
+      from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
 
 #ifdef TARGET_MEM_FUNCTIONS
       emit_library_call (memmove_libfunc, LCT_NORMAL,
@@ -4174,13 +4047,19 @@ store_expr (exp, target, want_value)
         target.  Otherwise, the caller might get confused by a result whose
         mode is larger than expected.  */
 
-      if (want_value && GET_MODE (temp) != GET_MODE (target)
-         && GET_MODE (temp) != VOIDmode)
+      if (want_value && GET_MODE (temp) != GET_MODE (target))
        {
-         temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
-         SUBREG_PROMOTED_VAR_P (temp) = 1;
-         SUBREG_PROMOTED_UNSIGNED_P (temp)
-           = SUBREG_PROMOTED_UNSIGNED_P (target);
+         if (GET_MODE (temp) != VOIDmode)
+           {
+             temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
+             SUBREG_PROMOTED_VAR_P (temp) = 1;
+             SUBREG_PROMOTED_UNSIGNED_P (temp)
+               = SUBREG_PROMOTED_UNSIGNED_P (target);
+           }
+         else
+           temp = convert_modes (GET_MODE (target),
+                                 GET_MODE (SUBREG_REG (target)),
+                                 temp, SUBREG_PROMOTED_UNSIGNED_P (target));
        }
 
       return want_value ? temp : NULL_RTX;
@@ -4213,28 +4092,9 @@ store_expr (exp, target, want_value)
     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
                          temp, TREE_UNSIGNED (TREE_TYPE (exp)));
 
-  if (current_function_check_memory_usage
-      && GET_CODE (target) == MEM
-      && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
-    {
-      in_check_memory_usage = 1;
-      if (GET_CODE (temp) == MEM)
-       emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
-                          VOIDmode, 3, XEXP (target, 0), Pmode,
-                          XEXP (temp, 0), Pmode,
-                          expr_size (exp), TYPE_MODE (sizetype));
-      else
-       emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
-                          VOIDmode, 3, XEXP (target, 0), Pmode,
-                          expr_size (exp), TYPE_MODE (sizetype),
-                          GEN_INT (MEMORY_USE_WO),
-                          TYPE_MODE (integer_type_node));
-      in_check_memory_usage = 0;
-    }
-
   /* If value was not generated in the target, store it there.
-     Convert the value to TARGET's type first if nec.  */
-  /* If TEMP and TARGET compare equal according to rtx_equal_p, but
+     Convert the value to TARGET's type first if necessary.
+     If TEMP and TARGET compare equal according to rtx_equal_p, but
      one or both of them are volatile memory refs, we have to distinguish
      two cases:
      - expand_expr has used TARGET.  In this case, we must not generate
@@ -4271,15 +4131,12 @@ store_expr (exp, target, want_value)
 
       else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
        {
-         /* Handle copying a string constant into an array.
-            The string constant may be shorter than the array.
-            So copy just the string's actual length, and clear the rest.  */
-         rtx size;
-         rtx addr;
+         /* Handle copying a string constant into an array.  The string
+            constant may be shorter than the array.  So copy just the string's
+            actual length, and clear the rest.  First get the size of the data
+            type of the string, which is actually the size of the target.  */
+         rtx size = expr_size (exp);
 
-         /* Get the size of the data type of the string,
-            which is actually the size of the target.  */
-         size = expr_size (exp);
          if (GET_CODE (size) == CONST_INT
              && INTVAL (size) < TREE_STRING_LENGTH (exp))
            emit_block_move (target, temp, size);
@@ -4295,53 +4152,38 @@ store_expr (exp, target, want_value)
              rtx label = 0;
 
              /* Copy that much.  */
+             copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, 0);
              emit_block_move (target, temp, copy_size_rtx);
 
              /* Figure out how much is left in TARGET that we have to clear.
                 Do all calculations in ptr_mode.  */
-
-             addr = XEXP (target, 0);
-             addr = convert_modes (ptr_mode, Pmode, addr, 1);
-
              if (GET_CODE (copy_size_rtx) == CONST_INT)
                {
-                 addr = plus_constant (addr, TREE_STRING_LENGTH (exp));
-                 size = plus_constant (size, -TREE_STRING_LENGTH (exp));
+                 size = plus_constant (size, -INTVAL (copy_size_rtx));
+                 target = adjust_address (target, BLKmode,
+                                          INTVAL (copy_size_rtx));
                }
              else
                {
-                 addr = force_reg (ptr_mode, addr);
-                 addr = expand_binop (ptr_mode, add_optab, addr,
-                                      copy_size_rtx, NULL_RTX, 0,
-                                      OPTAB_LIB_WIDEN);
-
                  size = expand_binop (ptr_mode, sub_optab, size,
                                       copy_size_rtx, NULL_RTX, 0,
                                       OPTAB_LIB_WIDEN);
 
+#ifdef POINTERS_EXTEND_UNSIGNED
+                 if (GET_MODE (copy_size_rtx) != Pmode)
+                   copy_size_rtx = convert_memory_address (Pmode,
+                                                           copy_size_rtx);
+#endif
+
+                 target = offset_address (target, copy_size_rtx,
+                                          highest_pow2_factor (copy_size));
                  label = gen_label_rtx ();
                  emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
-                                          GET_MODE (size), 0, 0, label);
+                                          GET_MODE (size), 0, label);
                }
 
              if (size != const0_rtx)
-               {
-                 rtx dest = gen_rtx_MEM (BLKmode, addr);
-
-                 MEM_COPY_ATTRIBUTES (dest, target);
-
-                 /* Be sure we can write on ADDR.  */
-                 in_check_memory_usage = 1;
-                 if (current_function_check_memory_usage)
-                   emit_library_call (chkr_check_addr_libfunc,
-                                      LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
-                                      addr, Pmode,
-                                      size, TYPE_MODE (sizetype),
-                                      GEN_INT (MEMORY_USE_WO),
-                                      TYPE_MODE (integer_type_node));
-                 in_check_memory_usage = 0;
-                 clear_storage (dest, size);
-               }
+               clear_storage (target, size);
 
              if (label)
                emit_label (label);
@@ -4350,8 +4192,7 @@ store_expr (exp, target, want_value)
       /* Handle calls that return values in multiple non-contiguous locations.
         The Irix 6 ABI has examples of this.  */
       else if (GET_CODE (target) == PARALLEL)
-       emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)),
-                        TYPE_ALIGN (TREE_TYPE (exp)));
+       emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
       else if (GET_MODE (temp) == BLKmode)
        emit_block_move (target, temp, expr_size (exp));
       else
@@ -4390,6 +4231,7 @@ is_zeros_p (exp)
     case CONVERT_EXPR:
     case NOP_EXPR:
     case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
       return is_zeros_p (TREE_OPERAND (exp, 0));
 
     case INTEGER_CST:
@@ -4452,7 +4294,7 @@ mostly_zeros_p (exp)
 /* Helper function for store_constructor.
    TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
    TYPE is the type of the CONSTRUCTOR, not the element type.
-   ALIGN and CLEARED are as for store_constructor.
+   CLEARED is as for store_constructor.
    ALIAS_SET is the alias set to use for any stores.
 
    This provides a recursive shortcut back to store_constructor when it isn't
@@ -4461,14 +4303,13 @@ mostly_zeros_p (exp)
    clear a substructure if the outer structure has already been cleared.  */
 
 static void
-store_constructor_field (target, bitsize, bitpos,
-                        mode, exp, type, align, cleared, alias_set)
+store_constructor_field (target, bitsize, bitpos, mode, exp, type, cleared,
+                        alias_set)
      rtx target;
      unsigned HOST_WIDE_INT bitsize;
      HOST_WIDE_INT bitpos;
      enum machine_mode mode;
      tree exp, type;
-     unsigned int align;
      int cleared;
      int alias_set;
 {
@@ -4488,11 +4329,7 @@ store_constructor_field (target, bitsize, bitpos,
                            ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
 
 
-      /* Show the alignment may no longer be what it was and update the alias
-        set, if required.  */
-      if (bitpos != 0)
-       align = MIN (align, (unsigned int) bitpos & - bitpos);
-
+      /* Update the alias set, if required.  */
       if (GET_CODE (target) == MEM && ! MEM_KEEP_ALIAS_SET_P (target)
          && MEM_ALIAS_SET (target) != 0)
        {
@@ -4500,26 +4337,25 @@ store_constructor_field (target, bitsize, bitpos,
          set_mem_alias_set (target, alias_set);
        }
 
-      store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
+      store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
     }
   else
-    store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, align,
-                int_size_in_bytes (type), alias_set);
+    store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
+                alias_set);
 }
 
 /* Store the value of constructor EXP into the rtx TARGET.
-   TARGET is either a REG or a MEM.
-   ALIGN is the maximum known alignment for TARGET.
+   TARGET is either a REG or a MEM; we know it cannot conflict, since
+   safe_from_p has been called.
    CLEARED is true if TARGET is known to have been zero'd.
    SIZE is the number of bytes of TARGET we are allowed to modify: this
    may not be the same as the size of EXP if we are assigning to a field
    which has been packed to exclude padding bits.  */
 
 static void
-store_constructor (exp, target, align, cleared, size)
+store_constructor (exp, target, cleared, size)
      tree exp;
      rtx target;
-     unsigned int align;
      int cleared;
      HOST_WIDE_INT size;
 {
@@ -4528,47 +4364,30 @@ store_constructor (exp, target, align, cleared, size)
   HOST_WIDE_INT exp_size = int_size_in_bytes (type);
 #endif
 
-  /* We know our target cannot conflict, since safe_from_p has been called.  */
-#if 0
-  /* Don't try copying piece by piece into a hard register
-     since that is vulnerable to being clobbered by EXP.
-     Instead, construct in a pseudo register and then copy it all.  */
-  if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
-    {
-      rtx temp = gen_reg_rtx (GET_MODE (target));
-      store_constructor (exp, temp, align, cleared, size);
-      emit_move_insn (target, temp);
-      return;
-    }
-#endif
-
   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
       || TREE_CODE (type) == QUAL_UNION_TYPE)
     {
       tree elt;
 
-      /* Inform later passes that the whole union value is dead.  */
+      /* We either clear the aggregate or indicate the value is dead.  */
       if ((TREE_CODE (type) == UNION_TYPE
           || TREE_CODE (type) == QUAL_UNION_TYPE)
-         && ! cleared)
+         && ! cleared
+         && ! CONSTRUCTOR_ELTS (exp))
+       /* If the constructor is empty, clear the union.  */
        {
-         emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-
-         /* If the constructor is empty, clear the union.  */
-         if (! CONSTRUCTOR_ELTS (exp)  && ! cleared)
-           clear_storage (target, expr_size (exp));
+         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 (GET_CODE (target) == REG && TREE_STATIC (exp)
+      else if (! cleared && GET_CODE (target) == REG && TREE_STATIC (exp)
               && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
        {
-         if (! cleared)
-           emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
-
+         emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
          cleared = 1;
        }
 
@@ -4577,20 +4396,19 @@ store_constructor (exp, target, align, cleared, size)
         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
+      else if (! cleared && size > 0
               && ((list_length (CONSTRUCTOR_ELTS (exp))
                    != fields_length (type))
                   || mostly_zeros_p (exp))
               && (GET_CODE (target) != REG
-                  || (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target)) == size))
+                  || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
+                      == size)))
        {
-         if (! cleared)
-           clear_storage (target, GEN_INT (size));
-
+         clear_storage (target, GEN_INT (size));
          cleared = 1;
        }
-      else if (! cleared)
-       /* Inform later passes that the old value is dead.  */
+
+      if (! cleared)
        emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
 
       /* Store each element of the constructor into
@@ -4599,9 +4417,7 @@ store_constructor (exp, target, align, cleared, size)
       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
        {
          tree field = TREE_PURPOSE (elt);
-#ifdef WORD_REGISTER_OPERATIONS
          tree value = TREE_VALUE (elt);
-#endif
          enum machine_mode mode;
          HOST_WIDE_INT bitsize;
          HOST_WIDE_INT bitpos = 0;
@@ -4615,7 +4431,7 @@ store_constructor (exp, target, align, cleared, size)
          if (field == 0)
            continue;
 
-         if (cleared && is_zeros_p (TREE_VALUE (elt)))
+         if (cleared && is_zeros_p (value))
            continue;
 
          if (host_integerp (DECL_SIZE (field), 1))
@@ -4660,8 +4476,6 @@ store_constructor (exp, target, align, cleared, size)
 
              to_rtx = offset_address (to_rtx, offset_rtx,
                                       highest_pow2_factor (offset));
-
-             align = DECL_OFFSET_ALIGN (field);
            }
 
          if (TREE_READONLY (field))
@@ -4686,11 +4500,13 @@ store_constructor (exp, target, align, cleared, size)
              && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
            {
              tree type = TREE_TYPE (value);
+
              if (TYPE_PRECISION (type) < BITS_PER_WORD)
                {
                  type = type_for_size (BITS_PER_WORD, TREE_UNSIGNED (type));
                  value = convert (type, value);
                }
+
              if (BYTES_BIG_ENDIAN)
                value
                  = fold (build (LSHIFT_EXPR, type, value,
@@ -4708,7 +4524,7 @@ store_constructor (exp, target, align, cleared, size)
            }
 
          store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                  TREE_VALUE (elt), type, align, cleared,
+                                  value, type, cleared,
                                   get_alias_set (TREE_TYPE (field)));
        }
     }
@@ -4805,7 +4621,6 @@ store_constructor (exp, target, align, cleared, size)
          HOST_WIDE_INT bitpos;
          int unsignedp;
          tree value = TREE_VALUE (elt);
-         unsigned int align = TYPE_ALIGN (TREE_TYPE (value));
          tree index = TREE_PURPOSE (elt);
          rtx xtarget = target;
 
@@ -4857,8 +4672,8 @@ store_constructor (exp, target, align, cleared, size)
                        }
 
                      store_constructor_field
-                       (target, bitsize, bitpos, mode, value, type, align,
-                        cleared, get_alias_set (elttype));
+                       (target, bitsize, bitpos, mode, value, type, cleared,
+                        get_alias_set (elttype));
                    }
                }
              else
@@ -4900,7 +4715,7 @@ store_constructor (exp, target, align, cleared, size)
                                            highest_pow2_factor (position));
                  xtarget = adjust_address (xtarget, mode, 0);
                  if (TREE_CODE (value) == CONSTRUCTOR)
-                   store_constructor (value, xtarget, align, cleared,
+                   store_constructor (value, xtarget, cleared,
                                       bitsize / BITS_PER_UNIT);
                  else
                    store_expr (value, xtarget, 0);
@@ -4954,8 +4769,7 @@ store_constructor (exp, target, align, cleared, size)
                }
 
              store_constructor_field (target, bitsize, bitpos, mode, value,
-                                      type, align, cleared,
-                                      get_alias_set (elttype));
+                                      type, cleared, get_alias_set (elttype));
 
            }
        }
@@ -5155,16 +4969,15 @@ store_constructor (exp, target, align, cleared, size)
    has mode VALUE_MODE if that is convenient to do.
    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
 
-   ALIGN is the alignment that TARGET is known to have.
-   TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.
+   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.  */
 
 static rtx
-store_field (target, bitsize, bitpos, mode, exp, value_mode,
-            unsignedp, align, total_size, alias_set)
+store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
+            alias_set)
      rtx target;
      HOST_WIDE_INT bitsize;
      HOST_WIDE_INT bitpos;
@@ -5172,8 +4985,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
      tree exp;
      enum machine_mode value_mode;
      int unsignedp;
-     unsigned int align;
-     HOST_WIDE_INT total_size;
+     tree type;
      int alias_set;
 {
   HOST_WIDE_INT width_mask = 0;
@@ -5185,8 +4997,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
      side-effects.  */
   if (bitsize == 0)
     return expand_expr (exp, const0_rtx, VOIDmode, 0);
-
-  if (bitsize < HOST_BITS_PER_WIDE_INT)
+  else if (bitsize >=0 && bitsize < HOST_BITS_PER_WIDE_INT)
     width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
 
   /* If we are storing into an unaligned field of an aligned union that is
@@ -5205,23 +5016,19 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
     {
       rtx object
        = assign_temp
-         (build_qualified_type (type_for_mode (GET_MODE (target), 0),
-                                TYPE_QUAL_CONST),
+         (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
           0, 1, 1);
-      rtx blk_object = copy_rtx (object);
-
-      PUT_MODE (blk_object, BLKmode);
+      rtx blk_object = adjust_address (object, BLKmode, 0);
 
       if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
 
-      store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
-                  align, total_size, alias_set);
+      store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
+                  alias_set);
 
-      /* Even though we aren't returning target, we need to
-        give it the updated value.  */
       emit_move_insn (target, object);
 
+      /* We want to return the BLKmode version of the data.  */
       return blk_object;
     }
 
@@ -5246,12 +5053,9 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
       || GET_CODE (target) == SUBREG
       /* If the field isn't aligned enough to store as an ordinary memref,
         store it as a bit field.  */
-      || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
-         && (align < GET_MODE_ALIGNMENT (mode)
+      || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))
+         && (MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode)
              || bitpos % GET_MODE_ALIGNMENT (mode)))
-      || (mode == BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
-         && (TYPE_ALIGN (TREE_TYPE (exp)) > align
-             || bitpos % TYPE_ALIGN (TREE_TYPE (exp)) != 0))
       /* If the RHS and field are a constant size and the size of the
         RHS isn't the same size as the bitfield, we must use bitfield
         operations.  */
@@ -5266,7 +5070,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
         low-order bits.  However, if EXP's type is a record and this is
         big-endian machine, we want the upper BITSIZE bits.  */
       if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
-         && bitsize < GET_MODE_BITSIZE (GET_MODE (temp))
+         && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
          && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
                             size_int (GET_MODE_BITSIZE (GET_MODE (temp))
@@ -5284,35 +5088,26 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
         boundary.  If so, we simply do a block copy.  */
       if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
        {
-         unsigned int exp_align = expr_align (exp);
-
          if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
              || bitpos % BITS_PER_UNIT != 0)
            abort ();
 
          target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
-
-         /* Make sure that ALIGN is no stricter than the alignment of EXP.  */
-         align = MIN (exp_align, align);
-
-         /* Find an alignment that is consistent with the bit position.  */
-         while ((bitpos % align) != 0)
-           align >>= 1;
-
          emit_block_move (target, temp,
-                          bitsize == -1 ? expr_size (exp)
-                          : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-                                     / BITS_PER_UNIT));
+                          GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+                                   / BITS_PER_UNIT));
 
          return value_mode == VOIDmode ? const0_rtx : target;
        }
 
       /* Store the value in the bitfield.  */
-      store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size);
+      store_bit_field (target, bitsize, bitpos, mode, temp,
+                      int_size_in_bytes (type));
+
       if (value_mode != VOIDmode)
        {
-         /* The caller wants an rtx for the value.  */
-         /* If possible, avoid refetching from the bitfield itself.  */
+         /* The caller wants an rtx for the value.
+            If possible, avoid refetching from the bitfield itself.  */
          if (width_mask != 0
              && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
            {
@@ -5327,6 +5122,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
                                     GET_MODE (temp) == VOIDmode
                                     ? value_mode
                                     : GET_MODE (temp))), NULL_RTX);
+
              tmode = GET_MODE (temp);
              if (tmode == VOIDmode)
                tmode = value_mode;
@@ -5334,16 +5130,17 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
            }
+
          return extract_bit_field (target, bitsize, bitpos, unsignedp,
-                                   NULL_RTX, value_mode, 0, align,
-                                   total_size);
+                                   NULL_RTX, value_mode, VOIDmode,
+                                   int_size_in_bytes (type));
        }
       return const0_rtx;
     }
   else
     {
       rtx addr = XEXP (target, 0);
-      rtx to_rtx;
+      rtx to_rtx = target;
 
       /* If a value is wanted, it must be the lhs;
         so make the address stable for multiple use.  */
@@ -5355,19 +5152,18 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
                && GET_CODE (XEXP (addr, 1)) == CONST_INT
                && (XEXP (addr, 0) == virtual_incoming_args_rtx
                    || XEXP (addr, 0) == virtual_stack_vars_rtx)))
-       target = replace_equiv_address (target, copy_to_reg (addr));
+       to_rtx = replace_equiv_address (to_rtx, copy_to_reg (addr));
 
       /* Now build a reference to just the desired component.  */
 
-      to_rtx = copy_rtx (adjust_address (target, mode,
-                                        bitpos / BITS_PER_UNIT));
+      to_rtx = adjust_address (target, mode, bitpos / BITS_PER_UNIT);
+
+      if (to_rtx == target)
+       to_rtx = copy_rtx (to_rtx);
 
       MEM_SET_IN_STRUCT_P (to_rtx, 1);
       if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
-       {
-         to_rtx = copy_rtx (to_rtx);
-         set_mem_alias_set (to_rtx, alias_set);
-       }
+       set_mem_alias_set (to_rtx, alias_set);
 
       return store_expr (exp, to_rtx, value_mode != VOIDmode);
     }
@@ -5383,9 +5179,6 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
    giving the variable offset (in units) in *POFFSET.
    This offset is in addition to the bit position.
    If the position is not variable, we store 0 in *POFFSET.
-   We set *PALIGNMENT to the alignment of the address that will be
-   computed.  This is the alignment of the thing we return if *POFFSET
-   is zero, but can be more less strictly aligned if *POFFSET is nonzero.
 
    If any of the extraction expressions is volatile,
    we store 1 in *PVOLATILEP.  Otherwise we don't change that.
@@ -5400,7 +5193,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
 
 tree
 get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
-                    punsignedp, pvolatilep, palignment)
+                    punsignedp, pvolatilep)
      tree exp;
      HOST_WIDE_INT *pbitsize;
      HOST_WIDE_INT *pbitpos;
@@ -5408,13 +5201,11 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
      enum machine_mode *pmode;
      int *punsignedp;
      int *pvolatilep;
-     unsigned int *palignment;
 {
   tree size_tree = 0;
   enum machine_mode mode = VOIDmode;
   tree offset = size_zero_node;
   tree bit_offset = bitsize_zero_node;
-  unsigned int alignment = BIGGEST_ALIGNMENT;
   tree placeholder_ptr = 0;
   tree tem;
 
@@ -5476,8 +5267,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
          bit_offset = size_binop (PLUS_EXPR, bit_offset,
                                   DECL_FIELD_BIT_OFFSET (field));
 
-         if (! host_integerp (offset, 0))
-           alignment = MIN (alignment, DECL_OFFSET_ALIGN (field));
+         /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN.  */
        }
 
       else if (TREE_CODE (exp) == ARRAY_REF
@@ -5528,6 +5318,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
          continue;
        }
       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
+              && TREE_CODE (exp) != VIEW_CONVERT_EXPR
               && ! ((TREE_CODE (exp) == NOP_EXPR
                      || TREE_CODE (exp) == CONVERT_EXPR)
                     && (TYPE_MODE (TREE_TYPE (exp))
@@ -5538,19 +5329,9 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
       if (TREE_THIS_VOLATILE (exp))
        *pvolatilep = 1;
 
-      /* If the offset is non-constant already, then we can't assume any
-        alignment more than the alignment here.  */
-      if (! TREE_CONSTANT (offset))
-       alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
-
       exp = TREE_OPERAND (exp, 0);
     }
 
-  if (DECL_P (exp))
-    alignment = MIN (alignment, DECL_ALIGN (exp));
-  else if (TREE_TYPE (exp) != 0)
-    alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
-
   /* If OFFSET is constant, see if we can return the whole thing as a
      constant bit position.  Otherwise, split it up.  */
   if (host_integerp (offset, 0)
@@ -5563,38 +5344,32 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
     *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
 
   *pmode = mode;
-  *palignment = alignment;
   return exp;
 }
 
-/* Subroutine of expand_exp: compute memory_usage from modifier.  */
+/* Return 1 if T is an expression that get_inner_reference handles.  */
 
-static enum memory_use_mode
-get_memory_usage_from_modifier (modifier)
-     enum expand_modifier modifier;
+int
+handled_component_p (t)
+     tree t;
 {
-  switch (modifier)
+  switch (TREE_CODE (t))
     {
-    case EXPAND_NORMAL:
-    case EXPAND_SUM:
-      return MEMORY_USE_RO;
-      break;
-    case EXPAND_MEMORY_USE_WO:
-      return MEMORY_USE_WO;
-      break;
-    case EXPAND_MEMORY_USE_RW:
-      return MEMORY_USE_RW;
-      break;
-    case EXPAND_MEMORY_USE_DONT:
-      /* EXPAND_CONST_ADDRESS and EXPAND_INITIALIZER are converted into
-        MEMORY_USE_DONT, because they are modifiers to a call of
-        expand_expr in the ADDR_EXPR case of expand_expr.  */
-    case EXPAND_CONST_ADDRESS:
-    case EXPAND_INITIALIZER:
-      return MEMORY_USE_DONT;
-    case EXPAND_MEMORY_USE_BAD:
+    case BIT_FIELD_REF:
+    case COMPONENT_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case NON_LVALUE_EXPR:
+    case VIEW_CONVERT_EXPR:
+      return 1;
+
+    case NOP_EXPR:
+    case CONVERT_EXPR:
+      return (TYPE_MODE (TREE_TYPE (t))
+             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
+
     default:
-      abort ();
+      return 0;
     }
 }
 \f
@@ -5686,6 +5461,22 @@ force_operand (value, target)
       /* We give UNSIGNEDP = 0 to expand_binop
         because the only operations we are expanding here are signed ones.  */
     }
+
+#ifdef INSN_SCHEDULING
+  /* On machines that have insn scheduling, we want all memory reference to be
+     explicit, so we need to deal with such paradoxical SUBREGs.  */
+  if (GET_CODE (value) == SUBREG && GET_CODE (SUBREG_REG (value)) == MEM
+      && (GET_MODE_SIZE (GET_MODE (value))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
+    value
+      = simplify_gen_subreg (GET_MODE (value),
+                            force_reg (GET_MODE (SUBREG_REG (value)),
+                                       force_operand (SUBREG_REG (value),
+                                                      NULL_RTX)),
+                            GET_MODE (SUBREG_REG (value)),
+                            SUBREG_BYTE (value));
+#endif
+
   return value;
 }
 \f
@@ -5901,8 +5692,7 @@ safe_from_p (x, exp, top_p)
         special handling.  */
       if ((unsigned int) TREE_CODE (exp)
          >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
-         && lang_safe_from_p
-         && !(*lang_safe_from_p) (x, exp))
+         && !(*lang_hooks.safe_from_p) (x, exp))
        return 0;
     }
 
@@ -6015,19 +5805,24 @@ highest_pow2_factor (exp)
   switch (TREE_CODE (exp))
     {
     case INTEGER_CST:
-      /* If the integer is expressable in a HOST_WIDE_INT, we can find
-        the lowest bit that's a one.  If the result is zero or negative,
-        pessimize by returning 1.  This is overly-conservative, but such
-        things should not happen in the offset expressions that we are
-        called with.  */
-      if (host_integerp (exp, 0))
+      /* If the integer is expressable in a HOST_WIDE_INT, we can find the
+        lowest bit that's a one.  If the result is zero, return
+        BIGGEST_ALIGNMENT.  We need to handle this case since we can find it
+        in a COND_EXPR, a MIN_EXPR, or a MAX_EXPR.  If the constant overlows,
+        we have an erroneous program, so return BIGGEST_ALIGNMENT to avoid any
+        later ICE.  */
+      if (TREE_CONSTANT_OVERFLOW (exp)
+         || integer_zerop (exp))
+       return BIGGEST_ALIGNMENT;
+      else if (host_integerp (exp, 0))
        {
          c0 = tree_low_cst (exp, 0);
-         return c0 >= 0 ? c0 & -c0 : 1;
+         c0 = c0 < 0 ? - c0 : c0;
+         return c0 & -c0;
        }
       break;
 
-    case PLUS_EXPR:  case MINUS_EXPR:
+    case PLUS_EXPR:  case MINUS_EXPR:  case MIN_EXPR:  case MAX_EXPR:
       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
       return MIN (c0, c1);
@@ -6039,14 +5834,22 @@ highest_pow2_factor (exp)
 
     case ROUND_DIV_EXPR:  case TRUNC_DIV_EXPR:  case FLOOR_DIV_EXPR:
     case CEIL_DIV_EXPR:
-      c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-      c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-      return MAX (1, c0 / c1);
+      if (integer_pow2p (TREE_OPERAND (exp, 1))
+         && host_integerp (TREE_OPERAND (exp, 1), 1))
+       {
+         c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
+         c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
+         return MAX (1, c0 / c1);
+       }
+      break;
 
     case NON_LVALUE_EXPR:  case NOP_EXPR:  case CONVERT_EXPR:
-    case COMPOUND_EXPR:  case SAVE_EXPR:
+    case SAVE_EXPR: case WITH_RECORD_EXPR:
       return highest_pow2_factor (TREE_OPERAND (exp, 0));
 
+    case COMPOUND_EXPR:
+      return highest_pow2_factor (TREE_OPERAND (exp, 1));
+
     case COND_EXPR:
       c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
       c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
@@ -6176,8 +5979,6 @@ expand_expr (exp, target, tmode, modifier)
   rtx subtarget, original_target;
   int ignore;
   tree context;
-  /* Used by check-memory-usage to make modifier read only.  */
-  enum expand_modifier ro_modifier;
 
   /* Handle ERROR_MARK before anybody tries to access its type.  */
   if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
@@ -6195,16 +5996,9 @@ expand_expr (exp, target, tmode, modifier)
   ignore = (target == const0_rtx
            || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
                 || code == CONVERT_EXPR || code == REFERENCE_EXPR
-                || code == COND_EXPR)
+                || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
                && TREE_CODE (type) == VOID_TYPE));
 
-  /* Make a read-only version of the modifier.  */
-  if (modifier == EXPAND_NORMAL || modifier == EXPAND_SUM
-      || modifier == EXPAND_CONST_ADDRESS || modifier == EXPAND_INITIALIZER)
-    ro_modifier = modifier;
-  else
-    ro_modifier = EXPAND_NORMAL;
-
   /* If we are going to ignore this result, we need only do something
      if there is a side-effect somewhere in the expression.  If there
      is, short-circuit the most common cases here.  Note that we must
@@ -6223,7 +6017,7 @@ expand_expr (exp, target, tmode, modifier)
          && mode != VOIDmode && mode != BLKmode
          && modifier != EXPAND_CONST_ADDRESS)
        {
-         temp = expand_expr (exp, NULL_RTX, VOIDmode, ro_modifier);
+         temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
          if (GET_CODE (temp) == MEM)
            temp = copy_to_reg (temp);
          return const0_rtx;
@@ -6231,34 +6025,30 @@ expand_expr (exp, target, tmode, modifier)
 
       if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF
          || code == INDIRECT_REF || code == BUFFER_REF)
-       return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
-                           VOIDmode, ro_modifier);
+       return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
+                           modifier);
+
       else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
               || code == ARRAY_REF || code == ARRAY_RANGE_REF)
        {
-         expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                      ro_modifier);
-         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode,
-                      ro_modifier);
+         expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
+         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
          return const0_rtx;
        }
       else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
               && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
        /* If the second operand has no side effects, just evaluate
           the first.  */
-       return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
-                           VOIDmode, ro_modifier);
+       return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
+                           modifier);
       else if (code == BIT_FIELD_REF)
        {
-         expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                      ro_modifier);
-         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode,
-                      ro_modifier);
-         expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode,
-                      ro_modifier);
+         expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
+         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
+         expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier);
          return const0_rtx;
        }
-      ;
+
       target = 0;
     }
 
@@ -6308,10 +6098,12 @@ expand_expr (exp, target, tmode, modifier)
   /* If will do cse, generate all results into pseudo registers
      since 1) that allows cse to find more things
      and 2) otherwise cse could produce an insn the machine
-     cannot support.  */
+     cannot support.  And exception is a CONSTRUCTOR into a multi-word
+     MEM: that's much more likely to be most efficient into the MEM.  */
 
   if (! cse_not_expected && mode != BLKmode && target
-      && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER))
+      && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
+      && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
     target = subtarget;
 
   switch (code)
@@ -6359,36 +6151,19 @@ expand_expr (exp, target, tmode, modifier)
       if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
          && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
        {
-         layout_decl (exp, 0);
-         PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
-       }
+         rtx value = DECL_RTL_IF_SET (exp);
 
-      /* Although static-storage variables start off initialized, according to
-        ANSI C, a memcpy could overwrite them with uninitialized values.  So
-        we check them too.  This also lets us check for read-only variables
-        accessed via a non-const declaration, in case it won't be detected
-        any other way (e.g., in an embedded system or OS kernel without
-        memory protection).
-
-        Aggregates are not checked here; they're handled elsewhere.  */
-      if (cfun && current_function_check_memory_usage
-         && code == VAR_DECL
-         && GET_CODE (DECL_RTL (exp)) == MEM
-         && ! AGGREGATE_TYPE_P (TREE_TYPE (exp)))
-       {
-         enum memory_use_mode memory_usage;
-         memory_usage = get_memory_usage_from_modifier (modifier);
+         layout_decl (exp, 0);
 
-         in_check_memory_usage = 1;
-         if (memory_usage != MEMORY_USE_DONT)
-           emit_library_call (chkr_check_addr_libfunc,
-                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
-                              XEXP (DECL_RTL (exp), 0), Pmode,
-                              GEN_INT (int_size_in_bytes (type)),
-                              TYPE_MODE (sizetype),
-                              GEN_INT (memory_usage),
-                              TYPE_MODE (integer_type_node));
-         in_check_memory_usage = 0;
+         /* If the RTL was already set, update its mode and memory
+            attributes.  */
+         if (value != 0)
+           {
+             PUT_MODE (value, DECL_MODE (exp));
+             SET_DECL_RTL (exp, 0);
+             set_mem_attributes (value, exp, 1);
+             SET_DECL_RTL (exp, value);
+           }
        }
 
       /* ... fall through ...  */
@@ -6482,7 +6257,7 @@ expand_expr (exp, target, tmode, modifier)
         but mark it so that we know that it was already extended.  */
 
       if (GET_CODE (DECL_RTL (exp)) == REG
-         && GET_MODE (DECL_RTL (exp)) != mode)
+         && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
        {
          /* Get the signedness used for this variable.  Ensure we get the
             same mode we got when the variable was declared.  */
@@ -6503,8 +6278,7 @@ expand_expr (exp, target, tmode, modifier)
                                 TREE_INT_CST_HIGH (exp), mode);
 
     case CONST_DECL:
-      return expand_expr (DECL_INITIAL (exp), target, VOIDmode,
-                         EXPAND_MEMORY_USE_BAD);
+      return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
 
     case REAL_CST:
       /* If optimized, generate immediate CONST_DOUBLE
@@ -6617,8 +6391,7 @@ expand_expr (exp, target, tmode, modifier)
            }
 
          if (temp == const0_rtx)
-           expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                        EXPAND_MEMORY_USE_BAD);
+           expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
          else
            store_expr (TREE_OPERAND (exp, 0), temp, 0);
 
@@ -6660,7 +6433,7 @@ expand_expr (exp, target, tmode, modifier)
          abort ();
 
        placeholder_list = TREE_CHAIN (placeholder_expr);
-       temp = expand_expr (exp, original_target, tmode, ro_modifier);
+       temp = expand_expr (exp, original_target, tmode, modifier);
        placeholder_list = old_list;
        return temp;
       }
@@ -6673,8 +6446,8 @@ expand_expr (exp, target, tmode, modifier)
         and pop the list.  */
       placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
                                    placeholder_list);
-      target = expand_expr (TREE_OPERAND (exp, 0), original_target,
-                           tmode, ro_modifier);
+      target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode,
+                           modifier);
       placeholder_list = TREE_CHAIN (placeholder_list);
       return target;
 
@@ -6692,7 +6465,7 @@ expand_expr (exp, target, tmode, modifier)
 
     case LABELED_BLOCK_EXPR:
       if (LABELED_BLOCK_BODY (exp))
-       expand_expr_stmt (LABELED_BLOCK_BODY (exp));
+       expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
       /* Should perhaps use expand_label, but this is simpler and safer.  */
       do_pending_stack_adjust ();
       emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
@@ -6707,7 +6480,7 @@ expand_expr (exp, target, tmode, modifier)
     case LOOP_EXPR:
       push_temp_slots ();
       expand_start_loop (1);
-      expand_expr_stmt (TREE_OPERAND (exp, 0));
+      expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
       expand_end_loop ();
       pop_temp_slots ();
 
@@ -6739,7 +6512,7 @@ expand_expr (exp, target, tmode, modifier)
            vars = TREE_CHAIN (vars);
          }
 
-       temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, ro_modifier);
+       temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
 
        expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
 
@@ -6764,9 +6537,10 @@ expand_expr (exp, target, tmode, modifier)
       if (ignore)
        {
          tree elt;
+
          for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-           expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode,
-                        EXPAND_MEMORY_USE_BAD);
+           expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
+
          return const0_rtx;
        }
 
@@ -6808,9 +6582,9 @@ expand_expr (exp, target, tmode, modifier)
                                                   (TYPE_QUALS (type)
                                                    | (TREE_READONLY (exp)
                                                       * TYPE_QUAL_CONST))),
-                            TREE_ADDRESSABLE (exp), 1, 1);
+                            0, TREE_ADDRESSABLE (exp), 1);
 
-         store_constructor (exp, target, TYPE_ALIGN (TREE_TYPE (exp)), 0,
+         store_constructor (exp, target, 0,
                             int_size_in_bytes (TREE_TYPE (exp)));
          return target;
        }
@@ -6828,39 +6602,19 @@ expand_expr (exp, target, tmode, modifier)
            && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
            && GET_MODE_CLASS (mode) == MODE_INT
            && GET_MODE_SIZE (mode) == 1
-           && modifier != EXPAND_MEMORY_USE_WO)
+           && modifier != EXPAND_WRITE)
          return
            GEN_INT (TREE_STRING_POINTER (string)[TREE_INT_CST_LOW (index)]);
 
        op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address (mode, op0);
-
-       if (cfun && current_function_check_memory_usage
-           && ! AGGREGATE_TYPE_P (TREE_TYPE (exp)))
-         {
-           enum memory_use_mode memory_usage;
-           memory_usage = get_memory_usage_from_modifier (modifier);
-
-            if (memory_usage != MEMORY_USE_DONT)
-             {
-               in_check_memory_usage = 1;
-               emit_library_call (chkr_check_addr_libfunc,
-                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, op0,
-                                  Pmode, GEN_INT (int_size_in_bytes (type)),
-                                  TYPE_MODE (sizetype),
-                                  GEN_INT (memory_usage),
-                                  TYPE_MODE (integer_type_node));
-               in_check_memory_usage = 0;
-             }
-         }
-
        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_MEMORY_USE_WO && readonly_fields_p (type))
+       if (modifier == EXPAND_WRITE && readonly_fields_p (type))
          RTX_UNCHANGING_P (temp) = 1;
 
        return temp;
@@ -6922,8 +6676,8 @@ expand_expr (exp, target, tmode, modifier)
              ;
 
            if (elem)
-             return expand_expr (fold (TREE_VALUE (elem)), target,
-                                 tmode, ro_modifier);
+             return expand_expr (fold (TREE_VALUE (elem)), target, tmode,
+                                 modifier);
          }
 
        else if (optimize >= 1
@@ -6949,7 +6703,7 @@ expand_expr (exp, target, tmode, modifier)
 
                    if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
                      return expand_expr (fold (TREE_VALUE (elem)), target,
-                                         tmode, ro_modifier);
+                                         tmode, modifier);
                  }
                else if (TREE_CODE (init) == STRING_CST
                         && 0 > compare_tree_int (index,
@@ -7033,10 +6787,8 @@ expand_expr (exp, target, tmode, modifier)
        HOST_WIDE_INT bitsize, bitpos;
        tree offset;
        int volatilep = 0;
-       unsigned int alignment;
        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-                                       &mode1, &unsignedp, &volatilep,
-                                       &alignment);
+                                       &mode1, &unsignedp, &volatilep);
        rtx orig_op0;
 
        /* If we got back the original object, something is wrong.  Perhaps
@@ -7098,7 +6850,6 @@ expand_expr (exp, target, tmode, modifier)
                                               | TYPE_QUAL_CONST));
                    rtx memloc = assign_temp (nt, 1, 1, 1);
 
-                   mark_temp_addr_taken (memloc);
                    emit_move_insn (memloc, op0);
                    op0 = memloc;
                  }
@@ -7123,7 +6874,7 @@ expand_expr (exp, target, tmode, modifier)
                && bitsize != 0
                && (bitpos % bitsize) == 0
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-               && alignment == GET_MODE_ALIGNMENT (mode1))
+               && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
              {
                rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
 
@@ -7150,34 +6901,6 @@ expand_expr (exp, target, tmode, modifier)
            MEM_VOLATILE_P (op0) = 1;
          }
 
-       /* Check the access.  */
-       if (cfun != 0 && current_function_check_memory_usage
-           && GET_CODE (op0) == MEM)
-         {
-           enum memory_use_mode memory_usage;
-           memory_usage = get_memory_usage_from_modifier (modifier);
-
-           if (memory_usage != MEMORY_USE_DONT)
-             {
-               rtx to;
-               int size;
-
-               to = plus_constant (XEXP (op0, 0), (bitpos / BITS_PER_UNIT));
-               size = (bitpos % BITS_PER_UNIT) + bitsize + BITS_PER_UNIT - 1;
-
-               /* Check the access right of the pointer.  */
-               in_check_memory_usage = 1;
-               if (size > BITS_PER_UNIT)
-                 emit_library_call (chkr_check_addr_libfunc,
-                                    LCT_CONST_MAKE_BLOCK, VOIDmode, 3, to,
-                                    Pmode, GEN_INT (size / BITS_PER_UNIT),
-                                    TYPE_MODE (sizetype),
-                                    GEN_INT (memory_usage),
-                                    TYPE_MODE (integer_type_node));
-               in_check_memory_usage = 0;
-             }
-         }
-
        /* In cases where an aligned union has an unaligned object
           as a field, we might be extracting a BLKmode value from
           an integer-mode (e.g., SImode) object.  Handle this case
@@ -7194,7 +6917,7 @@ expand_expr (exp, target, tmode, modifier)
            /* If the field isn't aligned enough to fetch as a memref,
               fetch it as a bit field.  */
            || (mode1 != BLKmode
-               && SLOW_UNALIGNED_ACCESS (mode1, alignment)
+               && SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))
                && ((TYPE_ALIGN (TREE_TYPE (tem))
                     < GET_MODE_ALIGNMENT (mode))
                    || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
@@ -7205,11 +6928,7 @@ expand_expr (exp, target, tmode, modifier)
                && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
                    == INTEGER_CST)
                && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
-                                         bitsize))
-           || (mode == BLKmode
-               && SLOW_UNALIGNED_ACCESS (mode, alignment)
-               && (TYPE_ALIGN (type) > alignment
-                   || bitpos % TYPE_ALIGN (type) != 0)))
+                                         bitsize)))
          {
            enum machine_mode ext_mode = mode;
 
@@ -7233,9 +6952,8 @@ expand_expr (exp, target, tmode, modifier)
                  target = assign_temp (type, 0, 1, 1);
 
                emit_block_move (target, op0,
-                                bitsize == -1 ? expr_size  (exp)
-                                : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-                                           / BITS_PER_UNIT));
+                                GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+                                         / BITS_PER_UNIT));
 
                return target;
              }
@@ -7243,11 +6961,10 @@ expand_expr (exp, target, tmode, modifier)
            op0 = validize_mem (op0);
 
            if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG)
-             mark_reg_pointer (XEXP (op0, 0), alignment);
+             mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
 
            op0 = extract_bit_field (op0, bitsize, bitpos,
                                     unsignedp, target, ext_mode, ext_mode,
-                                    alignment,
                                     int_size_in_bytes (TREE_TYPE (tem)));
 
            /* If the result is a record type and BITSIZE is narrower than
@@ -7255,7 +6972,7 @@ expand_expr (exp, target, tmode, modifier)
               machine, we must put the field into the high-order bits.  */
            if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
                && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-               && bitsize < GET_MODE_BITSIZE (GET_MODE (op0)))
+               && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
              op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
                                  size_int (GET_MODE_BITSIZE (GET_MODE (op0))
                                            - bitsize),
@@ -7263,13 +6980,14 @@ expand_expr (exp, target, tmode, modifier)
 
            if (mode == BLKmode)
              {
-               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
-                                               TYPE_QUAL_CONST);
-               rtx new = assign_temp (nt, 0, 1, 1);
+               rtx new = assign_temp (build_qualified_type
+                                      (type_for_mode (ext_mode, 0),
+                                       TYPE_QUAL_CONST), 0, 1, 1);
 
                emit_move_insn (new, op0);
                op0 = copy_rtx (new);
                PUT_MODE (op0, BLKmode);
+               set_mem_attributes (op0, exp, 1);
              }
 
            return op0;
@@ -7292,7 +7010,7 @@ expand_expr (exp, target, tmode, modifier)
 
        set_mem_attributes (op0, exp, 0);
        if (GET_CODE (XEXP (op0, 0)) == REG)
-         mark_reg_pointer (XEXP (op0, 0), alignment);
+         mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
 
        MEM_VOLATILE_P (op0) |= volatilep;
        if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
@@ -7399,17 +7117,13 @@ expand_expr (exp, target, tmode, modifier)
 
        if (! (GET_CODE (index_val) == CONST_INT
               && GET_CODE (lo_r) == CONST_INT))
-         {
-           emit_cmp_and_jump_insns (index_val, lo_r, LT, NULL_RTX,
-                                    GET_MODE (index_val), iunsignedp, 0, op1);
-         }
+         emit_cmp_and_jump_insns (index_val, lo_r, LT, NULL_RTX,
+                                  GET_MODE (index_val), iunsignedp, op1);
 
        if (! (GET_CODE (index_val) == CONST_INT
               && GET_CODE (hi_r) == CONST_INT))
-         {
-           emit_cmp_and_jump_insns (index_val, hi_r, GT, NULL_RTX,
-                                    GET_MODE (index_val), iunsignedp, 0, op1);
-         }
+         emit_cmp_and_jump_insns (index_val, hi_r, GT, NULL_RTX,
+                                  GET_MODE (index_val), iunsignedp, op1);
 
        /* Calculate the element number of bit zero in the first word
           of the set.  */
@@ -7458,7 +7172,7 @@ expand_expr (exp, target, tmode, modifier)
       if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
        {
          WITH_CLEANUP_EXPR_RTL (exp)
-           = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier);
+           = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
          expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1));
 
          /* That's it for this cleanup.  */
@@ -7474,7 +7188,7 @@ expand_expr (exp, target, tmode, modifier)
 
        target_temp_slot_level = temp_slot_level;
 
-       op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier);
+       op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
        /* If we're going to use this value, load it up now.  */
        if (! ignore)
          op0 = force_not_mem (op0);
@@ -7510,14 +7224,17 @@ expand_expr (exp, target, tmode, modifier)
        {
          tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
 
-         /* If both input and output are BLKmode, this conversion
-            isn't actually doing anything unless we need to make the
-            alignment stricter.  */
-         if (mode == BLKmode && TYPE_MODE (valtype) == BLKmode
-             && (TYPE_ALIGN (type) <= TYPE_ALIGN (valtype)
-                 || TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT))
-           return expand_expr (TREE_OPERAND (exp, 0), target, tmode,
-                               modifier);
+         /* If both input and output are BLKmode, this conversion isn't doing
+            anything except possibly changing memory attribute.  */
+         if (mode == BLKmode && TYPE_MODE (valtype) == BLKmode)
+           {
+             rtx result = expand_expr (TREE_OPERAND (exp, 0), target, tmode,
+                                       modifier);
+
+             result = copy_rtx (result);
+             set_mem_attributes (result, exp, 0);
+             return result;
+           }
 
          if (target == 0)
            target = assign_temp (type, 0, 1, 1);
@@ -7535,8 +7252,7 @@ expand_expr (exp, target, tmode, modifier)
                               * BITS_PER_UNIT),
                              (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
                         0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
-                        VOIDmode, 0, BITS_PER_UNIT,
-                        int_size_in_bytes (type), 0);
+                        VOIDmode, 0, type, 0);
          else
            abort ();
 
@@ -7547,7 +7263,7 @@ expand_expr (exp, target, tmode, modifier)
       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
        {
          op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
-                            ro_modifier);
+                            modifier);
 
          /* If the signedness of the conversion differs and OP0 is
             a promoted SUBREG, clear that indication since we now
@@ -7581,12 +7297,84 @@ expand_expr (exp, target, tmode, modifier)
                      TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
       return target;
 
+    case VIEW_CONVERT_EXPR:
+      op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
+
+      /* If the input and output modes are both the same, we are done.
+        Otherwise, if neither mode is BLKmode and both are within a word, we
+        can use gen_lowpart.  If neither is true, make sure the operand is
+        in memory and convert the MEM to the new mode.  */
+      if (TYPE_MODE (type) == GET_MODE (op0))
+       ;
+      else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
+              && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD
+              && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD)
+       op0 = gen_lowpart (TYPE_MODE (type), op0);
+      else if (GET_CODE (op0) != MEM)
+       {
+         /* If the operand is not a MEM, force it into memory.  Since we
+            are going to be be changing the mode of the MEM, don't call
+            force_const_mem for constants because we don't allow pool
+            constants to change mode.  */
+         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+
+         if (TREE_ADDRESSABLE (exp))
+           abort ();
+
+         if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
+           target
+             = assign_stack_temp_for_type
+               (TYPE_MODE (inner_type),
+                GET_MODE_SIZE (TYPE_MODE (inner_type)), 0, inner_type);
+
+         emit_move_insn (target, op0);
+         op0 = target;
+       }
+
+      /* At this point, OP0 is in the correct mode.  If the output type is such
+        that the operand is known to be aligned, indicate that it is.
+        Otherwise, we need only be concerned about alignment for non-BLKmode
+        results.  */
+      if (GET_CODE (op0) == MEM)
+       {
+         op0 = copy_rtx (op0);
+
+         if (TYPE_ALIGN_OK (type))
+           set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
+         else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
+                  && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+           {
+             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+             HOST_WIDE_INT temp_size
+               = MAX (int_size_in_bytes (inner_type),
+                      (HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type)));
+             rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
+                                                   temp_size, 0, type);
+             rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
+
+             if (TREE_ADDRESSABLE (exp))
+               abort ();
+
+             if (GET_MODE (op0) == BLKmode)
+               emit_block_move (new_with_op0_mode, op0,
+                                GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
+             else
+               emit_move_insn (new_with_op0_mode, op0);
+
+             op0 = new;
+           }
+      
+         op0 = adjust_address (op0, TYPE_MODE (type), 0);
+       }
+
+      return op0;
+
     case PLUS_EXPR:
       /* We come here from MINUS_EXPR when the second operand is a
          constant.  */
     plus_expr:
       this_optab = ! unsignedp && flag_trapv
-                   && (GET_MODE_CLASS(mode) == MODE_INT)
+                   && (GET_MODE_CLASS (mode) == MODE_INT)
                    ? addv_optab : add_optab;
 
       /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
@@ -7690,8 +7478,8 @@ expand_expr (exp, target, tmode, modifier)
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
 
-      op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, ro_modifier);
-      op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, ro_modifier);
+      op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
+      op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
 
     both_summands:
       /* Make sure any term that's a sum with a constant comes last.  */
@@ -7750,10 +7538,10 @@ expand_expr (exp, target, tmode, modifier)
          && really_constant_p (TREE_OPERAND (exp, 0))
          && really_constant_p (TREE_OPERAND (exp, 1)))
        {
-         rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX,
-                                VOIDmode, ro_modifier);
-         rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
-                                VOIDmode, ro_modifier);
+         rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
+                                modifier);
+         rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
+                                modifier);
 
          /* If the last operand is a CONST_INT, use plus_constant of
             the negated constant.  Else make the MINUS.  */
@@ -8046,7 +7834,7 @@ expand_expr (exp, target, tmode, modifier)
        {
          int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)));
          do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
-                                  unsignedp, mode, NULL_RTX, 0, NULL_RTX,
+                                  unsignedp, mode, NULL_RTX, NULL_RTX,
                                   op0);
        }
       emit_move_insn (target, op1);
@@ -8139,7 +7927,7 @@ expand_expr (exp, target, tmode, modifier)
 
          op1 = gen_label_rtx ();
          emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
-                                  GET_MODE (temp), unsignedp, 0, op1);
+                                  GET_MODE (temp), unsignedp, op1);
          emit_move_insn (temp, const1_rtx);
          emit_label (op1);
          return temp;
@@ -8235,11 +8023,11 @@ expand_expr (exp, target, tmode, modifier)
            if (ignore)
              {
                expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                            ro_modifier);
+                            modifier);
                return const0_rtx;
              }
 
-           op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, ro_modifier);
+           op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
            if (GET_MODE (op0) == mode)
              return op0;
 
@@ -8654,10 +8442,6 @@ expand_expr (exp, target, tmode, modifier)
       return expand_increment (exp, ! ignore, ignore);
 
     case ADDR_EXPR:
-      /* If nonzero, TEMP will be set to the address of something that might
-        be a MEM corresponding to a stack slot.  */
-      temp = 0;
-
       /* Are we taking the address of a nested function?  */
       if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
          && decl_function_context (TREE_OPERAND (exp, 0)) != 0
@@ -8705,65 +8489,97 @@ expand_expr (exp, target, tmode, modifier)
          if (CONSTANT_P (op0))
            op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
                                   op0);
-         else if (GET_CODE (op0) == MEM)
-           {
-             mark_temp_addr_taken (op0);
-             temp = XEXP (op0, 0);
-           }
-
          else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                   || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
                   || GET_CODE (op0) == PARALLEL)
            {
-             /* If this object is in a register, it must be not
-                be BLKmode.  */
-             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-             tree nt = build_qualified_type (inner_type,
-                                             (TYPE_QUALS (inner_type)
-                                              | TYPE_QUAL_CONST));
-             rtx memloc = assign_temp (nt, 1, 1, 1);
-
-             mark_temp_addr_taken (memloc);
-             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,
-                                 int_size_in_bytes (inner_type),
-                                 TYPE_ALIGN (inner_type));
+             /* If the operand is a SAVE_EXPR, we can deal with this by
+                forcing the SAVE_EXPR into memory.  */
+             if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
+               {
+                 put_var_into_stack (TREE_OPERAND (exp, 0));
+                 op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
+               }
              else
-               emit_move_insn (memloc, op0);
-             op0 = memloc;
+               {
+                 /* 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, 
+                                     int_size_in_bytes (inner_type));
+                 else
+                   emit_move_insn (memloc, op0);
+                 
+                 op0 = memloc;
+               }
            }
 
          if (GET_CODE (op0) != MEM)
            abort ();
 
+         mark_temp_addr_taken (op0);
          if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
            {
-             temp = XEXP (op0, 0);
+             op0 = XEXP (op0, 0);
 #ifdef POINTERS_EXTEND_UNSIGNED
-             if (GET_MODE (temp) == Pmode && GET_MODE (temp) != mode
+             if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
                  && mode == ptr_mode)
-               temp = convert_memory_address (ptr_mode, temp);
+               op0 = convert_memory_address (ptr_mode, op0);
 #endif
-             return temp;
+             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
+               = 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)));
+
+             if (TYPE_ALIGN_OK (inner_type))
+               abort ();
+
+             emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)));
+             op0 = new;
            }
 
          op0 = force_operand (XEXP (op0, 0), target);
        }
 
-      if (flag_force_addr && GET_CODE (op0) != REG)
+      if (flag_force_addr
+         && GET_CODE (op0) != REG
+         && modifier != EXPAND_CONST_ADDRESS
+         && modifier != EXPAND_INITIALIZER
+         && modifier != EXPAND_SUM)
        op0 = force_reg (Pmode, op0);
 
       if (GET_CODE (op0) == REG
          && ! REG_USERVAR_P (op0))
        mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
 
-      /* If we might have had a temp slot, add an equivalent address
-        for it.  */
-      if (temp != 0)
-       update_temp_slot_address (temp, op0);
-
 #ifdef POINTERS_EXTEND_UNSIGNED
       if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
          && mode == ptr_mode)
@@ -8943,314 +8759,6 @@ expand_expr (exp, target, tmode, modifier)
   return temp;
 }
 \f
-/* Similar to expand_expr, except that we don't specify a target, target
-   mode, or modifier and we return the alignment of the inner type.  This is
-   used in cases where it is not necessary to align the result to the
-   alignment of its type as long as we know the alignment of the result, for
-   example for comparisons of BLKmode values.  */
-
-static rtx
-expand_expr_unaligned (exp, palign)
-     tree exp;
-     unsigned int *palign;
-{
-  rtx op0;
-  tree type = TREE_TYPE (exp);
-  enum machine_mode mode = TYPE_MODE (type);
-
-  /* Default the alignment we return to that of the type.  */
-  *palign = TYPE_ALIGN (type);
-
-  /* The only cases in which we do anything special is if the resulting mode
-     is BLKmode.  */
-  if (mode != BLKmode)
-    return expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-
-  switch (TREE_CODE (exp))
-    {
-    case CONVERT_EXPR:
-    case NOP_EXPR:
-    case NON_LVALUE_EXPR:
-      /* Conversions between BLKmode values don't change the underlying
-         alignment or value.  */
-      if (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == BLKmode)
-       return expand_expr_unaligned (TREE_OPERAND (exp, 0), palign);
-      break;
-
-    case ARRAY_REF:
-      /* Much of the code for this case is copied directly from expand_expr.
-        We need to duplicate it here because we will do something different
-        in the fall-through case, so we need to handle the same exceptions
-        it does.  */
-      {
-       tree array = TREE_OPERAND (exp, 0);
-       tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-       tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
-       tree index = convert (sizetype, TREE_OPERAND (exp, 1));
-       HOST_WIDE_INT i;
-
-       if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
-         abort ();
-
-       /* Optimize the special-case of a zero lower bound.
-
-          We convert the low_bound to sizetype to avoid some problems
-          with constant folding.  (E.g. suppose the lower bound is 1,
-          and its mode is QI.  Without the conversion,  (ARRAY
-          +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
-          +INDEX), which becomes (ARRAY+255+INDEX).  Oops!)  */
-
-       if (! integer_zerop (low_bound))
-         index = size_diffop (index, convert (sizetype, low_bound));
-
-       /* If this is a constant index into a constant array,
-          just get the value from the array.  Handle both the cases when
-          we have an explicit constructor and when our operand is a variable
-          that was declared const.  */
-
-       if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
-           && host_integerp (index, 0)
-           && 0 > compare_tree_int (index,
-                                    list_length (CONSTRUCTOR_ELTS
-                                                 (TREE_OPERAND (exp, 0)))))
-         {
-           tree elem;
-
-           for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
-                i = tree_low_cst (index, 0);
-                elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
-             ;
-
-           if (elem)
-             return expand_expr_unaligned (fold (TREE_VALUE (elem)), palign);
-         }
-
-       else if (optimize >= 1
-                && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
-                && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
-                && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
-         {
-           if (TREE_CODE (index) == INTEGER_CST)
-             {
-               tree init = DECL_INITIAL (array);
-
-               if (TREE_CODE (init) == CONSTRUCTOR)
-                 {
-                   tree elem;
-
-                   for (elem = CONSTRUCTOR_ELTS (init);
-                        ! tree_int_cst_equal (TREE_PURPOSE (elem), index);
-                        elem = TREE_CHAIN (elem))
-                     ;
-
-                   if (elem)
-                     return expand_expr_unaligned (fold (TREE_VALUE (elem)),
-                                                   palign);
-                 }
-             }
-         }
-      }
-      /* Fall through.  */
-
-    case COMPONENT_REF:
-    case BIT_FIELD_REF:
-    case ARRAY_RANGE_REF:
-      /* If the operand is a CONSTRUCTOR, we can just extract the
-        appropriate field if it is present.  Don't do this if we have
-        already written the data since we want to refer to that copy
-        and varasm.c assumes that's what we'll do.  */
-      if (TREE_CODE (exp) == COMPONENT_REF
-         && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
-         && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
-       {
-         tree elt;
-
-         for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
-              elt = TREE_CHAIN (elt))
-           if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1))
-             /* Note that unlike the case in expand_expr, we know this is
-                BLKmode and hence not an integer.  */
-             return expand_expr_unaligned (TREE_VALUE (elt), palign);
-       }
-
-      {
-       enum machine_mode mode1;
-       HOST_WIDE_INT bitsize, bitpos;
-       tree offset;
-       int volatilep = 0;
-       unsigned int alignment;
-       int unsignedp;
-       tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-                                       &mode1, &unsignedp, &volatilep,
-                                       &alignment);
-
-       /* 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 ();
-
-       op0 = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-
-       /* If this is a constant, put it into a register if it is a
-          legitimate constant and OFFSET is 0 and memory if it isn't.  */
-       if (CONSTANT_P (op0))
-         {
-           enum machine_mode inner_mode = TYPE_MODE (TREE_TYPE (tem));
-
-           if (inner_mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
-               && offset == 0)
-             op0 = force_reg (inner_mode, op0);
-           else
-             op0 = validize_mem (force_const_mem (inner_mode, op0));
-         }
-
-       if (offset != 0)
-         {
-           rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
-
-           /* If this object is in a register, put it into memory.
-              This case can't occur in C, but can in Ada if we have
-              unchecked conversion of an expression from a scalar type to
-              an array or record type.  */
-           if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-               || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
-             {
-               tree nt = build_qualified_type (TREE_TYPE (tem),
-                                               (TYPE_QUALS (TREE_TYPE (tem))
-                                                | TYPE_QUAL_CONST));
-               rtx memloc = assign_temp (nt, 1, 1, 1);
-
-               mark_temp_addr_taken (memloc);
-               emit_move_insn (memloc, op0);
-               op0 = memloc;
-             }
-
-           if (GET_CODE (op0) != MEM)
-             abort ();
-
-           if (GET_MODE (offset_rtx) != ptr_mode)
-             offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
-
-#ifdef POINTERS_EXTEND_UNSIGNED
-           if (GET_MODE (offset_rtx) != Pmode)
-             offset_rtx = convert_memory_address (Pmode, offset_rtx);
-#endif
-
-           op0 = offset_address (op0, offset_rtx,
-                                 highest_pow2_factor (offset));
-         }
-
-       /* Don't forget about volatility even if this is a bitfield.  */
-       if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
-         {
-           op0 = copy_rtx (op0);
-           MEM_VOLATILE_P (op0) = 1;
-         }
-
-       /* Check the access.  */
-       if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
-         {
-           rtx to;
-           int size;
-
-           to = plus_constant (XEXP (op0, 0), (bitpos / BITS_PER_UNIT));
-           size = (bitpos % BITS_PER_UNIT) + bitsize + BITS_PER_UNIT - 1;
-
-           /* Check the access right of the pointer.  */
-           in_check_memory_usage = 1;
-           if (size > BITS_PER_UNIT)
-             emit_library_call (chkr_check_addr_libfunc,
-                                LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
-                                to, ptr_mode, GEN_INT (size / BITS_PER_UNIT),
-                                TYPE_MODE (sizetype),
-                                GEN_INT (MEMORY_USE_RO),
-                                TYPE_MODE (integer_type_node));
-           in_check_memory_usage = 0;
-         }
-
-       /* In cases where an aligned union has an unaligned object
-          as a field, we might be extracting a BLKmode value from
-          an integer-mode (e.g., SImode) object.  Handle this case
-          by doing the extract into an object as wide as the field
-          (which we know to be the width of a basic mode), then
-          storing into memory, and changing the mode to BLKmode.
-          If we ultimately want the address (EXPAND_CONST_ADDRESS or
-          EXPAND_INITIALIZER), then we must not copy to a temporary.  */
-       if (mode1 == VOIDmode
-           || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-           || (SLOW_UNALIGNED_ACCESS (mode1, alignment)
-               && (TYPE_ALIGN (type) > alignment
-                   || bitpos % TYPE_ALIGN (type) != 0)))
-         {
-           enum machine_mode ext_mode = mode_for_size (bitsize, MODE_INT, 1);
-
-           if (ext_mode == BLKmode)
-             {
-               /* In this case, BITPOS must start at a byte boundary.  */
-               if (GET_CODE (op0) != MEM
-                   || bitpos % BITS_PER_UNIT != 0)
-                 abort ();
-
-               op0 = adjust_address (op0, VOIDmode, bitpos / BITS_PER_UNIT);
-             }
-           else
-             {
-               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
-                                               TYPE_QUAL_CONST);
-               rtx new = assign_temp (nt, 0, 1, 1);
-
-               op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
-                                        unsignedp, NULL_RTX, ext_mode,
-                                        ext_mode, alignment,
-                                        int_size_in_bytes (TREE_TYPE (tem)));
-
-               /* If the result is a record type and BITSIZE is narrower than
-                  the mode of OP0, an integral mode, and this is a big endian
-                  machine, we must put the field into the high-order bits.  */
-               if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
-                   && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-                   && bitsize < GET_MODE_BITSIZE (GET_MODE (op0)))
-                 op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
-                                     size_int (GET_MODE_BITSIZE
-                                               (GET_MODE (op0))
-                                               - bitsize),
-                                     op0, 1);
-
-               emit_move_insn (new, op0);
-               op0 = copy_rtx (new);
-               PUT_MODE (op0, BLKmode);
-             }
-         }
-       else
-         /* Get a reference to just this component.  */
-         op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-
-       set_mem_attributes (op0, exp, 0);
-
-       /* Adjust the alignment in case the bit position is not
-          a multiple of the alignment of the inner object.  */
-       while (bitpos % alignment != 0)
-         alignment >>= 1;
-
-       if (GET_CODE (XEXP (op0, 0)) == REG)
-         mark_reg_pointer (XEXP (op0, 0), alignment);
-
-       MEM_IN_STRUCT_P (op0) = 1;
-       MEM_VOLATILE_P (op0) |= volatilep;
-
-       *palign = alignment;
-       return op0;
-      }
-
-    default:
-      break;
-
-    }
-
-  return expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-}
-\f
 /* Return the tree node if a ARG corresponds to a string constant or zero
    if it doesn't.  If we return non-zero, set *PTR_OFFSET to the offset
    in bytes within the string that ARG is accessing.  The type of the
@@ -9337,7 +8845,7 @@ expand_increment (exp, post, ignore)
      and insns were generated in computing it.  */
 
   temp = get_last_insn ();
-  op0 = expand_expr (incremented, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_RW);
+  op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
 
   /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
      in place but instead must do sign- or zero-extension during assignment,
@@ -9368,8 +8876,7 @@ expand_increment (exp, post, ignore)
 
   op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
                 && temp != get_last_insn ());
-  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
-                    EXPAND_MEMORY_USE_BAD);
+  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
 
   /* Decide whether incrementing or decrementing.  */
   if (TREE_CODE (exp) == POSTDECREMENT_EXPR
@@ -9385,7 +8892,7 @@ expand_increment (exp, post, ignore)
     }
 
   if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
-     this_optab = this_optab == add_optab ? addv_optab : subv_optab;
+    this_optab = this_optab == add_optab ? addv_optab : subv_optab;
 
   /* For a preincrement, see if we can do this with a single instruction.  */
   if (!post)
@@ -9490,9 +8997,9 @@ expand_increment (exp, post, ignore)
     temp = copy_rtx (value = op0);
 
   /* Increment however we can.  */
-  op1 = expand_binop (mode, this_optab, value, op1,
-                     current_function_check_memory_usage ? NULL_RTX : op0,
+  op1 = expand_binop (mode, this_optab, value, op1, op0,
                      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
+
   /* Make sure the value is stored into OP0.  */
   if (op1 != op0)
     emit_move_insn (op0, op1);
@@ -9739,12 +9246,11 @@ do_jump (exp, if_false_label, if_true_label)
        tree type;
        tree offset;
        int volatilep = 0;
-       unsigned int alignment;
 
        /* Get description of this reference.  We don't actually care
           about the underlying object here.  */
        get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
-                            &unsignedp, &volatilep, &alignment);
+                            &unsignedp, &volatilep);
 
        type = type_for_size (bitsize, unsignedp);
        if (! SLOW_BYTE_ACCESS
@@ -10046,7 +9552,7 @@ do_jump (exp, if_false_label, if_true_label)
       else if (GET_MODE (temp) != VOIDmode)
        do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
                                 NE, TREE_UNSIGNED (TREE_TYPE (exp)),
-                                GET_MODE (temp), NULL_RTX, 0,
+                                GET_MODE (temp), NULL_RTX,
                                 if_false_label, if_true_label);
       else
        abort ();
@@ -10121,12 +9627,12 @@ do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true
 
       /* All but high-order word must be compared as unsigned.  */
       do_compare_rtx_and_jump (op0_word, op1_word, GT,
-                              (unsignedp || i > 0), word_mode, NULL_RTX, 0,
+                              (unsignedp || i > 0), word_mode, NULL_RTX,
                               NULL_RTX, if_true_label);
 
       /* Consider lower words only if these are equal.  */
       do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
-                              NULL_RTX, 0, NULL_RTX, if_false_label);
+                              NULL_RTX, NULL_RTX, if_false_label);
     }
 
   if (if_false_label)
@@ -10157,8 +9663,7 @@ do_jump_by_parts_equality (exp, if_false_label, if_true_label)
     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
                             operand_subword_force (op1, i, mode),
                             EQ, TREE_UNSIGNED (TREE_TYPE (exp)),
-                            word_mode, NULL_RTX, 0, if_false_label,
-                            NULL_RTX);
+                            word_mode, NULL_RTX, if_false_label, NULL_RTX);
 
   if (if_true_label)
     emit_jump (if_true_label);
@@ -10195,7 +9700,7 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
   if (part != 0)
     {
       do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
-                              NULL_RTX, 0, if_false_label, if_true_label);
+                              NULL_RTX, if_false_label, if_true_label);
 
       return;
     }
@@ -10206,7 +9711,7 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
 
   for (i = 0; i < nwords; i++)
     do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
-                            const0_rtx, EQ, 1, word_mode, NULL_RTX, 0,
+                            const0_rtx, EQ, 1, word_mode, NULL_RTX,
                             if_false_label, NULL_RTX);
 
   if (if_true_label)
@@ -10225,19 +9730,15 @@ do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
    things pushed on the stack that aren't yet used.
 
    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
-   compared.
-
-   If ALIGN is non-zero, it is the alignment of this type; if zero, the
-   size of MODE should be used.  */
+   compared.  */
 
 rtx
-compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
+compare_from_rtx (op0, op1, code, unsignedp, mode, size)
      rtx op0, op1;
      enum rtx_code code;
      int unsignedp;
      enum machine_mode mode;
      rtx size;
-     unsigned int align;
 {
   rtx tem;
 
@@ -10286,7 +9787,7 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
     }
 #endif
 
-  emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align);
+  emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
 
   return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
 }
@@ -10295,20 +9796,16 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
    The decision as to signed or unsigned comparison must be made by the caller.
 
    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
-   compared.
-
-   If ALIGN is non-zero, it is the alignment of this type; if zero, the
-   size of MODE should be used.  */
+   compared.  */
 
 void
-do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size, align,
+do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size,
                         if_false_label, if_true_label)
      rtx op0, op1;
      enum rtx_code code;
      int unsignedp;
      enum machine_mode mode;
      rtx size;
-     unsigned int align;
      rtx if_false_label, if_true_label;
 {
   rtx tem;
@@ -10386,7 +9883,7 @@ do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size, align,
       if_true_label = gen_label_rtx ();
     }
 
-  emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, align,
+  emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
                           if_true_label);
 
   if (if_false_label)
@@ -10412,7 +9909,6 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
      enum rtx_code signed_code, unsigned_code;
      rtx if_false_label, if_true_label;
 {
-  unsigned int align0, align1;
   rtx op0, op1;
   tree type;
   enum machine_mode mode;
@@ -10420,11 +9916,11 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
   enum rtx_code code;
 
   /* Don't crash if the comparison was erroneous.  */
-  op0 = expand_expr_unaligned (TREE_OPERAND (exp, 0), &align0);
+  op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
   if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
     return;
 
-  op1 = expand_expr_unaligned (TREE_OPERAND (exp, 1), &align1);
+  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
   if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
     return;
 
@@ -10476,7 +9972,6 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
                           ((mode == BLKmode)
                            ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
-                          MIN (align0, align1),
                           if_false_label, if_true_label);
 }
 \f
@@ -10755,12 +10250,20 @@ do_store_flag (exp, target, mode, only_cheap)
 
   emit_move_insn (target, invert ? const0_rtx : const1_rtx);
   result = compare_from_rtx (op0, op1, code, unsignedp,
-                            operand_mode, NULL_RTX, 0);
+                            operand_mode, NULL_RTX);
   if (GET_CODE (result) == CONST_INT)
     return (((result == const0_rtx && ! invert)
             || (result != const0_rtx && invert))
            ? const0_rtx : const1_rtx);
 
+  /* The code of RESULT may not match CODE if compare_from_rtx
+     decided to swap its operands and reverse the original code.
+
+     We know that compare_from_rtx returns either a CONST_INT or
+     a new comparison code, so it is safe to just extract the
+     code from RESULT.  */
+  code = GET_CODE (result);
+
   label = gen_label_rtx ();
   if (bcc_gen_fctn[(int) code] == 0)
     abort ();
@@ -10822,7 +10325,7 @@ try_casesi (index_type, index_expr, minval, range,
       minval = integer_zero_node;
       index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
       emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
-                              omode, 1, 0, default_label);
+                              omode, 1, default_label);
       /* Now we can safely truncate.  */
       index = convert_to_mode (index_mode, index, 0);
     }
@@ -10902,7 +10405,7 @@ do_tablejump (index, mode, range, table_label, default_label)
      the maximum value of the range.  */
 
   emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
-                          0, default_label);
+                          default_label);
 
   /* If index is in range, it must fit in Pmode.
      Convert to Pmode so we can index with it.  */