re PR middle-end/5877 (negative offset to array index leads to inefficient code)
[gcc.git] / gcc / expr.c
index af36b3b5820fff038176f5c9edd0d52b42c5b6db..ac756432f20be533d25cbf55f0973ca3fcdfc8a4 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,
 /* 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.
 
 
 This file is part of GCC.
 
@@ -81,11 +81,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    the same indirect address eventually.  */
 int cse_not_expected;
 
    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;
 
 /* Chain of pending expressions for PLACEHOLDER_EXPR to replace.  */
 static tree placeholder_list = 0;
 
@@ -124,8 +119,6 @@ struct store_by_pieces
 
 extern struct obstack permanent_obstack;
 
 
 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,
 static rtx enqueue_insn                PARAMS ((rtx, rtx));
 static unsigned HOST_WIDE_INT move_by_pieces_ninsns
                                PARAMS ((unsigned HOST_WIDE_INT,
@@ -152,8 +145,6 @@ static rtx store_field              PARAMS ((rtx, HOST_WIDE_INT,
                                         HOST_WIDE_INT, enum machine_mode,
                                         tree, enum machine_mode, int, tree,
                                         int));
                                         HOST_WIDE_INT, enum machine_mode,
                                         tree, enum machine_mode, int, tree,
                                         int));
-static enum memory_use_mode
-  get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
 static rtx var_rtx             PARAMS ((tree));
 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
 static rtx expand_increment    PARAMS ((tree, int, int));
 static rtx var_rtx             PARAMS ((tree));
 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
 static rtx expand_increment    PARAMS ((tree, int, int));
@@ -1061,6 +1052,9 @@ convert_move (to, from, unsignedp)
       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
          != CODE_FOR_nothing)
        {
       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;
        }
          emit_unop_insn (code, to, from, equiv_code);
          return;
        }
@@ -1581,9 +1575,11 @@ move_by_pieces_1 (genfun, mode, data)
        from1 = adjust_address (data->from, mode, data->offset);
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
        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)
       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));
 
       if (data->to)
        emit_insn ((*genfun) (to1, from1));
@@ -1877,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
   /* 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;
     {
       emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
       return;
@@ -1886,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).  */
   /* 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;
     {
       rtx tem = operand_subword (x, 0, 1, BLKmode);
       rtx shift;
@@ -1933,7 +1932,7 @@ 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.  */
 /* 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.  */
-/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatent assumption that
+/* ??? 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
    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
@@ -2169,17 +2168,28 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
       preserve_temp_slots (tgtblk);
     }
 
       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)
   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.  */
 
   /* 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));
 
     big_endian_correction
       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
 
@@ -2783,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);
   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 ();
 
   if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
     abort ();
@@ -2809,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
       /* 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;
        {
          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.  */
 
          /* Do not use anti_adjust_stack, since we don't want to update
             stack_pointer_delta.  */
@@ -2824,12 +2834,13 @@ emit_move_insn_1 (x, y)
 #endif
                               stack_pointer_rtx,
                               GEN_INT
 #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);
          if (temp != stack_pointer_rtx)
            emit_move_insn (stack_pointer_rtx, temp);
+
 #ifdef STACK_GROWS_DOWNWARD
          offset1 = 0;
          offset2 = GET_MODE_SIZE (submode);
 #ifdef STACK_GROWS_DOWNWARD
          offset1 = 0;
          offset2 = GET_MODE_SIZE (submode);
@@ -2838,6 +2849,7 @@ emit_move_insn_1 (x, y)
          offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
                     + GET_MODE_SIZE (submode));
 #endif
          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,
          emit_move_insn (change_address (x, submode,
                                          gen_rtx_PLUS (Pmode,
                                                        stack_pointer_rtx,
@@ -2893,8 +2905,10 @@ emit_move_insn_1 (x, y)
          if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
              && (reload_in_progress | reload_completed) == 0)
            {
          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)
                {
 
              if (packed_dest_p || packed_src_p)
                {
@@ -2916,12 +2930,14 @@ emit_move_insn_1 (x, y)
                      if (packed_dest_p)
                        {
                          rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
                      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 (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);
                        }
                          emit_move_insn_1 (mem, sreg);
                          return emit_move_insn_1 (x, cmem);
                        }
@@ -2942,9 +2958,7 @@ emit_move_insn_1 (x, y)
              && ! (reload_in_progress || reload_completed)
              && (GET_CODE (realpart_x) == SUBREG
                  || GET_CODE (imagpart_x) == SUBREG))
              && ! (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));
 
          emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
                     (realpart_x, realpart_y));
@@ -2963,6 +2977,7 @@ emit_move_insn_1 (x, y)
       rtx last_insn = 0;
       rtx seq, inner;
       int need_clobber;
       rtx last_insn = 0;
       rtx seq, inner;
       int need_clobber;
