OSDN Git Service

* alias.c (get_alias_set): Try to replace PLACEHOLDER_EXPR.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 970c275..52f9cc0 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
    2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -33,6 +33,8 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-config.h"
 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
 #include "expr.h"
+#include "optabs.h"
+#include "libfuncs.h"
 #include "recog.h"
 #include "reload.h"
 #include "output.h"
@@ -161,9 +163,6 @@ static rtx store_field              PARAMS ((rtx, HOST_WIDE_INT,
                                         unsigned int, HOST_WIDE_INT, int));
 static enum memory_use_mode
   get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
-static tree save_noncopied_parts PARAMS ((tree, tree));
-static tree init_noncopied_parts PARAMS ((tree, tree));
-static int fixed_type_p                PARAMS ((tree));
 static rtx var_rtx             PARAMS ((tree));
 static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
@@ -172,7 +171,10 @@ static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
 static void do_compare_and_jump        PARAMS ((tree, enum rtx_code, enum rtx_code,
                                         rtx, rtx));
 static rtx do_store_flag       PARAMS ((tree, rtx, enum machine_mode, int));
+#ifdef PUSH_ROUNDING
 static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
+#endif
+static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
 
 /* Record for each mode whether we can move a register directly to or
    from an object of that mode in memory.  If we can't, we won't try
@@ -384,20 +386,23 @@ protect_from_queue (x, modify)
       if (code == MEM && GET_MODE (x) != BLKmode
          && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
        {
-         register rtx y = XEXP (x, 0);
-         register rtx new = gen_rtx_MEM (GET_MODE (x), QUEUED_VAR (y));
-
-         MEM_COPY_ATTRIBUTES (new, x);
+         rtx y = XEXP (x, 0);
+         rtx new = replace_equiv_address_nv (x, QUEUED_VAR (y));
 
          if (QUEUED_INSN (y))
            {
-             register rtx temp = gen_reg_rtx (GET_MODE (new));
+             rtx temp = gen_reg_rtx (GET_MODE (x));
+
              emit_insn_before (gen_move_insn (temp, new),
                                QUEUED_INSN (y));
              return temp;
            }
-         return new;
+
+         /* Copy the address into a pseudo, so that the returned value
+            remains correct across calls to emit_queue.  */
+         return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
        }
+
       /* Otherwise, recursively protect the subexpressions of all
         the kinds of rtx's that can contain a QUEUED.  */
       if (code == MEM)
@@ -422,9 +427,11 @@ protect_from_queue (x, modify)
        }
       return x;
     }
-  /* If the increment has not happened, use the variable itself.  */
+  /* If the increment has not happened, use the variable itself.  Copy it
+     into a new pseudo so that the value remains correct across calls to
+     emit_queue.  */
   if (QUEUED_INSN (x) == 0)
-    return QUEUED_VAR (x);
+    return copy_to_reg (QUEUED_VAR (x));
   /* If the increment has happened and a pre-increment copy exists,
      use that copy.  */
   if (QUEUED_COPY (x) != 0)
@@ -1382,13 +1389,12 @@ convert_modes (mode, oldmode, x, unsignedp)
 #define MOVE_MAX_PIECES   MOVE_MAX
 #endif
 
-/* Generate several move instructions to copy LEN bytes
-   from block FROM to block TO.  (These are MEM rtx's with BLKmode).
-   The caller must pass FROM and TO
-    through protect_from_queue before calling.
+/* Generate several move instructions to copy LEN bytes from block FROM to
+   block TO.  (These are MEM rtx's with BLKmode).  The caller must pass FROM
+   and TO through protect_from_queue before calling.
 
-   When TO is NULL, the emit_single_push_insn is used to push the
-   FROM to stack.
+   If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
+   used to push FROM to the stack.
 
    ALIGN is maximum alignment we can assume.  */
 
@@ -1511,7 +1517,7 @@ move_by_pieces (to, from, len, align)
 }
 
 /* Return number of insns required to move L bytes by pieces.
-   ALIGN (in bytes) is maximum alignment we can assume.  */
+   ALIGN (in bits) is maximum alignment we can assume.  */
 
 static unsigned HOST_WIDE_INT
 move_by_pieces_ninsns (l, align)
@@ -1561,7 +1567,7 @@ move_by_pieces_1 (genfun, mode, data)
      struct move_by_pieces *data;
 {
   unsigned int size = GET_MODE_SIZE (mode);
-  rtx to1, from1;
+  rtx to1 = NULL_RTX, from1;
 
   while (data->len >= size)
     {
@@ -1572,22 +1578,20 @@ move_by_pieces_1 (genfun, mode, data)
        {
          if (data->autinc_to)
            {
-             to1 = gen_rtx_MEM (mode, data->to_addr);
-             MEM_COPY_ATTRIBUTES (to1, data->to);
+             to1 = replace_equiv_address (data->to, data->to_addr);
+             to1 = adjust_address (to1, mode, 0);
            }
          else
-           to1 = change_address (data->to, mode,
-                                 plus_constant (data->to_addr, data->offset));
+           to1 = adjust_address (data->to, mode, data->offset);
        }
 
       if (data->autinc_from)
        {
-         from1 = gen_rtx_MEM (mode, data->from_addr);
-         MEM_COPY_ATTRIBUTES (from1, data->from);
+         from1 = replace_equiv_address (data->from, data->from_addr);
+         from1 = adjust_address (from1, mode, 0);
        }
       else
-       from1 = change_address (data->from, mode,
-                               plus_constant (data->from_addr, data->offset));
+       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)));
@@ -1597,7 +1601,13 @@ move_by_pieces_1 (genfun, mode, data)
       if (data->to)
        emit_insn ((*genfun) (to1, from1));
       else
-       emit_single_push_insn (mode, from1, NULL);
+       {
+#ifdef PUSH_ROUNDING
+         emit_single_push_insn (mode, from1, NULL);
+#else
+         abort ();
+#endif
+       }
 
       if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
        emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
@@ -1768,7 +1778,8 @@ emit_block_move (x, y, size, align)
          DECL_EXTERNAL (fn) = 1;
          TREE_PUBLIC (fn) = 1;
          DECL_ARTIFICIAL (fn) = 1;
-         make_decl_rtl (fn, NULL_PTR);
+         TREE_NOTHROW (fn) = 1;
+         make_decl_rtl (fn, NULL);
          assemble_external (fn);
        }
 
@@ -1875,8 +1886,7 @@ move_block_from_reg (regno, x, nregs, size)
   if (size <= UNITS_PER_WORD
       && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
     {
-      emit_move_insn (change_address (x, mode, NULL),
-                     gen_rtx_REG (mode, regno));
+      emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
       return;
     }
 
@@ -1959,18 +1969,6 @@ emit_group_load (dst, orig_src, ssize, align)
 
   tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
 
-  /* If we won't be loading directly from memory, protect the real source
-     from strange tricks we might play.  */
-  src = orig_src;
-  if (GET_CODE (src) != MEM && ! CONSTANT_P (src))
-    {
-      if (GET_MODE (src) == VOIDmode)
-       src = gen_reg_rtx (GET_MODE (dst));
-      else
-       src = gen_reg_rtx (GET_MODE (orig_src));
-      emit_move_insn (src, orig_src);
-    }
-
   /* Process the pieces.  */
   for (i = start; i < XVECLEN (dst, 0); i++)
     {
@@ -1988,6 +1986,22 @@ emit_group_load (dst, orig_src, ssize, align)
            abort ();
        }
 
+      /* If we won't be loading directly from memory, protect the real source
+        from strange tricks we might play; but make sure that the source can
+        be loaded directly into the destination.  */
+      src = orig_src;
+      if (GET_CODE (orig_src) != MEM
+         && (!CONSTANT_P (orig_src)
+             || (GET_MODE (orig_src) != mode
+                 && GET_MODE (orig_src) != VOIDmode)))
+       {
+         if (GET_MODE (orig_src) == VOIDmode)
+           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)
@@ -1995,10 +2009,7 @@ emit_group_load (dst, orig_src, ssize, align)
          && bytelen == GET_MODE_SIZE (mode))
        {
          tmps[i] = gen_reg_rtx (mode);
-         emit_move_insn (tmps[i],
-                         change_address (src, mode,
-                                         plus_constant (XEXP (src, 0),
-                                                        bytepos)));
+         emit_move_insn (tmps[i], adjust_address (src, mode, bytepos));
        }
       else if (GET_CODE (src) == CONCAT)
        {
@@ -2011,8 +2022,7 @@ emit_group_load (dst, orig_src, ssize, align)
          else
            abort ();
        }