+      int i;
 
 #ifdef PUSH_ROUNDING
 
 
 #ifdef PUSH_ROUNDING
 
@@ -2983,19 +2998,20 @@ emit_move_insn_1 (x, y)
 #endif
                               stack_pointer_rtx,
                               GEN_INT
 #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));
           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, 
          /* 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))));
          else if (code == POST_DEC)
            temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 
                                GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
@@ -3054,9 +3070,7 @@ emit_move_insn_1 (x, y)
       if (x != y
          && ! (reload_in_progress || reload_completed)
          && need_clobber != 0)
       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);
 
 
       emit_insn (seq);
 
@@ -3124,26 +3138,6 @@ push_block (size, extra, below)
   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
 }
 
   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.  */
 #ifdef PUSH_ROUNDING
 
 /* Emit single push insn.  */
@@ -3167,7 +3161,7 @@ emit_single_push_insn (mode, x, type)
   if (icode != CODE_FOR_nothing)
     {
       if (((pred = insn_data[(int) icode].operand[0].predicate)
   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;
        x = force_reg (mode, x);
       emit_insn (GEN_FCN (icode) (x));
       return;
@@ -3178,7 +3172,7 @@ emit_single_push_insn (mode, x, type)
     {
 #ifdef STACK_GROWS_DOWNWARD
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
     {
 #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));
 #else
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
                                GEN_INT (rounded_size));
@@ -3325,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);
            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  */
        }
       else
 #endif /* PUSH_ROUNDING  */
@@ -3385,26 +3357,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                                                                args_addr,
                                                                args_so_far),
                                                  skip));
                                                                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)
          target = gen_rtx_MEM (BLKmode, temp);
 
          if (type != 0)
@@ -3605,27 +3557,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
          emit_move_insn (dest, x);
        }
 
          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:
     }
 
  ret:
@@ -3724,11 +3655,11 @@ expand_assignment (to, from, want_value, suggest_reg)
       if (mode1 == VOIDmode && want_value)
        tem = stabilize_reference (tem);
 
       if (mode1 == VOIDmode && want_value)
        tem = stabilize_reference (tem);
 
-      orig_to_rtx = 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)
        {
       if (offset != 0)
        {
-         rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+         rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
 
          if (GET_CODE (to_rtx) != MEM)
            abort ();
 
          if (GET_CODE (to_rtx) != MEM)
            abort ();
@@ -3751,15 +3682,7 @@ expand_assignment (to, from, want_value, suggest_reg)
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
            {
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
            {
-             rtx temp
-               = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
-
-             if (GET_CODE (XEXP (temp, 0)) == REG)
-               to_rtx = temp;
-             else
-               to_rtx = (replace_equiv_address
-                         (to_rtx, force_reg (GET_MODE (XEXP (temp, 0)),
-                                             XEXP (temp, 0))));
+             to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
              bitpos = 0;
            }
 
              bitpos = 0;
            }
 
@@ -3805,43 +3728,13 @@ expand_assignment (to, from, want_value, suggest_reg)
          RTX_UNCHANGING_P (to_rtx) = 1;
        }
 
          RTX_UNCHANGING_P (to_rtx) = 1;
        }
 
-      if (! can_address_p (to))
+      if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
        {
          if (to_rtx == orig_to_rtx)
            to_rtx = copy_rtx (to_rtx);
          MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
        }
 
        {
          if (to_rtx == orig_to_rtx)
            to_rtx = copy_rtx (to_rtx);
          MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
        }
 