-      else if ((CONSTANT_P (src)
-               && (GET_MODE (src) == VOIDmode || GET_MODE (src) == mode))
+      else if (CONSTANT_P (src)
               || (GET_CODE (src) == REG && GET_MODE (src) == mode))
        tmps[i] = src;
       else
@@ -2119,13 +2129,10 @@ emit_group_store (orig_dst, src, ssize, align)
          && align >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
-       emit_move_insn (change_address (dst, mode,
-                                       plus_constant (XEXP (dst, 0),
-                                                      bytepos)),
-                       tmps[i]);
+       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], align, ssize);
     }
 
   emit_queue ();
@@ -2192,7 +2199,8 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
         (the first time through).  */
       if (xbitpos % BITS_PER_WORD == 0
          || xbitpos == big_endian_correction)
-       src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD, BLKmode);
+       src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
+                                    GET_MODE (srcreg));
 
       /* We need a new destination operand each time bitpos is on
         a word boundary.  */
@@ -2382,7 +2390,7 @@ clear_by_pieces (to, len, align)
   struct store_by_pieces data;
 
   data.constfun = clear_by_pieces_1;
-  data.constfundata = NULL_PTR;
+  data.constfundata = NULL;
   data.len = len;
   data.to = to;
   store_by_pieces_1 (&data, align);
@@ -2507,12 +2515,11 @@ store_by_pieces_2 (genfun, mode, data)
 
       if (data->autinc_to)
        {
-         to1 = gen_rtx_MEM (mode, data->to_addr);
-         MEM_COPY_ATTRIBUTES (to1, data->to);
+         to1 = replace_equiv_address (data->to, data->to_addr);
+         to1 = adjust_address (to1, mode, 0);
        }
       else
-       to1 = change_address (data->to, mode,
-                             plus_constant (data->to_addr, data->offset));
+       to1 = adjust_address (data->to, mode, data->offset);
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
        emit_insn (gen_add2_insn (data->to_addr,
@@ -2650,7 +2657,7 @@ clear_storage (object, size, align)
 
             For targets where libcalls and normal calls have different
             conventions for returning pointers, we could end up generating
-             incorrect code.
+            incorrect code.
 
             So instead of using a libcall sequence we build up a suitable
             CALL_EXPR and expand the call in the normal fashion.  */
@@ -2668,7 +2675,8 @@ clear_storage (object, size, align)
              DECL_EXTERNAL (fn) = 1;
              TREE_PUBLIC (fn) = 1;
              DECL_ARTIFICIAL (fn) = 1;
-             make_decl_rtl (fn, NULL_PTR);
+             TREE_NOTHROW (fn) = 1;
+             make_decl_rtl (fn, NULL);
              assemble_external (fn);
            }
 
@@ -2744,13 +2752,13 @@ emit_move_insn (x, y)
           && ! push_operand (x, GET_MODE (x)))
          || (flag_force_addr
              && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
-    x = change_address (x, VOIDmode, XEXP (x, 0));
+    x = validize_mem (x);
 
   if (GET_CODE (y) == MEM
       && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
          || (flag_force_addr
              && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
-    y = change_address (y, VOIDmode, XEXP (y, 0));
+    y = validize_mem (y);
 
   if (mode == BLKmode)
     abort ();
@@ -2900,7 +2908,7 @@ emit_move_insn_1 (x, y)
                    {
                      rtx mem = assign_stack_temp (reg_mode,
                                                   GET_MODE_SIZE (mode), 0);
-                     rtx cmem = change_address (mem, mode, NULL_RTX);
+                     rtx cmem = adjust_address (mem, mode, 0);
 
                      cfun->cannot_inline
                        = N_("function using short complex types cannot be inline");
@@ -2962,8 +2970,39 @@ emit_move_insn_1 (x, y)
         X with a reference to the stack pointer.  */
       if (push_operand (x, GET_MODE (x)))
        {
-         anti_adjust_stack (GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
-         x = change_address (x, VOIDmode, stack_pointer_rtx);
+         rtx temp;
+         enum rtx_code code;
+         
+         /* Do not use anti_adjust_stack, since we don't want to update
+            stack_pointer_delta.  */
+         temp = expand_binop (Pmode,
+#ifdef STACK_GROWS_DOWNWARD
+                              sub_optab,
+#else
+                              add_optab,
+#endif
+                              stack_pointer_rtx,
+                              GEN_INT
+                                (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))));
+         else if (code == POST_DEC)
+           temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 
+                               GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
+         else
+           temp = stack_pointer_rtx;
+
+         x = change_address (x, VOIDmode, temp);
        }
 #endif
 
@@ -2971,20 +3010,10 @@ emit_move_insn_1 (x, y)
         is scheduled for replacement.  */
       if (reload_in_progress && GET_CODE (x) == MEM
          && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
-       {
-         rtx new = gen_rtx_MEM (GET_MODE (x), inner);
-
-         MEM_COPY_ATTRIBUTES (new, x);
-         x = new;
-       }
+       x = replace_equiv_address_nv (x, inner);
       if (reload_in_progress && GET_CODE (y) == MEM
          && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
-       {
-         rtx new = gen_rtx_MEM (GET_MODE (y), inner);
-
-         MEM_COPY_ATTRIBUTES (new, y);
-         y = new;
-       }
+       y = replace_equiv_address_nv (y, inner);
 
       start_sequence ();
 
@@ -3070,18 +3099,11 @@ push_block (size, extra, below)
     }
 
 #ifndef STACK_GROWS_DOWNWARD
-#ifdef ARGS_GROW_DOWNWARD
-  if (!ACCUMULATE_OUTGOING_ARGS)
-#else
   if (0)
-#endif
 #else
   if (1)
 #endif
     {
-      /* Return the lowest stack address when STACK or ARGS grow downward and
-        we are not aaccumulating outgoing arguments (the c4x port uses such
-        conventions).  */
       temp = virtual_outgoing_args_rtx;
       if (extra != 0 && below)
        temp = plus_constant (temp, extra);
@@ -3122,25 +3144,41 @@ get_push_address (size)
   return copy_to_reg (temp);
 }
 
+#ifdef PUSH_ROUNDING
+
 /* Emit single push insn.  */
+
 static void
 emit_single_push_insn (mode, x, type)
      rtx x;
      enum machine_mode mode;
      tree type;
 {
-#ifdef PUSH_ROUNDING
   rtx dest_addr;
-  int rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
+  unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
   rtx dest;
+  enum insn_code icode;
+  insn_operand_predicate_fn pred;
 
+  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+  /* If there is push pattern, use it.  Otherwise try old way of throwing
+     MEM representing push operation to move expander.  */
+  icode = push_optab->handlers[(int) mode].insn_code;
+  if (icode != CODE_FOR_nothing)
+    {
+      if (((pred = insn_data[(int) icode].operand[0].predicate)
+         && !((*pred) (x, mode))))
+       x = force_reg (mode, x);
+      emit_insn (GEN_FCN (icode) (x));
+      return;
+    }
   if (GET_MODE_SIZE (mode) == rounded_size)
     dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
   else
     {
 #ifdef STACK_GROWS_DOWNWARD
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               GEN_INT (-rounded_size));
+                               GEN_INT (-(HOST_WIDE_INT)rounded_size));
 #else
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
                                GEN_INT (rounded_size));
@@ -3150,8 +3188,6 @@ emit_single_push_insn (mode, x, type)
 
   dest = gen_rtx_MEM (mode, dest_addr);
 
-  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
-
   if (type != 0)
     {
       set_mem_attributes (dest, type, 1);
@@ -3159,13 +3195,11 @@ emit_single_push_insn (mode, x, type)
          outgoing arguments and we cannot allow reordering of reads
          from function arguments with stores to outgoing arguments
          of sibling calls.  */
-      MEM_ALIAS_SET (dest) = 0;
+      set_mem_alias_set (dest, 0);
     }
   emit_move_insn (dest, x);
-#else
-  abort();
-#endif
 }
+#endif
 
 /* Generate code to push X onto the stack, assuming it has mode MODE and
    type TYPE.
@@ -3174,7 +3208,7 @@ emit_single_push_insn (mode, x, type)
    SIZE is an rtx for the size of data to be copied (in bytes),
    needed only if X is BLKmode.
 
-   ALIGN is maximum alignment we can assume.
+   ALIGN (in bits) is maximum alignment we can assume.
 
    If PARTIAL and REG are both nonzero, then copy that many of the first
    words of X into registers starting with REG, and push the rest of X.
@@ -3229,8 +3263,9 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
      Default is below for small data on big-endian machines; else above.  */
   enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
 
-  /* Invert direction if stack is post-update.  */
-  if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC)
+  /* Invert direction if stack is post-decrement. 
+     FIXME: why?  */
+  if (STACK_PUSH_CODE == POST_DEC)
     if (where_pad != none)
       where_pad = (where_pad == downward ? upward : downward);
 
@@ -3254,8 +3289,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
         because registers will take care of them.  */
 
       if (partial != 0)
-       xinner = change_address (xinner, BLKmode,
-                                plus_constant (XEXP (xinner, 0), used));
+       xinner = adjust_address (xinner, BLKmode, used);
 
       /* If the partial register-part of the arg counts in its stack size,
         skip the part of stack space corresponding to the registers.
@@ -3277,7 +3311,8 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
             and such small pushes do rounding that causes trouble.  */
          && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
              || align >= BIGGEST_ALIGNMENT
-             || PUSH_ROUNDING (align) == align)
+             || (PUSH_ROUNDING (align / BITS_PER_UNIT)
+                 == (align / BITS_PER_UNIT)))
          && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
        {
          /* Push padding now if padding above and stack grows down,
@@ -3377,7 +3412,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                 outgoing arguments and we cannot allow reordering of reads
                 from function arguments with stores to outgoing arguments
                 of sibling calls.  */
-             MEM_ALIAS_SET (target) = 0;
+             set_mem_alias_set (target, 0);
            }
 
          /* TEMP is the address of the block.  Copy the data there.  */
@@ -3560,7 +3595,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                 outgoing arguments and we cannot allow reordering of reads
                 from function arguments with stores to outgoing arguments
                 of sibling calls.  */
-             MEM_ALIAS_SET (dest) = 0;
+             set_mem_alias_set (dest, 0);
            }
 
          emit_move_insn (dest, x);
@@ -3666,7 +3701,7 @@ expand_assignment (to, from, want_value, suggest_reg)
      problem.  */
 
   if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF
-      || TREE_CODE (to) == ARRAY_REF)
+      || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF)
     {
       enum machine_mode mode1;
       HOST_WIDE_INT bitsize, bitpos;
@@ -3713,16 +3748,15 @@ expand_assignment (to, from, want_value, suggest_reg)
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && alignment == GET_MODE_ALIGNMENT (mode1))
            {
-             rtx temp = change_address (to_rtx, mode1,
-                                        plus_constant (XEXP (to_rtx, 0),
-                                                       (bitpos /
-                                                        BITS_PER_UNIT)));
+             rtx temp
+               = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
+
              if (GET_CODE (XEXP (temp, 0)) == REG)
                to_rtx = temp;
              else
-               to_rtx = change_address (to_rtx, mode1,
-                                        force_reg (GET_MODE (XEXP (temp, 0)),
-                                                   XEXP (temp, 0)));
+               to_rtx = (replace_equiv_address
+                         (to_rtx, force_reg (GET_MODE (XEXP (temp, 0)),
+                                             XEXP (temp, 0))));
              bitpos = 0;
            }
 
@@ -3798,9 +3832,7 @@ expand_assignment (to, from, want_value, suggest_reg)
          unsigned int from_align;
          rtx from_rtx = expand_expr_unaligned (from, &from_align);
          rtx inner_to_rtx
-           = change_address (to_rtx, VOIDmode,
-                             plus_constant (XEXP (to_rtx, 0),
-                                            bitpos / BITS_PER_UNIT));
+           = adjust_address (to_rtx, BLKmode, bitpos / BITS_PER_UNIT);
 
          emit_block_move (inner_to_rtx, from_rtx, expr_size (from),
                           MIN (alignment, from_align));
@@ -3887,7 +3919,7 @@ expand_assignment (to, from, want_value, suggest_reg)
     {
       to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_WO);
       if (GET_CODE (to_rtx) == MEM)
-       MEM_ALIAS_SET (to_rtx) = get_alias_set (to);
+       set_mem_alias_set (to_rtx, get_alias_set (to));
     }
 
   /* Don't move directly into a return register.  */
@@ -3935,7 +3967,7 @@ expand_assignment (to, from, want_value, suggest_reg)
                           TYPE_MODE (sizetype));
 
 #ifdef TARGET_MEM_FUNCTIONS
-      emit_library_call (memcpy_libfunc, LCT_NORMAL,
+      emit_library_call (memmove_libfunc, LCT_NORMAL,
                         VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
                         XEXP (from_rtx, 0), Pmode,
                         convert_to_mode (TYPE_MODE (sizetype),
@@ -4447,13 +4479,11 @@ store_constructor_field (target, bitsize, bitpos,
     {
       if (bitpos != 0)
        target
-         = change_address (target,
+         = adjust_address (target,
                            GET_MODE (target) == BLKmode
                            || 0 != (bitpos
                                     % GET_MODE_ALIGNMENT (GET_MODE (target)))
-                           ? BLKmode : VOIDmode,
-                           plus_constant (XEXP (target, 0),
-                                          bitpos / BITS_PER_UNIT));
+                           ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
 
 
       /* Show the alignment may no longer be what it was and update the alias
@@ -4461,7 +4491,7 @@ store_constructor_field (target, bitsize, bitpos,
       if (bitpos != 0)
        align = MIN (align, (unsigned int) bitpos & - bitpos);
       if (GET_CODE (target) == MEM)
-       MEM_ALIAS_SET (target) = alias_set;
+       set_mem_alias_set (target, alias_set);
 
       store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
     }
@@ -4537,7 +4567,7 @@ store_constructor (exp, target, align, cleared, size)
 
       /* If the constructor has fewer fields than the structure
         or if we are initializing the structure to mostly zeros,
-        clear the whole structure first.  Don't do this is TARGET is
+        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
@@ -4680,10 +4710,12 @@ store_constructor (exp, target, align, cleared, size)
       int need_to_clear;
       tree domain = TYPE_DOMAIN (type);
       tree elttype = TREE_TYPE (type);
-      int const_bounds_p = (host_integerp (TYPE_MIN_VALUE (domain), 0)
+      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));
-      HOST_WIDE_INT minelt;
-      HOST_WIDE_INT maxelt;
+      HOST_WIDE_INT minelt = 0;
+      HOST_WIDE_INT maxelt = 0;
 
       /* If we have constant bounds for the range of the type, get them.  */
       if (const_bounds_p)
@@ -4748,7 +4780,7 @@ store_constructor (exp, target, align, cleared, size)
            clear_storage (target, GEN_INT (size), align);
          cleared = 1;
        }
-      else
+      else if (REG_P (target))
        /* Inform later passes that the old value is dead.  */
        emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
 
@@ -4979,10 +5011,7 @@ store_constructor (exp, target, align, cleared, size)
                         XEXP if the set is multi-word, but not if
                         it's single-word.  */
                      if (GET_CODE (target) == MEM)
-                       {
-                         to_rtx = plus_constant (XEXP (target, 0), offset);
-                         to_rtx = change_address (target, mode, to_rtx);
-                       }
+                       to_rtx = adjust_address (target, mode, offset);
                      else if (offset == 0)
                        to_rtx = target;
                      else
@@ -5131,6 +5160,11 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
   if (TREE_CODE (exp) == ERROR_MARK)
     return const0_rtx;
 
+  /* If we have nothing to store, do nothing unless the expression has
+     side-effects.  */
+  if (bitsize == 0)
+    return expand_expr (exp, const0_rtx, VOIDmode, 0);
+
   if (bitsize < HOST_BITS_PER_WIDE_INT)
     width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
 
@@ -5235,9 +5269,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
              || bitpos % BITS_PER_UNIT != 0)
            abort ();
 
-         target = change_address (target, VOIDmode,
-                                  plus_constant (XEXP (target, 0),
-                                               bitpos / BITS_PER_UNIT));
+         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);
@@ -5303,24 +5335,31 @@ 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)))
-       addr = copy_to_reg (addr);
+       target = replace_equiv_address (target, copy_to_reg (addr));
 
       /* Now build a reference to just the desired component.  */
 