-      /* Check the access.  */
-      if (current_function_check_memory_usage && GET_CODE (to_rtx) == MEM)
-       {
-         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;
-       }
-
       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
                            (want_value
                             /* Spurious cast for HPUX compiler.  */
       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
                            (want_value
                             /* Spurious cast for HPUX compiler.  */
@@ -3883,7 +3776,7 @@ expand_assignment (to, from, want_value, suggest_reg)
       push_temp_slots ();
       value = expand_expr (from, NULL_RTX, VOIDmode, 0);
       if (to_rtx == 0)
       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.  */
 
       /* Handle calls that return values in multiple non-contiguous locations.
         The Irix 6 ABI has examples of this.  */
@@ -3910,7 +3803,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)
      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
 
   /* Don't move directly into a return register.  */
   if (TREE_CODE (to) == RESULT_DECL
@@ -3943,17 +3836,7 @@ expand_assignment (to, from, want_value, suggest_reg)
 
       push_temp_slots ();
       size = expr_size (from);
 
       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,
 
 #ifdef TARGET_MEM_FUNCTIONS
       emit_library_call (memmove_libfunc, LCT_NORMAL,
@@ -4106,6 +3989,8 @@ store_expr (exp, target, want_value)
        and then convert to the wider mode.  Our value is the computed
        expression.  */
     {
        and then convert to the wider mode.  Our value is the computed
        expression.  */
     {
+      rtx inner_target = 0;
+
       /* If we don't want a value, we can do the conversion inside EXP,
         which will often result in some optimizations.  Do the conversion
         in two steps: first change the signedness, if needed, then
       /* If we don't want a value, we can do the conversion inside EXP,
         which will often result in some optimizations.  Do the conversion
         in two steps: first change the signedness, if needed, then
@@ -4126,9 +4011,11 @@ store_expr (exp, target, want_value)
          exp = convert (type_for_mode (GET_MODE (SUBREG_REG (target)),
                                        SUBREG_PROMOTED_UNSIGNED_P (target)),
                         exp);
          exp = convert (type_for_mode (GET_MODE (SUBREG_REG (target)),
                                        SUBREG_PROMOTED_UNSIGNED_P (target)),
                         exp);
+
+         inner_target = SUBREG_REG (target);
        }
 
        }
 
-      temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+      temp = expand_expr (exp, inner_target, VOIDmode, 0);
 
       /* If TEMP is a volatile MEM and we want a result value, make
         the access now so it gets done only once.  Likewise if
 
       /* If TEMP is a volatile MEM and we want a result value, make
         the access now so it gets done only once.  Likewise if
@@ -4156,13 +4043,19 @@ store_expr (exp, target, want_value)
         target.  Otherwise, the caller might get confused by a result whose
         mode is larger than expected.  */
 
         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_SET (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;
        }
 
       return want_value ? temp : NULL_RTX;
@@ -4195,28 +4088,9 @@ store_expr (exp, target, want_value)
     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
                          temp, TREE_UNSIGNED (TREE_TYPE (exp)));
 
     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.
   /* 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
      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
@@ -4305,19 +4179,7 @@ store_expr (exp, target, want_value)
                }
 
              if (size != const0_rtx)
                }
 
              if (size != const0_rtx)
-               {
-                 /* 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,
-                                      XEXP (target, 0), Pmode,
-                                      size, TYPE_MODE (sizetype),
-                                      GEN_INT (MEMORY_USE_WO),
-                                      TYPE_MODE (integer_type_node));
-                 in_check_memory_usage = 0;
-                 clear_storage (target, size);
-               }
+               clear_storage (target, size);
 
              if (label)
                emit_label (label);
 
              if (label)
                emit_label (label);
@@ -4378,6 +4240,14 @@ is_zeros_p (exp)
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
 
     case REAL_CST:
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
 
+    case VECTOR_CST:
+      for (elt = TREE_VECTOR_CST_ELTS (exp); elt;
+          elt = TREE_CHAIN (elt))
+       if (!is_zeros_p (TREE_VALUE (elt)))
+         return 0;
+
+      return 1;
+
     case CONSTRUCTOR:
       if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
        return CONSTRUCTOR_ELTS (exp) == NULL_TREE;
     case CONSTRUCTOR:
       if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
        return CONSTRUCTOR_ELTS (exp) == NULL_TREE;
@@ -4662,20 +4532,34 @@ store_constructor (exp, target, cleared, size)
                                   get_alias_set (TREE_TYPE (field)));
        }
     }
                                   get_alias_set (TREE_TYPE (field)));
        }
     }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
+  else if (TREE_CODE (type) == ARRAY_TYPE
+          || TREE_CODE (type) == VECTOR_TYPE)
     {
       tree elt;
       int i;
       int need_to_clear;
       tree domain = TYPE_DOMAIN (type);
       tree elttype = TREE_TYPE (type);
     {
       tree elt;
       int i;
       int need_to_clear;
       tree domain = TYPE_DOMAIN (type);
       tree elttype = TREE_TYPE (type);
-      int const_bounds_p = (TYPE_MIN_VALUE (domain)
-                           && TYPE_MAX_VALUE (domain)
-                           && host_integerp (TYPE_MIN_VALUE (domain), 0)
-                           && host_integerp (TYPE_MAX_VALUE (domain), 0));
+      int const_bounds_p;
       HOST_WIDE_INT minelt = 0;
       HOST_WIDE_INT maxelt = 0;
 
       HOST_WIDE_INT minelt = 0;
       HOST_WIDE_INT maxelt = 0;
 
+      /* Vectors are like arrays, but the domain is stored via an array
+        type indirectly.  */
+      if (TREE_CODE (type) == VECTOR_TYPE)
+       {
+         /* Note that although TYPE_DEBUG_REPRESENTATION_TYPE uses
+            the same field as TYPE_DOMAIN, we are not guaranteed that
+            it always will.  */
+         domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+         domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
+       }
+
+      const_bounds_p = (TYPE_MIN_VALUE (domain)
+                       && TYPE_MAX_VALUE (domain)
+                       && host_integerp (TYPE_MIN_VALUE (domain), 0)
+                       && host_integerp (TYPE_MAX_VALUE (domain), 0));
+
       /* If we have constant bounds for the range of the type, get them.  */
       if (const_bounds_p)
        {
       /* If we have constant bounds for the range of the type, get them.  */
       if (const_bounds_p)
        {
@@ -4736,7 +4620,12 @@ store_constructor (exp, target, cleared, size)
       if (need_to_clear && size > 0)
        {
          if (! cleared)
       if (need_to_clear && size > 0)
        {
          if (! cleared)
-           clear_storage (target, GEN_INT (size));
+           {
+             if (REG_P (target))
+               emit_move_insn (target,  CONST0_RTX (GET_MODE (target)));
+             else
+               clear_storage (target, GEN_INT (size));
+           }
          cleared = 1;
        }
       else if (REG_P (target))
          cleared = 1;
        }
       else if (REG_P (target))
@@ -4799,6 +4688,7 @@ store_constructor (exp, target, cleared, size)
 
                      if (GET_CODE (target) == MEM
                          && !MEM_KEEP_ALIAS_SET_P (target)
 
                      if (GET_CODE (target) == MEM
                          && !MEM_KEEP_ALIAS_SET_P (target)
+                         && TREE_CODE (type) == ARRAY_TYPE
                          && TYPE_NONALIASED_COMPONENT (type))
                        {
                          target = copy_rtx (target);
                          && TYPE_NONALIASED_COMPONENT (type))
                        {
                          target = copy_rtx (target);
@@ -4896,6 +4786,7 @@ store_constructor (exp, target, cleared, size)
                bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
 
              if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
                bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
 
              if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
+                 && TREE_CODE (type) == ARRAY_TYPE
                  && TYPE_NONALIASED_COMPONENT (type))
                {
                  target = copy_rtx (target);
                  && TYPE_NONALIASED_COMPONENT (type))
                {
                  target = copy_rtx (target);
@@ -5152,9 +5043,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
        = assign_temp
          (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
           0, 1, 1);
        = assign_temp
          (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);
 
       if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
@@ -5206,7 +5095,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
         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
         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))
          && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
                             size_int (GET_MODE_BITSIZE (GET_MODE (temp))
@@ -5250,18 +5139,16 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
              tree count;
              enum machine_mode tmode;
 
              tree count;
              enum machine_mode tmode;
 
-             if (unsignedp)
-               return expand_and (temp,
-                                  GEN_INT
-                                  (trunc_int_for_mode
-                                   (width_mask,
-                                    GET_MODE (temp) == VOIDmode
-                                    ? value_mode
-                                    : GET_MODE (temp))), NULL_RTX);
-
              tmode = GET_MODE (temp);
              if (tmode == VOIDmode)
                tmode = value_mode;
              tmode = GET_MODE (temp);
              if (tmode == VOIDmode)
                tmode = value_mode;
+
+             if (unsignedp)
+               return expand_and (tmode, temp,
+                                  GEN_INT (trunc_int_for_mode (width_mask,
+                                                               tmode)),
+                                  NULL_RTX);
+
              count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
              count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
@@ -5508,37 +5395,6 @@ handled_component_p (t)
       return 0;
     }
 }
       return 0;
     }
 }
-
-/* Subroutine of expand_exp: compute memory_usage from modifier.  */
-
-static enum memory_use_mode
-get_memory_usage_from_modifier (modifier)
-     enum expand_modifier modifier;
-{
-  switch (modifier)
-    {
-    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:
-    default:
-      abort ();
-    }
-}
 \f
 /* Given an rtx VALUE that may contain additions and multiplications, return
    an equivalent value that just refers to a register, memory, or constant.
 \f
 /* Given an rtx VALUE that may contain additions and multiplications, return
    an equivalent value that just refers to a register, memory, or constant.
@@ -5560,8 +5416,7 @@ force_operand (value, target)
   rtx subtarget = get_subtarget (target);
 
   /* Check for a PIC address load.  */
   rtx subtarget = get_subtarget (target);
 
   /* Check for a PIC address load.  */
-  if (flag_pic
-      && (GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
+  if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
       && XEXP (value, 0) == pic_offset_table_rtx
       && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
          || GET_CODE (XEXP (value, 1)) == LABEL_REF
       && XEXP (value, 0) == pic_offset_table_rtx
       && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
          || GET_CODE (XEXP (value, 1)) == LABEL_REF
@@ -5879,7 +5734,7 @@ safe_from_p (x, exp, top_p)
         are memory and they conflict.  */
       return ! (rtx_equal_p (x, exp_rtl)
                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
         are memory and they conflict.  */
       return ! (rtx_equal_p (x, exp_rtl)
                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
-                   && true_dependence (exp_rtl, GET_MODE (x), x,
+                   && true_dependence (exp_rtl, VOIDmode, x,
                                        rtx_addr_varies_p)));
     }
 
                                        rtx_addr_varies_p)));
     }
 
@@ -5972,19 +5827,25 @@ highest_pow2_factor (exp)
   switch (TREE_CODE (exp))
     {
     case INTEGER_CST:
   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, 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))