-      to_rtx = copy_rtx (change_address (target, mode,
-                                        plus_constant (addr,
-                                                       (bitpos
-                                                        / BITS_PER_UNIT))));
+      to_rtx = copy_rtx (adjust_address (target, mode,
+                                        bitpos / BITS_PER_UNIT));
+
       MEM_SET_IN_STRUCT_P (to_rtx, 1);
-      MEM_ALIAS_SET (to_rtx) = alias_set;
+      /* If the address of the structure varies, then it might be on
+        the stack.  And, stack slots may be shared across scopes.
+        So, two different structures, of different types, can end up
+        at the same location.  We will give the structures alias set
+        zero; here we must be careful not to give non-zero alias sets
+        to their fields.  */
+      set_mem_alias_set (to_rtx,
+                        rtx_varies_p (addr, /*for_alias=*/0)
+                        ? 0 : alias_set);
 
       return store_expr (exp, to_rtx, value_mode != VOIDmode);
     }
 }
 \f
 /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
-   or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or
-   ARRAY_REFs and find the ultimate containing object, which we return.
+   an ARRAY_REF, or an ARRAY_RANGE_REF, look for nested operations of these
+   codes and find the ultimate containing object, which we return.
 
    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
    bit position, and *PUNSIGNEDP to the signedness of the field.
@@ -5424,12 +5463,14 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
            alignment = MIN (alignment, DECL_OFFSET_ALIGN (field));
        }
 
-      else if (TREE_CODE (exp) == ARRAY_REF)
+      else if (TREE_CODE (exp) == ARRAY_REF
+              || TREE_CODE (exp) == ARRAY_RANGE_REF)
        {
          tree index = TREE_OPERAND (exp, 1);
-         tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+         tree array = TREE_OPERAND (exp, 0);
+         tree domain = TYPE_DOMAIN (TREE_TYPE (array));
          tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
-         tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
+         tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
 
          /* We assume all arrays have sizes that are a multiple of a byte.
             First subtract the lower bound, if any, in the type of the
@@ -5447,8 +5488,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
            index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
          if (! TREE_CONSTANT (unit_size)
              && contains_placeholder_p (unit_size))
-           unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size,
-                              TREE_OPERAND (exp, 0));
+           unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
 
          offset = size_binop (PLUS_EXPR, offset,
                               size_binop (MULT_EXPR,
@@ -5618,69 +5658,6 @@ force_operand (value, target)
   return value;
 }
 \f
-/* Subroutine of expand_expr:
-   save the non-copied parts (LIST) of an expr (LHS), and return a list
-   which can restore these values to their previous values,
-   should something modify their storage.  */
-
-static tree
-save_noncopied_parts (lhs, list)
-     tree lhs;
-     tree list;
-{
-  tree tail;
-  tree parts = 0;
-
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
-      parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail)));
-    else
-      {
-       tree part = TREE_VALUE (tail);
-       tree part_type = TREE_TYPE (part);
-       tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
-       rtx target
-         = assign_temp (build_qualified_type (part_type,
-                                              (TYPE_QUALS (part_type)
-                                               | TYPE_QUAL_CONST)),
-                        0, 1, 1);
-
-       if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0)))
-         target = change_address (target, TYPE_MODE (part_type), NULL_RTX);
-       parts = tree_cons (to_be_saved,
-                          build (RTL_EXPR, part_type, NULL_TREE,
-                                 (tree) target),
-                          parts);
-       store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0);
-      }
-  return parts;
-}
-
-/* Subroutine of expand_expr:
-   record the non-copied parts (LIST) of an expr (LHS), and return a list
-   which specifies the initial values of these parts.  */
-
-static tree
-init_noncopied_parts (lhs, list)
-     tree lhs;
-     tree list;
-{
-  tree tail;
-  tree parts = 0;
-
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
-      parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
-    else if (TREE_PURPOSE (tail))
-      {
-       tree part = TREE_VALUE (tail);
-       tree part_type = TREE_TYPE (part);
-       tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
-       parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
-      }
-  return parts;
-}
-
 /* Subroutine of expand_expr: return nonzero iff there is no way that
    EXP can reference X, which is being modified.  TOP_P is nonzero if this
    call is going to be used to determine whether we need a temporary
@@ -5822,7 +5799,7 @@ safe_from_p (x, exp, top_p)
          break;
 
        case WITH_CLEANUP_EXPR:
-         exp_rtl = RTL_EXPR_RTL (exp);
+         exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
          break;
 
        case CLEANUP_POINT_EXPR:
@@ -5905,22 +5882,6 @@ safe_from_p (x, exp, top_p)
   return 1;
 }
 
-/* Subroutine of expand_expr: return nonzero iff EXP is an
-   expression whose type is statically determinable.  */
-
-static int
-fixed_type_p (exp)
-     tree exp;
-{
-  if (TREE_CODE (exp) == PARM_DECL
-      || TREE_CODE (exp) == VAR_DECL
-      || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR
-      || TREE_CODE (exp) == COMPONENT_REF
-      || TREE_CODE (exp) == ARRAY_REF)
-    return 1;
-  return 0;
-}
-
 /* Subroutine of expand_expr: return rtx if EXP is a
    variable or parameter; else return 0.  */
 
@@ -5994,6 +5955,69 @@ check_max_integer_computation_mode (exp)
 }
 #endif
 \f