+      /* We can find the lowest bit that's a one.  If the low
+        HOST_BITS_PER_WIDE_INT bits are 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))
+       return BIGGEST_ALIGNMENT;
+      else
        {
        {
-         c0 = tree_low_cst (exp, 0);
-         c0 = c0 < 0 ? - c0 : c0;
-         return c0 != 0 ? c0 & -c0 : 1;
+         /* Note: tree_low_cst is intentionally not used here,
+            we don't care about the upper bits.  */
+         c0 = TREE_INT_CST_LOW (exp);
+         c0 &= -c0;
+         return c0 ? c0 : BIGGEST_ALIGNMENT;
        }
       break;
 
        }
       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);
       c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
       c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
       return MIN (c0, c1);
@@ -5996,14 +5857,22 @@ highest_pow2_factor (exp)
 
     case ROUND_DIV_EXPR:  case TRUNC_DIV_EXPR:  case FLOOR_DIV_EXPR:
     case CEIL_DIV_EXPR:
 
     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 NON_LVALUE_EXPR:  case NOP_EXPR:  case CONVERT_EXPR:
-    case COMPOUND_EXPR:    case SAVE_EXPR: case WITH_RECORD_EXPR:
+    case SAVE_EXPR: case WITH_RECORD_EXPR:
       return highest_pow2_factor (TREE_OPERAND (exp, 0));
 
       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));
     case COND_EXPR:
       c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
       c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
@@ -6133,8 +6002,6 @@ expand_expr (exp, target, tmode, modifier)
   rtx subtarget, original_target;
   int ignore;
   tree context;
   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)
 
   /* Handle ERROR_MARK before anybody tries to access its type.  */
   if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
@@ -6155,13 +6022,6 @@ expand_expr (exp, target, tmode, modifier)
                 || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
                && TREE_CODE (type) == VOID_TYPE));
 
                 || 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
   /* 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
@@ -6180,7 +6040,7 @@ expand_expr (exp, target, tmode, modifier)
          && mode != VOIDmode && mode != BLKmode
          && modifier != EXPAND_CONST_ADDRESS)
        {
          && 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;
          if (GET_CODE (temp) == MEM)
            temp = copy_to_reg (temp);
          return const0_rtx;
@@ -6188,34 +6048,30 @@ expand_expr (exp, target, tmode, modifier)
 
       if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF
          || code == INDIRECT_REF || code == BUFFER_REF)
 
       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)
        {
       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 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)
        {
       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;
        }
          return const0_rtx;
        }
-      ;
+
       target = 0;
     }
 
       target = 0;
     }
 
@@ -6333,34 +6189,6 @@ expand_expr (exp, target, tmode, modifier)
            }
        }
 
            }
        }
 
-      /* 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);
-
-         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;
-       }
-
       /* ... fall through ...  */
 
     case FUNCTION_DECL:
       /* ... fall through ...  */
 
     case FUNCTION_DECL:
@@ -6452,7 +6280,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
         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.  */
        {
          /* Get the signedness used for this variable.  Ensure we get the
             same mode we got when the variable was declared.  */
@@ -6462,7 +6290,7 @@ expand_expr (exp, target, tmode, modifier)
 
          temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
          SUBREG_PROMOTED_VAR_P (temp) = 1;
 
          temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
          SUBREG_PROMOTED_VAR_P (temp) = 1;
-         SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+         SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
          return temp;
        }
 
          return temp;
        }
 