+/* Return an object on the placeholder list that matches EXP, a
+   PLACEHOLDER_EXPR.  An object "matches" if it is of the type of the
+   PLACEHOLDER_EXPR or a pointer type to it.  For further information,
+   see tree.def.  If no such object is found, abort.  If PLIST is nonzero,
+   it is a location into which a pointer into the placeholder list at
+   which the object is found is placed.  */
+
+tree
+find_placeholder (exp, plist)
+     tree exp;
+     tree *plist;
+{
+  tree type = TREE_TYPE (exp);
+  tree placeholder_expr;
+
+  for (placeholder_expr = placeholder_list; placeholder_expr != 0;
+       placeholder_expr = TREE_CHAIN (placeholder_expr))
+    {
+      tree need_type = TYPE_MAIN_VARIANT (type);
+      tree elt;
+
+      /* Find the outermost reference that is of the type we want.  If none,
+        see if any object has a type that is a pointer to the type we
+        want.  */
+      for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+          elt = ((TREE_CODE (elt) == COMPOUND_EXPR
+                  || TREE_CODE (elt) == COND_EXPR)
+                 ? TREE_OPERAND (elt, 1)
+                 : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+                    || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+                 ? TREE_OPERAND (elt, 0) : 0))
+       if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
+         {
+           if (plist)
+             *plist = placeholder_expr;
+           return elt;
+         }
+
+      for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+          elt
+          = ((TREE_CODE (elt) == COMPOUND_EXPR
+              || TREE_CODE (elt) == COND_EXPR)
+             ? TREE_OPERAND (elt, 1)
+             : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+                || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+             ? TREE_OPERAND (elt, 0) : 0))
+       if (POINTER_TYPE_P (TREE_TYPE (elt))
+           && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
+               == need_type))
+         {
+           if (plist)
+             *plist = placeholder_expr;
+           return build1 (INDIRECT_REF, need_type, elt);
+         }
+    }
+
+  abort ();
+}
+\f
 /* expand_expr: generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.
    In the case of a void EXP, const0_rtx is returned.
@@ -6103,10 +6127,12 @@ expand_expr (exp, target, tmode, modifier)
        return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
                            VOIDmode, ro_modifier);
       else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
-              || code == ARRAY_REF)
+              || 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,
+                      ro_modifier);
+         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode,
+                      ro_modifier);
          return const0_rtx;
        }
       else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
@@ -6117,9 +6143,12 @@ expand_expr (exp, target, tmode, modifier)
                            VOIDmode, ro_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,
+                      ro_modifier);
+         expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode,
+                      ro_modifier);
+         expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode,
+                      ro_modifier);
          return const0_rtx;
        }
       ;
@@ -6136,6 +6165,7 @@ expand_expr (exp, target, tmode, modifier)
       && TREE_CODE (exp) != INTEGER_CST
       && TREE_CODE (exp) != PARM_DECL
       && TREE_CODE (exp) != ARRAY_REF
+      && TREE_CODE (exp) != ARRAY_RANGE_REF
       && TREE_CODE (exp) != COMPONENT_REF
       && TREE_CODE (exp) != BIT_FIELD_REF
       && TREE_CODE (exp) != INDIRECT_REF
@@ -6154,6 +6184,7 @@ expand_expr (exp, target, tmode, modifier)
       && TREE_CODE (exp) != INTEGER_CST
       && TREE_CODE (exp) != PARM_DECL
       && TREE_CODE (exp) != ARRAY_REF
+      && TREE_CODE (exp) != ARRAY_RANGE_REF
       && TREE_CODE (exp) != COMPONENT_REF
       && TREE_CODE (exp) != BIT_FIELD_REF
       && TREE_CODE (exp) != INDIRECT_REF
@@ -6297,12 +6328,13 @@ expand_expr (exp, target, tmode, modifier)
            abort ();
          addr = XEXP (DECL_RTL (exp), 0);
          if (GET_CODE (addr) == MEM)
-           addr = change_address (addr, Pmode,
-                                  fix_lexical_addr (XEXP (addr, 0), exp));
+           addr
+             = replace_equiv_address (addr,
+                                      fix_lexical_addr (XEXP (addr, 0), exp));
          else
            addr = fix_lexical_addr (addr, exp);
 
-         temp = change_address (DECL_RTL (exp), mode, addr);
+         temp = replace_equiv_address (DECL_RTL (exp), addr);
        }
 
       /* This is the case of an array whose size is to be determined
@@ -6311,8 +6343,7 @@ expand_expr (exp, target, tmode, modifier)
 
       else if (GET_CODE (DECL_RTL (exp)) == MEM
               && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
-       temp = change_address (DECL_RTL (exp), GET_MODE (DECL_RTL (exp)),
-                              XEXP (DECL_RTL (exp), 0));
+       temp = validize_mem (DECL_RTL (exp));
 
       /* If DECL_RTL is memory, we are in the normal case and either
         the address is not valid or it is not a register and -fforce-addr
@@ -6326,11 +6357,11 @@ expand_expr (exp, target, tmode, modifier)
                                       XEXP (DECL_RTL (exp), 0))
                   || (flag_force_addr
                       && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
-       temp = change_address (DECL_RTL (exp), VOIDmode,
-                              copy_rtx (XEXP (DECL_RTL (exp), 0)));
+       temp = replace_equiv_address (DECL_RTL (exp),
+                                     copy_rtx (XEXP (DECL_RTL (exp), 0)));
 
       /* If we got something, return it.  But first, set the alignment
-        the address is a register.  */
+        if the address is a register.  */
       if (temp != 0)
        {
          if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
@@ -6396,8 +6427,8 @@ expand_expr (exp, target, tmode, modifier)
          && (! memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))
              || (flag_force_addr
                  && GET_CODE (XEXP (TREE_CST_RTL (exp), 0)) != REG)))
-       return change_address (TREE_CST_RTL (exp), VOIDmode,
-                              copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
+       return replace_equiv_address (TREE_CST_RTL (exp),
+                                     copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
       return TREE_CST_RTL (exp);
 
     case EXPR_WITH_FILE_LOCATION:
@@ -6409,7 +6440,7 @@ expand_expr (exp, target, tmode, modifier)
        lineno = EXPR_WFL_LINENO (exp);
        if (EXPR_WFL_EMIT_LINE_NOTE (exp))
          emit_line_note (input_filename, lineno);
-       /* Possibly avoid switching back and force here.  */
+       /* Possibly avoid switching back and forth here.  */
        to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
        input_filename = saved_input_filename;
        lineno = saved_lineno;
@@ -6446,8 +6477,9 @@ expand_expr (exp, target, tmode, modifier)
            }
          if (temp == 0 || GET_CODE (temp) != MEM)
            abort ();
-         return change_address (temp, mode,
-                                fix_lexical_addr (XEXP (temp, 0), exp));
+         return
+           replace_equiv_address (temp,
+                                  fix_lexical_addr (XEXP (temp, 0), exp));
        }
       if (SAVE_EXPR_RTL (exp) == 0)
        {
@@ -6513,66 +6545,14 @@ expand_expr (exp, target, tmode, modifier)
 
     case PLACEHOLDER_EXPR:
       {
+       tree old_list = placeholder_list;
        tree placeholder_expr;
 
-       /* If there is an object on the head of the placeholder list,
-          see if some object in it of type TYPE or a pointer to it.  For
-          further information, see tree.def.  */
-       for (placeholder_expr = placeholder_list;
-            placeholder_expr != 0;
-            placeholder_expr = TREE_CHAIN (placeholder_expr))
-         {
-           tree need_type = TYPE_MAIN_VARIANT (type);
-           tree object = 0;
-           tree old_list = placeholder_list;
-           tree elt;
-
-           /* Find the outermost reference that is of the type we want.
-              If none, see if any object has a type that is a pointer to
-              the type we want.  */
-           for (elt = TREE_PURPOSE (placeholder_expr);
-                elt != 0 && object == 0;
-                elt
-                = ((TREE_CODE (elt) == COMPOUND_EXPR
-                    || TREE_CODE (elt) == COND_EXPR)
-                   ? TREE_OPERAND (elt, 1)
-                   : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-                   ? TREE_OPERAND (elt, 0) : 0))
-             if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
-               object = elt;
-
-           for (elt = TREE_PURPOSE (placeholder_expr);
-                elt != 0 && object == 0;
-                elt
-                = ((TREE_CODE (elt) == COMPOUND_EXPR
-                    || TREE_CODE (elt) == COND_EXPR)
-                   ? TREE_OPERAND (elt, 1)
-                   : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-                      || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-                   ? TREE_OPERAND (elt, 0) : 0))
-             if (POINTER_TYPE_P (TREE_TYPE (elt))
-                 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
-                     == need_type))
-               object = build1 (INDIRECT_REF, need_type, elt);
-
-           if (object != 0)
-             {
-               /* Expand this object skipping the list entries before
-                  it was found in case it is also a PLACEHOLDER_EXPR.
-                  In that case, we want to translate it using subsequent
-                  entries.  */
-               placeholder_list = TREE_CHAIN (placeholder_expr);
-               temp = expand_expr (object, original_target, tmode,
-                                   ro_modifier);
-               placeholder_list = old_list;
-               return temp;
-             }
-         }
+       exp = find_placeholder (exp, &placeholder_expr);
+       placeholder_list = TREE_CHAIN (placeholder_expr);
+       temp = expand_expr (exp, original_target, tmode, ro_modifier);
+       placeholder_list = old_list;
+       return temp;
       }
 
       /* We can't find the object or there was a missing WITH_RECORD_EXPR.  */