@@ -6473,8 +6301,7 @@ expand_expr (exp, target, tmode, modifier)
                                 TREE_INT_CST_HIGH (exp), mode);
 
     case CONST_DECL:
                                 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
 
     case REAL_CST:
       /* If optimized, generate immediate CONST_DOUBLE
@@ -6583,12 +6410,11 @@ expand_expr (exp, target, tmode, modifier)
            {
              temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
              SUBREG_PROMOTED_VAR_P (temp) = 1;
            {
              temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
              SUBREG_PROMOTED_VAR_P (temp) = 1;
-             SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+             SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
            }
 
          if (temp == const0_rtx)
            }
 
          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);
 
          else
            store_expr (TREE_OPERAND (exp, 0), temp, 0);
 
@@ -6606,7 +6432,7 @@ expand_expr (exp, target, tmode, modifier)
          promote_mode (type, mode, &unsignedp, 0);
          temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
          SUBREG_PROMOTED_VAR_P (temp) = 1;
          promote_mode (type, mode, &unsignedp, 0);
          temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
          SUBREG_PROMOTED_VAR_P (temp) = 1;
-         SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+         SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
          return temp;
        }
 
          return temp;
        }
 
@@ -6616,7 +6442,8 @@ expand_expr (exp, target, tmode, modifier)
       {
        rtx temp;
        temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
       {
        rtx temp;
        temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-       TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
+       TREE_OPERAND (exp, 0)
+         = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
        return temp;
       }
 
        return temp;
       }
 
@@ -6630,7 +6457,7 @@ expand_expr (exp, target, tmode, modifier)
          abort ();
 
        placeholder_list = TREE_CHAIN (placeholder_expr);
          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;
       }
        placeholder_list = old_list;
        return temp;
       }
@@ -6643,8 +6470,8 @@ expand_expr (exp, target, tmode, modifier)
         and pop the list.  */
       placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
                                    placeholder_list);
         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;
 
       placeholder_list = TREE_CHAIN (placeholder_list);
       return target;
 
@@ -6662,7 +6489,7 @@ expand_expr (exp, target, tmode, modifier)
 
     case LABELED_BLOCK_EXPR:
       if (LABELED_BLOCK_BODY (exp))
 
     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)));
       /* Should perhaps use expand_label, but this is simpler and safer.  */
       do_pending_stack_adjust ();
       emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
@@ -6677,7 +6504,7 @@ expand_expr (exp, target, tmode, modifier)
     case LOOP_EXPR:
       push_temp_slots ();
       expand_start_loop (1);
     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 ();
 
       expand_end_loop ();
       pop_temp_slots ();
 
@@ -6709,7 +6536,7 @@ expand_expr (exp, target, tmode, modifier)
            vars = TREE_CHAIN (vars);
          }
 
            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);
 
 
        expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
 
@@ -6734,9 +6561,10 @@ expand_expr (exp, target, tmode, modifier)
       if (ignore)
        {
          tree elt;
       if (ignore)
        {
          tree elt;
+
          for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (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;
        }
 
          return const0_rtx;
        }
 
@@ -6798,39 +6626,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
            && 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);
          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.  */
        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;
          RTX_UNCHANGING_P (temp) = 1;
 
        return temp;