@@ -6596,13 +6576,15 @@ expand_expr (exp, target, tmode, modifier)
       return const0_rtx;
 
     case EXIT_EXPR:
-      expand_exit_loop_if_false (NULL_PTR,
+      expand_exit_loop_if_false (NULL,
                                 invert_truthvalue (TREE_OPERAND (exp, 0)));
       return const0_rtx;
 
     case LABELED_BLOCK_EXPR:
       if (LABELED_BLOCK_BODY (exp))
        expand_expr_stmt (LABELED_BLOCK_BODY (exp));
+      /* Should perhaps use expand_label, but this is simpler and safer.  */
+      do_pending_stack_adjust ();
       emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
       return const0_rtx;
 
@@ -6700,13 +6682,9 @@ expand_expr (exp, target, tmode, modifier)
 
          if (modifier != EXPAND_CONST_ADDRESS
              && modifier != EXPAND_INITIALIZER
-             && modifier != EXPAND_SUM
-             && (! memory_address_p (GET_MODE (constructor),
-                                     XEXP (constructor, 0))
-                 || (flag_force_addr
-                     && GET_CODE (XEXP (constructor, 0)) != REG)))
-           constructor = change_address (constructor, VOIDmode,
-                                         XEXP (constructor, 0));
+             && modifier != EXPAND_SUM)
+           constructor = validize_mem (constructor);
+
          return constructor;
        }
       else
@@ -6812,7 +6790,8 @@ expand_expr (exp, target, tmode, modifier)
           Don't fold if this is for wide characters since it's too
           difficult to do correctly and this is a very rare case.  */
 
-       if (TREE_CODE (array) == STRING_CST
+       if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER
+           && TREE_CODE (array) == STRING_CST
            && TREE_CODE (index) == INTEGER_CST
            && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
            && GET_MODE_CLASS (mode) == MODE_INT
@@ -6825,7 +6804,8 @@ expand_expr (exp, target, tmode, modifier)
           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)
+       if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER
+           && TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
            && TREE_CODE (index) == INTEGER_CST
            && 0 > compare_tree_int (index,
                                     list_length (CONSTRUCTOR_ELTS
@@ -6844,6 +6824,8 @@ expand_expr (exp, target, tmode, modifier)
          }
 
        else if (optimize >= 1
+                && modifier != EXPAND_CONST_ADDRESS
+                && modifier != EXPAND_INITIALIZER
                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
                 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
                 && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
@@ -6862,7 +6844,7 @@ expand_expr (exp, target, tmode, modifier)
                         elem = TREE_CHAIN (elem))
                      ;
 
-                   if (elem)
+                   if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
                      return expand_expr (fold (TREE_VALUE (elem)), target,
                                          tmode, ro_modifier);
                  }
@@ -6886,11 +6868,12 @@ expand_expr (exp, target, tmode, modifier)
 
     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 (code != ARRAY_REF
+      if (code == COMPONENT_REF
          && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
          && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
        {
@@ -6951,6 +6934,7 @@ expand_expr (exp, target, tmode, modifier)
        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
                                        &mode1, &unsignedp, &volatilep,
                                        &alignment);
+       rtx orig_op0;
 
        /* If we got back the original object, something is wrong.  Perhaps
           we are evaluating an expression too early.  In any event, don't
@@ -6962,15 +6946,16 @@ expand_expr (exp, target, tmode, modifier)
           computation, since it will need a temporary and TARGET is known
           to have to do.  This occurs in unchecked conversion in Ada.  */
 
-       op0 = expand_expr (tem,
-                          (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-                           && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-                               != INTEGER_CST)
-                           ? target : NULL_RTX),
-                          VOIDmode,
-                          (modifier == EXPAND_INITIALIZER
-                           || modifier == EXPAND_CONST_ADDRESS)
-                          ? modifier : EXPAND_NORMAL);
+       orig_op0 = op0
+         = expand_expr (tem,
+                        (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
+                         && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
+                             != INTEGER_CST)
+                         ? target : NULL_RTX),
+                        VOIDmode,
+                        (modifier == EXPAND_INITIALIZER
+                         || modifier == EXPAND_CONST_ADDRESS)
+                        ? modifier : 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.  */
@@ -6988,21 +6973,32 @@ expand_expr (exp, target, tmode, modifier)
          {
            rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
 
-           /* If this object is in memory, put it into a register.
+           /* 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);
+               /* 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
+                 {
+                   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;
+                   mark_temp_addr_taken (memloc);
+                   emit_move_insn (memloc, op0);
+                   op0 = memloc;
+                 }
              }
 
            if (GET_CODE (op0) != MEM)
@@ -7027,16 +7023,15 @@ expand_expr (exp, target, tmode, modifier)
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
                && alignment == GET_MODE_ALIGNMENT (mode1))
              {
-               rtx temp = change_address (op0, mode1,
-                                          plus_constant (XEXP (op0, 0),
-                                                         (bitpos /
-                                                          BITS_PER_UNIT)));
+               rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
+
                if (GET_CODE (XEXP (temp, 0)) == REG)
                  op0 = temp;
                else
-                 op0 = change_address (op0, mode1,
-                                       force_reg (GET_MODE (XEXP (temp, 0)),
-                                                  XEXP (temp, 0)));
+                 op0 = (replace_equiv_address
+                        (op0,
+                         force_reg (GET_MODE (XEXP (temp, 0)),
+                                    XEXP (temp, 0))));
                bitpos = 0;
              }
 
@@ -7049,7 +7044,9 @@ expand_expr (exp, target, tmode, modifier)
        /* 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);
+           if (op0 == orig_op0)
+             op0 = copy_rtx (op0);
+
            MEM_VOLATILE_P (op0) = 1;
          }
 
@@ -7086,34 +7083,30 @@ expand_expr (exp, target, tmode, modifier)
           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.  */
+          storing into memory, and changing the mode to BLKmode.  */
        if (mode1 == VOIDmode
            || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-           || (modifier != EXPAND_CONST_ADDRESS
-               && modifier != EXPAND_INITIALIZER
-               && ((mode1 != BLKmode && ! direct_load[(int) mode1]
-                    && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
-                    && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
-                   /* 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)
-                       && ((TYPE_ALIGN (TREE_TYPE (tem))
-                            < GET_MODE_ALIGNMENT (mode))
-                           || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
-                   /* If the type and the field are a constant size and the
-                      size of the type isn't the same size as the bitfield,
-                      we must use bitfield operations.  */
-                   || ((bitsize >= 0
-                        && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
-                            == INTEGER_CST)
-                        && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
-                                                  bitsize)))))
-           || (modifier != EXPAND_CONST_ADDRESS
-               && modifier != EXPAND_INITIALIZER
-               && mode == BLKmode
+           || (mode1 != BLKmode && ! direct_load[(int) mode1]
+               && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
+               && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
+               && modifier != EXPAND_CONST_ADDRESS
+               && modifier != EXPAND_INITIALIZER)
+           /* 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)
+               && ((TYPE_ALIGN (TREE_TYPE (tem))
+                    < GET_MODE_ALIGNMENT (mode))
+                   || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
+           /* If the type and the field are a constant size and the
+              size of the type isn't the same size as the bitfield,
+              we must use bitfield operations.  */
+           || (bitsize >= 0
+               && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
+                   == INTEGER_CST)
+               && 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)))
@@ -7135,9 +7128,7 @@ expand_expr (exp, target, tmode, modifier)
                    || bitpos % BITS_PER_UNIT != 0)
                  abort ();
 
-               op0 = change_address (op0, VOIDmode,
-                                     plus_constant (XEXP (op0, 0),
-                                                    bitpos / BITS_PER_UNIT));
+               op0 = adjust_address (op0, VOIDmode, bitpos / BITS_PER_UNIT);
                if (target == 0)
                  target = assign_temp (type, 0, 1, 1);
 
@@ -7193,18 +7184,12 @@ expand_expr (exp, target, tmode, modifier)
        /* Get a reference to just this component.  */
        if (modifier == EXPAND_CONST_ADDRESS
            || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-         {
-           rtx new = gen_rtx_MEM (mode1,
-                                  plus_constant (XEXP (op0, 0),
-                                                 (bitpos / BITS_PER_UNIT)));
-
-           MEM_COPY_ATTRIBUTES (new, op0);
-           op0 = new;
-         }
+         op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
        else
-         op0 = change_address (op0, mode1,
-                               plus_constant (XEXP (op0, 0),
-                                              (bitpos / BITS_PER_UNIT)));
+         op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
+
+       if (op0 == orig_op0)
+         op0 = copy_rtx (op0);
 
        set_mem_attributes (op0, exp, 0);
        if (GET_CODE (XEXP (op0, 0)) == REG)
@@ -7334,16 +7319,16 @@ expand_expr (exp, target, tmode, modifier)
       }
 
     case WITH_CLEANUP_EXPR:
-      if (RTL_EXPR_RTL (exp) == 0)
+      if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
        {
-         RTL_EXPR_RTL (exp)
+         WITH_CLEANUP_EXPR_RTL (exp)
            = expand_expr (TREE_OPERAND (exp, 0), target, tmode, ro_modifier);
-         expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 2));
+         expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1));
 
          /* That's it for this cleanup.  */
-         TREE_OPERAND (exp, 2) = 0;
+         TREE_OPERAND (exp, 1) = 0;
        }
-      return RTL_EXPR_RTL (exp);
+      return WITH_CLEANUP_EXPR_RTL (exp);
 
     case CLEANUP_POINT_EXPR:
       {
@@ -7404,7 +7389,7 @@ expand_expr (exp, target, tmode, modifier)
          if (GET_CODE (target) == MEM)
            /* Store data into beginning of memory target.  */
            store_expr (TREE_OPERAND (exp, 0),
-                       change_address (target, TYPE_MODE (valtype), 0), 0);
+                       adjust_address (target, TYPE_MODE (valtype), 0), 0);
 
          else if (GET_CODE (target) == REG)
            /* Store this field into a union of the proper type.  */
@@ -7800,7 +7785,17 @@ expand_expr (exp, target, tmode, modifier)
       return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
 
     case RDIV_EXPR:
-      this_optab = flodiv_optab;
+      /* Emit a/b as a*(1/b).  Later we may manage CSE the reciprocal saving
+         expensive divide.  If not, combine will rebuild the original
+         computation.  */
+      if (flag_unsafe_math_optimizations && optimize && !optimize_size
+         && !real_onep (TREE_OPERAND (exp, 0)))
+        return expand_expr (build (MULT_EXPR, type, TREE_OPERAND (exp, 0),
+                                  build (RDIV_EXPR, type,
+                                         build_real (type, dconst1),
+                                         TREE_OPERAND (exp, 1))),
+                           target, tmode, unsignedp);
+      this_optab = sdiv_optab;
       goto binop;
 
     case TRUNC_MOD_EXPR:
@@ -8159,8 +8154,8 @@ expand_expr (exp, target, tmode, modifier)
                     || GET_CODE (original_target) == REG
                     || TREE_ADDRESSABLE (type))
 #endif
-                && ! (GET_CODE (original_target) == MEM
-                      && MEM_VOLATILE_P (original_target)))
+                && (GET_CODE (original_target) != MEM
+                    || TREE_ADDRESSABLE (type)))
          temp = original_target;
        else if (TREE_ADDRESSABLE (type))
          abort ();
@@ -8449,35 +8444,23 @@ expand_expr (exp, target, tmode, modifier)
       {
        tree lhs = TREE_OPERAND (exp, 0);
        tree rhs = TREE_OPERAND (exp, 1);
-       tree noncopied_parts = 0;
-       tree lhs_type = TREE_TYPE (lhs);
 
        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-       if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs))
-         noncopied_parts = init_noncopied_parts (stabilize_reference (lhs),
-                                                 TYPE_NONCOPIED_PARTS (lhs_type));
-       while (noncopied_parts != 0)
-         {
-           expand_assignment (TREE_VALUE (noncopied_parts),
-                              TREE_PURPOSE (noncopied_parts), 0, 0);
-           noncopied_parts = TREE_CHAIN (noncopied_parts);
-         }
        return temp;
       }
 
     case MODIFY_EXPR:
       {
        /* If lhs is complex, expand calls in rhs before computing it.
-          That's so we don't compute a pointer and save it over a call.
-          If lhs is simple, compute it first so we can give it as a
-          target if the rhs is just a call.  This avoids an extra temp and copy
-          and that prevents a partial-subsumption which makes bad code.
-          Actually we could treat component_ref's of vars like vars.  */
+          That's so we don't compute a pointer and save it over a
+          call.  If lhs is simple, compute it first so we can give it
+          as a target if the rhs is just a call.  This avoids an
+          extra temp and copy and that prevents a partial-subsumption
+          which makes bad code.  Actually we could treat
+          component_ref's of vars like vars.  */
 
        tree lhs = TREE_OPERAND (exp, 0);
        tree rhs = TREE_OPERAND (exp, 1);
-       tree noncopied_parts = 0;
-       tree lhs_type = TREE_TYPE (lhs);
 
        temp = 0;
 
@@ -8513,18 +8496,8 @@ expand_expr (exp, target, tmode, modifier)
            return const0_rtx;
          }
 
-       if (TYPE_NONCOPIED_PARTS (lhs_type) != 0
-           && ! (fixed_type_p (lhs) && fixed_type_p (rhs)))
-         noncopied_parts = save_noncopied_parts (stabilize_reference (lhs),
-                                                 TYPE_NONCOPIED_PARTS (lhs_type));
-
        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-       while (noncopied_parts != 0)
-         {
-           expand_assignment (TREE_PURPOSE (noncopied_parts),
-                              TREE_VALUE (noncopied_parts), 0, 0);
-           noncopied_parts = TREE_CHAIN (noncopied_parts);
-         }
+       
        return temp;
       }
 
@@ -8577,7 +8550,9 @@ expand_expr (exp, target, tmode, modifier)
          if (ignore)
            return op0;
 
-         op0 = protect_from_queue (op0, 0);
+         /* Pass 1 for MODIFY, so that protect_from_queue doesn't get
+            clever and returns a REG when given a MEM.  */
+         op0 = protect_from_queue (op0, 1);
 
          /* We would like the object in memory.  If it is a constant, we can
             have it be statically allocated into memory.  For a non-constant,
@@ -8798,7 +8773,12 @@ expand_expr (exp, target, tmode, modifier)
       return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
 
     case EXC_PTR_EXPR:
-      return get_exception_pointer ();
+      return get_exception_pointer (cfun);
+
+    case FDESC_EXPR:
+      /* Function descriptors are not valid except for as
+        initialization constants, and should not be expanded.  */
+      abort ();
 
     default:
       return (*lang_expand_expr) (exp, original_target, tmode, modifier);
@@ -8930,11 +8910,12 @@ expand_expr_unaligned (exp, palign)
 
     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) != ARRAY_REF
+      if (TREE_CODE (exp) == COMPONENT_REF
          && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
          && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
        {
@@ -9070,9 +9051,7 @@ expand_expr_unaligned (exp, palign)
                    || bitpos % BITS_PER_UNIT != 0)
                  abort ();
 
-               op0 = change_address (op0, VOIDmode,
-                                     plus_constant (XEXP (op0, 0),
-                                                    bitpos / BITS_PER_UNIT));
+               op0 = adjust_address (op0, VOIDmode, bitpos / BITS_PER_UNIT);
              }
            else
              {
@@ -9104,11 +9083,9 @@ expand_expr_unaligned (exp, palign)
          }
        else
          /* Get a reference to just this component.  */