@@ -6892,8 +6700,8 @@ expand_expr (exp, target, tmode, modifier)
              ;
 
            if (elem)
              ;
 
            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
          }
 
        else if (optimize >= 1
@@ -6919,7 +6727,7 @@ expand_expr (exp, target, tmode, modifier)
 
                    if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
                      return expand_expr (fold (TREE_VALUE (elem)), target,
 
                    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,
                  }
                else if (TREE_CODE (init) == STRING_CST
                         && 0 > compare_tree_int (index,
@@ -6973,16 +6781,16 @@ expand_expr (exp, target, tmode, modifier)
                  {
                    HOST_WIDE_INT bitsize
                      = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
                  {
                    HOST_WIDE_INT bitsize
                      = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
+                   enum machine_mode imode
+                     = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
 
                    if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
                      {
                        op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
 
                    if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
                      {
                        op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
-                       op0 = expand_and (op0, op1, target);
+                       op0 = expand_and (imode, op0, op1, target);
                      }
                    else
                      {
                      }
                    else
                      {
-                       enum machine_mode imode
-                         = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
                        tree count
                          = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
                                         0);
                        tree count
                          = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
                                         0);
@@ -7042,7 +6850,7 @@ expand_expr (exp, target, tmode, modifier)
 
        if (offset != 0)
          {
 
        if (offset != 0)
          {
-           rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
+           rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
 
            /* 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
 
            /* 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
@@ -7092,15 +6900,7 @@ expand_expr (exp, target, tmode, modifier)
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
                && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
              {
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
                && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
              {
-               rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-
-               if (GET_CODE (XEXP (temp, 0)) == REG)
-                 op0 = temp;
-               else
-                 op0 = (replace_equiv_address
-                        (op0,
-                         force_reg (GET_MODE (XEXP (temp, 0)),
-                                    XEXP (temp, 0))));
+               op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
                bitpos = 0;
              }
 
                bitpos = 0;
              }
 
@@ -7117,34 +6917,6 @@ expand_expr (exp, target, tmode, modifier)
            MEM_VOLATILE_P (op0) = 1;
          }
 
            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
        /* 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
@@ -7216,7 +6988,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
               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),
              op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
                                  size_int (GET_MODE_BITSIZE (GET_MODE (op0))
                                            - bitsize),
@@ -7416,7 +7188,7 @@ expand_expr (exp, target, tmode, modifier)
       if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
        {
          WITH_CLEANUP_EXPR_RTL (exp)
       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.  */
          expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1));
 
          /* That's it for this cleanup.  */
@@ -7432,7 +7204,7 @@ expand_expr (exp, target, tmode, modifier)
 
        target_temp_slot_level = temp_slot_level;
 
 
        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);
        /* If we're going to use this value, load it up now.  */
        if (! ignore)
          op0 = force_not_mem (op0);
@@ -7507,7 +7279,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,
       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
 
          /* If the signedness of the conversion differs and OP0 is
             a promoted SUBREG, clear that indication since we now
@@ -7519,15 +7291,24 @@ expand_expr (exp, target, tmode, modifier)
          return op0;
        }
 
          return op0;
        }
 
-      op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
+      op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
       if (GET_MODE (op0) == mode)
        return op0;
 
       /* If OP0 is a constant, just convert it into the proper mode.  */
       if (CONSTANT_P (op0))
       if (GET_MODE (op0) == mode)
        return op0;
 
       /* If OP0 is a constant, just convert it into the proper mode.  */
       if (CONSTANT_P (op0))
-       return
-         convert_modes (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
-                        op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
+       {
+         tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+         enum machine_mode inner_mode = TYPE_MODE (inner_type);
+
+          if (modifier == EXPAND_INITIALIZER)
+           return simplify_gen_subreg (mode, op0, inner_mode,
+                                       subreg_lowpart_offset (mode,
+                                                              inner_mode));
+         else
+           return convert_modes (mode, inner_mode, op0,
+                                 TREE_UNSIGNED (inner_type));
+       }
 
       if (modifier == EXPAND_INITIALIZER)
        return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
 
       if (modifier == EXPAND_INITIALIZER)
        return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
@@ -7542,7 +7323,7 @@ expand_expr (exp, target, tmode, modifier)
       return target;
 
     case VIEW_CONVERT_EXPR:
       return target;
 
     case VIEW_CONVERT_EXPR:
-      op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, ro_modifier);
+      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
 
       /* 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
@@ -7589,16 +7370,16 @@ expand_expr (exp, target, tmode, modifier)
                   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
            {
              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
                   && 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),
-                                            GET_MODE_SIZE (TYPE_MODE (type)));
+             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 = assign_stack_temp_for_type (TYPE_MODE (type),
                                                    temp_size, 0, type);
-             rtx new_with_op0_mode = copy_rtx (new);
+             rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
 
              if (TREE_ADDRESSABLE (exp))
                abort ();
 
 
              if (TREE_ADDRESSABLE (exp))
                abort ();
 
-             PUT_MODE (new_with_op0_mode, GET_MODE (op0));
              if (GET_MODE (op0) == BLKmode)
                emit_block_move (new_with_op0_mode, op0,
                                 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
              if (GET_MODE (op0) == BLKmode)
                emit_block_move (new_with_op0_mode, op0,
                                 GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
@@ -7608,7 +7389,7 @@ expand_expr (exp, target, tmode, modifier)
              op0 = new;
            }
       
              op0 = new;
            }
       
-         PUT_MODE (op0, TYPE_MODE (type));
+         op0 = adjust_address (op0, TYPE_MODE (type), 0);
        }
 
       return op0;
        }
 
       return op0;
@@ -7618,7 +7399,7 @@ expand_expr (exp, target, tmode, modifier)
          constant.  */
     plus_expr:
       this_optab = ! unsignedp && flag_trapv
          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
                    ? addv_optab : add_optab;
 
       /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
@@ -7722,8 +7503,8 @@ expand_expr (exp, target, tmode, modifier)
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
 
       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.  */
 
     both_summands:
       /* Make sure any term that's a sum with a constant comes last.  */
@@ -7782,10 +7563,10 @@ expand_expr (exp, target, tmode, modifier)
          && really_constant_p (TREE_OPERAND (exp, 0))
          && really_constant_p (TREE_OPERAND (exp, 1)))
        {
          && 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.  */
 
          /* If the last operand is a CONST_INT, use plus_constant of
             the negated constant.  Else make the MINUS.  */
@@ -7831,23 +7612,20 @@ expand_expr (exp, target, tmode, modifier)
         indexed address, for machines that support that.  */
 
       if (modifier == EXPAND_SUM && mode == ptr_mode
         indexed address, for machines that support that.  */
 
       if (modifier == EXPAND_SUM && mode == ptr_mode
-         && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+         && host_integerp (TREE_OPERAND (exp, 1), 0))
        {
          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
                             EXPAND_SUM);
 
        {
          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
                             EXPAND_SUM);
 
-         /* Apply distributive law if OP0 is x+c.  */
-         if (GET_CODE (op0) == PLUS
-             && GET_CODE (XEXP (op0, 1)) == CONST_INT)
-           return
-             gen_rtx_PLUS
-               (mode,
-                gen_rtx_MULT
-                (mode, XEXP (op0, 0),
-                 GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
-                GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
-                         * INTVAL (XEXP (op0, 1))));
+         /* If we knew for certain that this is arithmetic for an array
+            reference, and we knew the bounds of the array, then we could
+            apply the distributive law across (PLUS X C) for constant C.
+            Without such knowledge, we risk overflowing the computation
+            when both X and C are large, but X+C isn't.  */
+         /* ??? Could perhaps special-case EXP being unsigned and C being
+            positive.  In that case we are certain that X+C is no smaller
+            than X and so the transformed expression will overflow iff the
+            original would have.  */
 
          if (GET_CODE (op0) != REG)
            op0 = force_operand (op0, NULL_RTX);
 
          if (GET_CODE (op0) != REG)
            op0 = force_operand (op0, NULL_RTX);
@@ -7856,7 +7634,7 @@ expand_expr (exp, target, tmode, modifier)
 
          return
            gen_rtx_MULT (mode, op0,
 
          return
            gen_rtx_MULT (mode, op0,
-                         GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
+                         GEN_INT (tree_low_cst (TREE_OPERAND (exp, 1), 0)));
        }
 
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        }
 
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
@@ -8267,11 +8045,11 @@ expand_expr (exp, target, tmode, modifier)
            if (ignore)
              {
                expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
            if (ignore)
              {
                expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-                            ro_modifier);
+                            modifier);
                return const0_rtx;
              }
 
                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;
 
            if (GET_MODE (op0) == mode)
              return op0;
 
@@ -8737,21 +8515,30 @@ expand_expr (exp, target, tmode, modifier)
                   || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
                   || GET_CODE (op0) == PARALLEL)
            {
                   || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
                   || GET_CODE (op0) == PARALLEL)
            {
-             /* If this object is in a register, it must can't 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);
-
-             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));
+             /* 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
              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)
            }
 
          if (GET_CODE (op0) != MEM)
@@ -8804,7 +8591,11 @@ expand_expr (exp, target, tmode, modifier)
          op0 = force_operand (XEXP (op0, 0), target);
        }
 
          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
        op0 = force_reg (Pmode, op0);
 
       if (GET_CODE (op0) == REG
@@ -9076,7 +8867,7 @@ expand_increment (exp, post, ignore)
      and insns were generated in computing it.  */
 
   temp = get_last_insn ();
      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,
 
   /* 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,
@@ -9107,8 +8898,7 @@ expand_increment (exp, post, ignore)
 
   op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
                 && temp != get_last_insn ());
 
   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
 
   /* Decide whether incrementing or decrementing.  */
   if (TREE_CODE (exp) == POSTDECREMENT_EXPR
@@ -9124,7 +8914,7 @@ expand_increment (exp, post, ignore)
     }
 
   if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
     }
 
   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)
 
   /* For a preincrement, see if we can do this with a single instruction.  */
   if (!post)
@@ -9229,9 +9019,9 @@ expand_increment (exp, post, ignore)
     temp = copy_rtx (value = op0);
 
   /* Increment however we can.  */
     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);
                      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
+
   /* Make sure the value is stored into OP0.  */
   if (op1 != op0)
     emit_move_insn (op0, op1);
   /* Make sure the value is stored into OP0.  */
   if (op1 != op0)
     emit_move_insn (op0, op1);
@@ -10417,7 +10207,7 @@ do_store_flag (exp, target, mode, only_cheap)
 
       /* Put the AND last so it can combine with more things.  */
       if (bitnum != TYPE_PRECISION (type) - 1)
 
       /* Put the AND last so it can combine with more things.  */
       if (bitnum != TYPE_PRECISION (type) - 1)
-       op0 = expand_and (op0, const1_rtx, subtarget);
+       op0 = expand_and (mode, op0, const1_rtx, subtarget);
 
       return op0;
     }
 
       return op0;
     }
@@ -10488,6 +10278,14 @@ do_store_flag (exp, target, mode, only_cheap)
             || (result != const0_rtx && invert))
            ? const0_rtx : const1_rtx);
 
             || (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 ();
   label = gen_label_rtx ();
   if (bcc_gen_fctn[(int) code] == 0)
     abort ();