-         op0 = change_address (op0, mode1,
-                               plus_constant (XEXP (op0, 0),
-                                              (bitpos / BITS_PER_UNIT)));
+         op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
 
-       MEM_ALIAS_SET (op0) = get_alias_set (exp);
+       set_mem_alias_set (op0, get_alias_set (exp));
 
        /* Adjust the alignment in case the bit position is not
           a multiple of the alignment of the inner object.  */
@@ -9347,7 +9324,7 @@ expand_increment (exp, post, ignore)
                      : copy_to_reg (XEXP (op0, 0)));
          rtx temp, result;
 
-         op0 = change_address (op0, VOIDmode, addr);
+         op0 = replace_equiv_address (op0, addr);
          temp = force_reg (GET_MODE (op0), op0);
          if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
            op1 = force_reg (mode, op1);
@@ -9506,7 +9483,8 @@ do_jump (exp, if_false_label, if_true_label)
     case NOP_EXPR:
       if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
          || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
-         || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF)
+         || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
+         || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
        goto normal;
     case CONVERT_EXPR:
       /* If we are narrowing the operand, we have to do the compare in the
@@ -9612,6 +9590,7 @@ do_jump (exp, if_false_label, if_true_label)
     case COMPONENT_REF:
     case BIT_FIELD_REF:
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
       {
        HOST_WIDE_INT bitsize, bitpos;
        int unsignedp;
@@ -9862,6 +9841,39 @@ do_jump (exp, if_false_label, if_true_label)
       }
       break;
 
+      /* Special case:
+               __builtin_expect (<test>, 0)    and
+               __builtin_expect (<test>, 1)
+
+        We need to do this here, so that <test> is not converted to a SCC
+        operation on machines that use condition code registers and COMPARE
+        like the PowerPC, and then the jump is done based on whether the SCC
+        operation produced a 1 or 0.  */
+    case CALL_EXPR:
+      /* Check for a built-in function.  */
+      if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
+       {
+         tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+         tree arglist = TREE_OPERAND (exp, 1);
+
+         if (TREE_CODE (fndecl) == FUNCTION_DECL
+             && DECL_BUILT_IN (fndecl)
+             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
+             && arglist != NULL_TREE
+             && TREE_CHAIN (arglist) != NULL_TREE)
+           {
+             rtx seq = expand_builtin_expect_jump (exp, if_false_label,
+                                                   if_true_label);
+
+             if (seq != NULL_RTX)
+               {
+                 emit_insn (seq);
+                 return;
+               }
+           }
+       }
+      /* fall through and generate the normal code.  */
+
     default:
     normal:
       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
@@ -10091,8 +10103,7 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
 
-  if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
-      || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+  if (swap_commutative_operands_p (op0, op1))
     {
       tem = op0;
       op0 = op1;
@@ -10174,8 +10185,7 @@ do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size, align,
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
 
-  if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
-      || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+  if (swap_commutative_operands_p (op0, op1))
     {
       tem = op0;
       op0 = op1;
@@ -10621,11 +10631,112 @@ do_store_flag (exp, target, mode, only_cheap)
   return target;
 }
 \f
-/* Generate a tablejump instruction (used for switch statements).  */
 
-#ifdef HAVE_tablejump
+/* Stubs in case we haven't got a casesi insn.  */
+#ifndef HAVE_casesi
+# define HAVE_casesi 0
+# define gen_casesi(a, b, c, d, e) (0)
+# define CODE_FOR_casesi CODE_FOR_nothing
+#endif
+
+/* If the machine does not have a case insn that compares the bounds,
+   this means extra overhead for dispatch tables, which raises the
+   threshold for using them.  */
+#ifndef CASE_VALUES_THRESHOLD
+#define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
+#endif /* CASE_VALUES_THRESHOLD */
+
+unsigned int
+case_values_threshold ()
+{
+  return CASE_VALUES_THRESHOLD;
+}
+
+/* Attempt to generate a casesi instruction.  Returns 1 if successful,
+   0 otherwise (i.e. if there is no casesi instruction).  */
+int
+try_casesi (index_type, index_expr, minval, range,
+           table_label, default_label)
+     tree index_type, index_expr, minval, range;
+     rtx table_label ATTRIBUTE_UNUSED;
+     rtx default_label;
+{
+  enum machine_mode index_mode = SImode;
+  int index_bits = GET_MODE_BITSIZE (index_mode);
+  rtx op1, op2, index;
+  enum machine_mode op_mode;
+
+  if (! HAVE_casesi)
+    return 0;
+
+  /* Convert the index to SImode.  */
+  if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
+    {
+      enum machine_mode omode = TYPE_MODE (index_type);
+      rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
+
+      /* We must handle the endpoints in the original mode.  */
+      index_expr = build (MINUS_EXPR, index_type,
+                         index_expr, minval);
+      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);
+      /* Now we can safely truncate.  */
+      index = convert_to_mode (index_mode, index, 0);
+    }
+  else
+    {
+      if (TYPE_MODE (index_type) != index_mode)
+       {
+         index_expr = convert (type_for_size (index_bits, 0),
+                               index_expr);
+         index_type = TREE_TYPE (index_expr);
+       }
+
+      index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+    }
+  emit_queue ();
+  index = protect_from_queue (index, 0);
+  do_pending_stack_adjust ();
+
+  op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
+  if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
+      (index, op_mode))
+    index = copy_to_mode_reg (op_mode, index);
+
+  op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
+
+  op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
+  op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
+                      op1, TREE_UNSIGNED (TREE_TYPE (minval)));
+  if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
+      (op1, op_mode))
+    op1 = copy_to_mode_reg (op_mode, op1);
+
+  op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
+
+  op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
+  op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
+                      op2, TREE_UNSIGNED (TREE_TYPE (range)));
+  if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
+      (op2, op_mode))
+    op2 = copy_to_mode_reg (op_mode, op2);
+
+  emit_jump_insn (gen_casesi (index, op1, op2,
+                             table_label, default_label));
+  return 1;
+}
+
+/* Attempt to generate a tablejump instruction; same concept.  */
+#ifndef HAVE_tablejump
+#define HAVE_tablejump 0
+#define gen_tablejump(x, y) (0)
+#endif
+
+/* Subroutine of the next function.
 
-/* INDEX is the value being switched on, with the lowest value
+   INDEX is the value being switched on, with the lowest value
    in the table already subtracted.
    MODE is its expected mode (needed if INDEX is constant).
    RANGE is the length of the jump table.
@@ -10634,7 +10745,7 @@ do_store_flag (exp, target, mode, only_cheap)
    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
    index value is out of range.  */
 
-void
+static void
 do_tablejump (index, mode, range, table_label, default_label)
      rtx index, range, table_label, default_label;
      enum machine_mode mode;
@@ -10696,4 +10807,31 @@ do_tablejump (index, mode, range, table_label, default_label)
     emit_barrier ();
 }
 
-#endif /* HAVE_tablejump  */
+int
+try_tablejump (index_type, index_expr, minval, range,
+              table_label, default_label)
+     tree index_type, index_expr, minval, range;
+     rtx table_label, default_label;
+{
+  rtx index;
+
+  if (! HAVE_tablejump)
+    return 0;
+
+  index_expr = fold (build (MINUS_EXPR, index_type,
+                           convert (index_type, index_expr),
+                           convert (index_type, minval)));
+  index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
+  emit_queue ();
+  index = protect_from_queue (index, 0);
+  do_pending_stack_adjust ();
+
+  do_tablejump (index, TYPE_MODE (index_type),
+               convert_modes (TYPE_MODE (index_type),
+                              TYPE_MODE (TREE_TYPE (range)),
+                              expand_expr (range, NULL_RTX,
+                                           VOIDmode, 0),
+                              TREE_UNSIGNED (TREE_TYPE (range))),
+               table_label, default_label);
+  return 1;
+}