tree-ssa-live.h (find_replaceable_exprs, [...]): Move prototypes to...
[platform/upstream/gcc.git] / gcc / expr.c
index 9158b9f..235cd67 100644 (file)
@@ -1,7 +1,5 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
-   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-   2012 Free Software Foundation, Inc.
+   Copyright (C) 1988-2013 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -45,13 +43,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "tm_p.h"
 #include "tree-iterator.h"
-#include "tree-flow.h"
+#include "tree-ssa.h"
 #include "target.h"
 #include "common/common-target.h"
 #include "timevar.h"
 #include "df.h"
 #include "diagnostic.h"
-#include "ssaexpand.h"
+#include "tree-outof-ssa.h"
 #include "target-globals.h"
 #include "params.h"
 
@@ -121,7 +119,7 @@ struct store_by_pieces_d
   int reverse;
 };
 
-static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
+static void move_by_pieces_1 (insn_gen_fn, machine_mode,
                              struct move_by_pieces_d *);
 static bool block_move_libcall_safe_for_call_parm (void);
 static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT);
@@ -130,19 +128,18 @@ static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
 static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
 static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
 static void store_by_pieces_1 (struct store_by_pieces_d *, unsigned int);
-static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
+static void store_by_pieces_2 (insn_gen_fn, machine_mode,
                               struct store_by_pieces_d *);
 static tree clear_storage_libcall_fn (int);
 static rtx compress_float_constant (rtx, rtx);
 static rtx get_subtarget (rtx);
 static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
                                     HOST_WIDE_INT, enum machine_mode,
-                                    tree, tree, int, alias_set_type);
+                                    tree, int, alias_set_type);
 static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
 static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT,
                        unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
-                       enum machine_mode,
-                       tree, tree, alias_set_type, bool);
+                       enum machine_mode, tree, alias_set_type, bool);
 
 static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree, const_tree);
 
@@ -154,7 +151,7 @@ static rtx do_store_flag (sepops, rtx, enum machine_mode);
 #ifdef PUSH_ROUNDING
 static void emit_single_push_insn (enum machine_mode, rtx, tree);
 #endif
-static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx);
+static void do_tablejump (rtx, enum machine_mode, rtx, rtx, rtx, int);
 static rtx const_vector_from_tree (tree);
 static void write_complex_part (rtx, rtx, bool);
 
@@ -189,12 +186,6 @@ static void write_complex_part (rtx, rtx, bool);
   (move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
    < (unsigned int) MOVE_RATIO (optimize_insn_for_speed_p ()))
 #endif
-
-/* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow.  */
-
-#ifndef SLOW_UNALIGNED_ACCESS
-#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
-#endif
 \f
 /* This is run to set up which modes can be used
    directly in memory and to initialize the block move optab.  It is run
@@ -573,7 +564,8 @@ convert_move (rtx to, rtx from, int unsignedp)
       if (!((MEM_P (from)
             && ! MEM_VOLATILE_P (from)
             && direct_load[(int) to_mode]
-            && ! mode_dependent_address_p (XEXP (from, 0)))
+            && ! mode_dependent_address_p (XEXP (from, 0),
+                                           MEM_ADDR_SPACE (from)))
            || REG_P (from)
            || GET_CODE (from) == SUBREG))
        from = force_reg (from_mode, from);
@@ -591,7 +583,8 @@ convert_move (rtx to, rtx from, int unsignedp)
       if (!((MEM_P (from)
             && ! MEM_VOLATILE_P (from)
             && direct_load[(int) to_mode]
-            && ! mode_dependent_address_p (XEXP (from, 0)))
+            && ! mode_dependent_address_p (XEXP (from, 0),
+                                           MEM_ADDR_SPACE (from)))
            || REG_P (from)
            || GET_CODE (from) == SUBREG))
        from = force_reg (from_mode, from);
@@ -845,7 +838,7 @@ widest_int_mode_for_size (unsigned int size)
    succeed.  */
 
 int
-can_move_by_pieces (unsigned HOST_WIDE_INT len,
+can_move_by_pieces (unsigned HOST_WIDE_INT len ATTRIBUTE_UNUSED,
                    unsigned int align ATTRIBUTE_UNUSED)
 {
   return MOVE_BY_PIECES_P (len, align);
@@ -964,7 +957,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
   /* First move what we can in the largest integer mode, then go to
      successively smaller modes.  */
 
-  while (max_size > 1)
+  while (max_size > 1 && data.len > 0)
     {
       enum machine_mode mode = widest_int_mode_for_size (max_size);
 
@@ -1024,7 +1017,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
 
   align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align);
 
-  while (max_size > 1)
+  while (max_size > 1 && l > 0)
     {
       enum machine_mode mode;
       enum insn_code icode;
@@ -1050,7 +1043,7 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
    to make a move insn for that mode.  DATA has all the other info.  */
 
 static void
-move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+move_by_pieces_1 (insn_gen_fn genfun, machine_mode mode,
                  struct move_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
@@ -1078,10 +1071,12 @@ move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
        emit_insn (gen_add2_insn (data->to_addr,
-                                 GEN_INT (-(HOST_WIDE_INT)size)));
+                                 gen_int_mode (-(HOST_WIDE_INT) size,
+                                               GET_MODE (data->to_addr))));
       if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
        emit_insn (gen_add2_insn (data->from_addr,
-                                 GEN_INT (-(HOST_WIDE_INT)size)));
+                                 gen_int_mode (-(HOST_WIDE_INT) size,
+                                               GET_MODE (data->from_addr))));
 
       if (data->to)
        emit_insn ((*genfun) (to1, from1));
@@ -1095,9 +1090,13 @@ move_by_pieces_1 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
        }
 
       if (HAVE_POST_INCREMENT && 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_mode (size,
+                                               GET_MODE (data->to_addr))));
       if (HAVE_POST_INCREMENT && 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_mode (size,
+                                               GET_MODE (data->from_addr))));
 
       if (! data->reverse)
        data->offset += size;
@@ -1462,11 +1461,11 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
   emit_label (top_label);
 
   tmp = convert_modes (x_addr_mode, iter_mode, iter, true);
-  x_addr = gen_rtx_PLUS (x_addr_mode, x_addr, tmp);
+  x_addr = simplify_gen_binary (PLUS, x_addr_mode, x_addr, tmp);
 
   if (x_addr_mode != y_addr_mode)
     tmp = convert_modes (y_addr_mode, iter_mode, iter, true);
-  y_addr = gen_rtx_PLUS (y_addr_mode, y_addr, tmp);
+  y_addr = simplify_gen_binary (PLUS, y_addr_mode, y_addr, tmp);
 
   x = change_address (x, QImode, x_addr);
   y = change_address (y, QImode, y_addr);
@@ -1481,7 +1480,7 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
   emit_label (cmp_label);
 
   emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
-                          true, top_label);
+                          true, top_label, REG_BR_PROB_BASE * 90 / 100);
 }
 \f
 /* Copy all or part of a value X into registers starting at REGNO.
@@ -2084,39 +2083,40 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
     emit_move_insn (orig_dst, dst);
 }
 
-/* Generate code to copy a BLKmode object of TYPE out of a
-   set of registers starting with SRCREG into TGTBLK.  If TGTBLK
-   is null, a stack temporary is created.  TGTBLK is returned.
-
-   The purpose of this routine is to handle functions that return
-   BLKmode structures in registers.  Some machines (the PA for example)
-   want to return all small structures in registers regardless of the
-   structure's alignment.  */
+/* Return a form of X that does not use a PARALLEL.  TYPE is the type
+   of the value stored in X.  */
 
 rtx
-copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
+maybe_emit_group_store (rtx x, tree type)
+{
+  enum machine_mode mode = TYPE_MODE (type);
+  gcc_checking_assert (GET_MODE (x) == VOIDmode || GET_MODE (x) == mode);
+  if (GET_CODE (x) == PARALLEL)
+    {
+      rtx result = gen_reg_rtx (mode);
+      emit_group_store (result, x, type, int_size_in_bytes (type));
+      return result;
+    }
+  return x;
+}
+
+/* Copy a BLKmode object of TYPE out of a register SRCREG into TARGET.
+
+   This is used on targets that return BLKmode values in registers.  */
+
+void
+copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
 {
   unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
   rtx src = NULL, dst = NULL;
   unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
   unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0;
+  enum machine_mode mode = GET_MODE (srcreg);
+  enum machine_mode tmode = GET_MODE (target);
   enum machine_mode copy_mode;
 
-  if (tgtblk == 0)
-    {
-      tgtblk = assign_temp (build_qualified_type (type,
-                                                 (TYPE_QUALS (type)
-                                                  | TYPE_QUAL_CONST)),
-                           1, 1);
-      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.  */
-
-  if (GET_MODE (srcreg) != BLKmode
-      && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
-    srcreg = convert_to_mode (word_mode, srcreg, TYPE_UNSIGNED (type));
+  /* BLKmode registers created in the back-end shouldn't have survived.  */
+  gcc_assert (mode != BLKmode);
 
   /* If the structure doesn't take up a whole number of words, see whether
      SRCREG is padded on the left or on the right.  If it's on the left,
@@ -2134,22 +2134,54 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
     padding_correction
       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
 
+  /* We can use a single move if we have an exact mode for the size.  */
+  else if (MEM_P (target)
+          && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))
+              || MEM_ALIGN (target) >= GET_MODE_ALIGNMENT (mode))
+          && bytes == GET_MODE_SIZE (mode))
+  {
+    emit_move_insn (adjust_address (target, mode, 0), srcreg);
+    return;
+  }
+
+  /* And if we additionally have the same mode for a register.  */
+  else if (REG_P (target)
+          && GET_MODE (target) == mode
+          && bytes == GET_MODE_SIZE (mode))
+  {
+    emit_move_insn (target, srcreg);
+    return;
+  }
+
+  /* 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 (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    {
+      srcreg = convert_to_mode (word_mode, srcreg, TYPE_UNSIGNED (type));
+      mode = word_mode;
+    }
+
   /* Copy the structure BITSIZE bits at a time.  If the target lives in
      memory, take care of not reading/writing past its end by selecting
      a copy mode suited to BITSIZE.  This should always be possible given
      how it is computed.
 
+     If the target lives in register, make sure not to select a copy mode
+     larger than the mode of the register.
+
      We could probably emit more efficient code for machines which do not use
      strict alignment, but it doesn't seem worth the effort at the current
      time.  */
 
   copy_mode = word_mode;
-  if (MEM_P (tgtblk))
+  if (MEM_P (target))
     {
       enum machine_mode mem_mode = mode_for_size (bitsize, MODE_INT, 1);
       if (mem_mode != BLKmode)
        copy_mode = mem_mode;
     }
+  else if (REG_P (target) && GET_MODE_BITSIZE (tmode) < BITS_PER_WORD)
+    copy_mode = tmode;
 
   for (bitpos = 0, xbitpos = padding_correction;
        bitpos < bytes * BITS_PER_UNIT;
@@ -2158,15 +2190,15 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
       /* We need a new source operand each time xbitpos is on a
         word boundary and when xbitpos == padding_correction
         (the first time through).  */
-      if (xbitpos % BITS_PER_WORD == 0
-         || xbitpos == padding_correction)
-       src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
-                                    GET_MODE (srcreg));
+      if (xbitpos % BITS_PER_WORD == 0 || xbitpos == padding_correction)
+       src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD, mode);
 
       /* We need a new destination operand each time bitpos is on
         a word boundary.  */
-      if (bitpos % BITS_PER_WORD == 0)
-       dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
+      if (REG_P (target) && GET_MODE_BITSIZE (tmode) < BITS_PER_WORD)
+       dst = target;
+      else if (bitpos % BITS_PER_WORD == 0)
+       dst = operand_subword (target, bitpos / BITS_PER_WORD, 1, tmode);
 
       /* Use xbitpos for the source extraction (right justified) and
         bitpos for the destination store (left justified).  */
@@ -2175,8 +2207,6 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
                                          xbitpos % BITS_PER_WORD, 1, false,
                                          NULL_RTX, copy_mode, copy_mode));
     }
-
-  return tgtblk;
 }
 
 /* Copy BLKmode value SRC into a register of mode MODE.  Return the
@@ -2415,7 +2445,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
     {
       l = len;
       max_size = STORE_MAX_PIECES + 1;
-      while (max_size > 1)
+      while (max_size > 1 && l > 0)
        {
          mode = widest_int_mode_for_size (max_size);
 
@@ -2610,7 +2640,7 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
   /* First store what we can in the largest integer mode, then go to
      successively smaller modes.  */
 
-  while (max_size > 1)
+  while (max_size > 1 && data->len > 0)
     {
       enum machine_mode mode = widest_int_mode_for_size (max_size);
 
@@ -2633,7 +2663,7 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
    to make a move insn for that mode.  DATA has all the other info.  */
 
 static void
-store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
+store_by_pieces_2 (insn_gen_fn genfun, machine_mode mode,
                   struct store_by_pieces_d *data)
 {
   unsigned int size = GET_MODE_SIZE (mode);
@@ -2652,13 +2682,16 @@ store_by_pieces_2 (rtx (*genfun) (rtx, ...), enum machine_mode mode,
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
        emit_insn (gen_add2_insn (data->to_addr,
-                                 GEN_INT (-(HOST_WIDE_INT) size)));
+                                 gen_int_mode (-(HOST_WIDE_INT) size,
+                                               GET_MODE (data->to_addr))));
 
       cst = (*data->constfun) (data->constfundata, data->offset, mode);
       emit_insn ((*genfun) (to1, cst));
 
       if (HAVE_POST_INCREMENT && 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_mode (size,
+                                               GET_MODE (data->to_addr))));
 
       if (! data->reverse)
        data->offset += size;
@@ -3108,7 +3141,7 @@ emit_move_resolve_push (enum machine_mode mode, rtx x)
   /* Do not use anti_adjust_stack, since we don't want to update
      stack_pointer_delta.  */
   temp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
-                             GEN_INT (adjust), stack_pointer_rtx,
+                             gen_int_mode (adjust, Pmode), stack_pointer_rtx,
                              0, OPTAB_LIB_WIDEN);
   if (temp != stack_pointer_rtx)
     emit_move_insn (stack_pointer_rtx, temp);
@@ -3208,11 +3241,16 @@ emit_move_complex (enum machine_mode mode, rtx x, rtx y)
   if (push_operand (x, mode))
     return emit_move_complex_push (mode, x, y);
 
-  /* See if we can coerce the target into moving both values at once.  */
-
-  /* Move floating point as parts.  */
+  /* See if we can coerce the target into moving both values at once, except
+     for floating point where we favor moving as parts if this is easy.  */
   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-      && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing)
+      && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
+      && !(REG_P (x)
+          && HARD_REGISTER_P (x)
+          && hard_regno_nregs[REGNO(x)][mode] == 1)
+      && !(REG_P (y)
+          && HARD_REGISTER_P (y)
+          && hard_regno_nregs[REGNO(y)][mode] == 1))
     try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
   else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -3432,9 +3470,13 @@ emit_move_insn_1 (rtx x, rtx y)
      fits within a HOST_WIDE_INT.  */
   if (!CONSTANT_P (y) || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
     {
-      rtx ret = emit_move_via_integer (mode, x, y, false);
+      rtx ret = emit_move_via_integer (mode, x, y, lra_in_progress);
+
       if (ret)
-       return ret;
+       {
+         if (! lra_in_progress || recog (PATTERN (ret), ret, 0) >= 0)
+           return ret;
+       }
     }
 
   return emit_move_multi_word (mode, x, y);
@@ -3610,7 +3652,8 @@ push_block (rtx size, int extra, int below)
     {
       temp = copy_to_mode_reg (Pmode, size);
       if (extra != 0)
-       temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
+       temp = expand_binop (Pmode, add_optab, temp,
+                            gen_int_mode (extra, Pmode),
                             temp, 0, OPTAB_LIB_WIDEN);
       anti_adjust_stack (temp);
     }
@@ -3878,7 +3921,7 @@ emit_single_push_insn_1 (enum machine_mode mode, rtx x, tree type)
                                    add_optab,
 #endif
                                    stack_pointer_rtx,
-                                   GEN_INT (rounded_size),
+                                   gen_int_mode (rounded_size, Pmode),
                                    NULL_RTX, 0, OPTAB_LIB_WIDEN));
 
       offset = (HOST_WIDE_INT) padding_size;
@@ -3893,18 +3936,20 @@ emit_single_push_insn_1 (enum machine_mode mode, rtx x, tree type)
           previous value.  */
        offset -= (HOST_WIDE_INT) rounded_size;
 #endif
-      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
+      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+                               gen_int_mode (offset, Pmode));
     }
   else
     {
 #ifdef STACK_GROWS_DOWNWARD
       /* ??? This seems wrong if STACK_PUSH_CODE == POST_DEC.  */
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               GEN_INT (-(HOST_WIDE_INT) rounded_size));
+                               gen_int_mode (-(HOST_WIDE_INT) rounded_size,
+                                             Pmode));
 #else
       /* ??? This seems wrong if STACK_PUSH_CODE == POST_INC.  */
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               GEN_INT (rounded_size));
+                               gen_int_mode (rounded_size, Pmode));
 #endif
       dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
     }
@@ -4092,8 +4137,8 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
                size = GEN_INT (INTVAL (size) - used);
              else
                size = expand_binop (GET_MODE (size), sub_optab, size,
-                                    GEN_INT (used), NULL_RTX, 0,
-                                    OPTAB_LIB_WIDEN);
+                                    gen_int_mode (used, GET_MODE (size)),
+                                    NULL_RTX, 0, OPTAB_LIB_WIDEN);
            }
 
          /* Get the address of the stack space.
@@ -4440,7 +4485,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
       binop = code == BIT_IOR_EXPR ? ior_optab : xor_optab;
       if (bitpos + bitsize != str_bitsize)
        {
-         rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize) - 1);
+         rtx mask = gen_int_mode (((unsigned HOST_WIDE_INT) 1 << bitsize) - 1,
+                                  str_mode);
          value = expand_and (str_mode, value, mask, NULL_RTX);
        }
       value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
@@ -4544,21 +4590,48 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
   *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
 }
 
+/* Returns true if ADDR is an ADDR_EXPR of a DECL that does not reside
+   in memory and has non-BLKmode.  DECL_RTL must not be a MEM; if
+   DECL_RTL was not set yet, return NORTL.  */
+
+static inline bool
+addr_expr_of_non_mem_decl_p_1 (tree addr, bool nortl)
+{
+  if (TREE_CODE (addr) != ADDR_EXPR)
+    return false;
+
+  tree base = TREE_OPERAND (addr, 0);
+
+  if (!DECL_P (base)
+      || TREE_ADDRESSABLE (base)
+      || DECL_MODE (base) == BLKmode)
+    return false;
+
+  if (!DECL_RTL_SET_P (base))
+    return nortl;
+
+  return (!MEM_P (DECL_RTL (base)));
+}
+
 /* Returns true if the MEM_REF REF refers to an object that does not
    reside in memory and has non-BLKmode.  */
 
-static bool
+static inline bool
 mem_ref_refers_to_non_mem_p (tree ref)
 {
   tree base = TREE_OPERAND (ref, 0);
-  if (TREE_CODE (base) != ADDR_EXPR)
-    return false;
-  base = TREE_OPERAND (base, 0);
-  return (DECL_P (base)
-         && !TREE_ADDRESSABLE (base)
-         && DECL_MODE (base) != BLKmode
-         && DECL_RTL_SET_P (base)
-         && !MEM_P (DECL_RTL (base)));
+  return addr_expr_of_non_mem_decl_p_1 (base, false);
+}
+
+/* Return TRUE iff OP is an ADDR_EXPR of a DECL that's not
+   addressable.  This is very much like mem_ref_refers_to_non_mem_p,
+   but instead of the MEM_REF, it takes its base, and it doesn't
+   assume a DECL is in memory just because its RTL is not set yet.  */
+
+bool
+addr_expr_of_non_mem_decl_p (tree op)
+{
+  return addr_expr_of_non_mem_decl_p_1 (op, true);
 }
 
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
@@ -4636,8 +4709,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
       int unsignedp;
       int volatilep = 0;
       tree tem;
-      bool misalignp;
-      rtx mem = NULL_RTX;
 
       push_temp_slots ();
       tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
@@ -4647,40 +4718,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
          && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
        get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
 
-      /* If we are going to use store_bit_field and extract_bit_field,
-        make sure to_rtx will be safe for multiple use.  */
-      mode = TYPE_MODE (TREE_TYPE (tem));
-      if (TREE_CODE (tem) == MEM_REF
-         && mode != BLKmode
-         && ((align = get_object_alignment (tem))
-             < GET_MODE_ALIGNMENT (mode))
-         && ((icode = optab_handler (movmisalign_optab, mode))
-             != CODE_FOR_nothing))
-       {
-         struct expand_operand ops[2];
-
-         misalignp = true;
-         to_rtx = gen_reg_rtx (mode);
-         mem = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
-
-         /* If the misaligned store doesn't overwrite all bits, perform
-            rmw cycle on MEM.  */
-         if (bitsize != GET_MODE_BITSIZE (mode))
-           {
-             create_input_operand (&ops[0], to_rtx, mode);
-             create_fixed_operand (&ops[1], mem);
-             /* The movmisalign<mode> pattern cannot fail, else the assignment
-                would silently be omitted.  */
-             expand_insn (icode, 2, ops);
-
-             mem = copy_rtx (mem);
-           }
-       }
-      else
-       {
-         misalignp = false;
-         to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
-       }
+      to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
       /* If the bitfield is volatile, we want to access it in the
         field's mode, not the computed mode.
@@ -4758,15 +4796,14 @@ expand_assignment (tree to, tree from, bool nontemporal)
          else if (bitpos + bitsize <= mode_bitsize / 2)
            result = store_field (XEXP (to_rtx, 0), bitsize, bitpos,
                                  bitregion_start, bitregion_end,
-                                 mode1, from, TREE_TYPE (tem),
+                                 mode1, from,
                                  get_alias_set (to), nontemporal);
          else if (bitpos >= mode_bitsize / 2)
            result = store_field (XEXP (to_rtx, 1), bitsize,
                                  bitpos - mode_bitsize / 2,
                                  bitregion_start, bitregion_end,
                                  mode1, from,
-                                 TREE_TYPE (tem), get_alias_set (to),
-                                 nontemporal);
+                                 get_alias_set (to), nontemporal);
          else if (bitpos == 0 && bitsize == mode_bitsize)
            {
              rtx from_rtx;
@@ -4787,8 +4824,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
              result = store_field (temp, bitsize, bitpos,
                                    bitregion_start, bitregion_end,
                                    mode1, from,
-                                   TREE_TYPE (tem), get_alias_set (to),
-                                   nontemporal);
+                                   get_alias_set (to), nontemporal);
              emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp, false));
              emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true));
            }
@@ -4800,15 +4836,9 @@ expand_assignment (tree to, tree from, bool nontemporal)
              /* If the field is at offset zero, we could have been given the
                 DECL_RTX of the parent struct.  Don't munge it.  */
              to_rtx = shallow_copy_rtx (to_rtx);
-
              set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
-
-             /* Deal with volatile and readonly fields.  The former is only
-                done for MEM.  Also set MEM_KEEP_ALIAS_SET_P if needed.  */
              if (volatilep)
                MEM_VOLATILE_P (to_rtx) = 1;
-             if (component_uses_parent_alias_set (to))
-               MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
            }
 
          if (optimize_bitfield_assignment_op (bitsize, bitpos,
@@ -4820,19 +4850,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
            result = store_field (to_rtx, bitsize, bitpos,
                                  bitregion_start, bitregion_end,
                                  mode1, from,
-                                 TREE_TYPE (tem), get_alias_set (to),
-                                 nontemporal);
-       }
-
-      if (misalignp)
-       {
-         struct expand_operand ops[2];
-
-         create_fixed_operand (&ops[0], mem);
-         create_input_operand (&ops[1], to_rtx, mode);
-         /* The movmisalign<mode> pattern cannot fail, else the assignment
-            would silently be omitted.  */
-         expand_insn (icode, 2, ops);
+                                 get_alias_set (to), nontemporal);
        }
 
       if (result)
@@ -4881,7 +4899,13 @@ expand_assignment (tree to, tree from, bool nontemporal)
        emit_group_store (to_rtx, value, TREE_TYPE (from),
                          int_size_in_bytes (TREE_TYPE (from)));
       else if (GET_MODE (to_rtx) == BLKmode)
-       emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
+       {
+         /* Handle calls that return BLKmode values in registers.  */
+         if (REG_P (value))
+           copy_blkmode_from_reg (to_rtx, value, TREE_TYPE (from));
+         else
+           emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
+       }
       else
        {
          if (POINTER_TYPE_P (TREE_TYPE (to)))
@@ -4906,7 +4930,12 @@ expand_assignment (tree to, tree from, bool nontemporal)
       rtx temp;
 
       push_temp_slots ();
-      if (REG_P (to_rtx) && TYPE_MODE (TREE_TYPE (from)) == BLKmode)
+
+      /* If the source is itself a return value, it still is in a pseudo at
+        this point so we can move it back to the return register directly.  */
+      if (REG_P (to_rtx)
+         && TYPE_MODE (TREE_TYPE (from)) == BLKmode
+         && TREE_CODE (from) != CALL_EXPR)
        temp = copy_blkmode_to_reg (GET_MODE (to_rtx), from);
       else
        temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL);
@@ -5005,7 +5034,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
 {
   rtx temp;
   rtx alt_rtl = NULL_RTX;
-  location_t loc = EXPR_LOCATION (exp);
+  location_t loc = curr_insn_location ();
 
   if (VOID_TYPE_P (TREE_TYPE (exp)))
     {
@@ -5223,21 +5252,20 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
         supposed to be bit-copied or bit-initialized.  */
       && expr_size (exp) != const0_rtx)
     {
-      if (GET_MODE (temp) != GET_MODE (target)
-         && GET_MODE (temp) != VOIDmode)
+      if (GET_MODE (temp) != GET_MODE (target) && GET_MODE (temp) != VOIDmode)
        {
-         int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
-         if (GET_MODE (target) == BLKmode
-             && GET_MODE (temp) == BLKmode)
-           emit_block_move (target, temp, expr_size (exp),
-                            (call_param_p
-                             ? BLOCK_OP_CALL_PARM
-                             : BLOCK_OP_NORMAL));
-         else if (GET_MODE (target) == BLKmode)
-           store_bit_field (target, INTVAL (expr_size (exp)) * BITS_PER_UNIT,
-                            0, 0, 0, GET_MODE (temp), temp);
+         if (GET_MODE (target) == BLKmode)
+           {
+             /* Handle calls that return BLKmode values in registers.  */
+             if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
+               copy_blkmode_from_reg (target, temp, TREE_TYPE (exp));
+             else
+               store_bit_field (target,
+                                INTVAL (expr_size (exp)) * BITS_PER_UNIT,
+                                0, 0, 0, GET_MODE (temp), temp);
+           }
          else
-           convert_move (target, temp, unsignedp);
+           convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp)));
        }
 
       else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
@@ -5489,7 +5517,7 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
     {
       HOST_WIDE_INT mult = 1;
 
-      if (TREE_CODE (purpose) == RANGE_EXPR)
+      if (purpose && TREE_CODE (purpose) == RANGE_EXPR)
        {
          tree lo_index = TREE_OPERAND (purpose, 0);
          tree hi_index = TREE_OPERAND (purpose, 1);
@@ -5663,7 +5691,6 @@ all_zeros_p (const_tree exp)
 \f
 /* Helper function for store_constructor.
    TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
-   TYPE is the type of the CONSTRUCTOR, not the element type.
    CLEARED is as for store_constructor.
    ALIAS_SET is the alias set to use for any stores.
 
@@ -5675,8 +5702,7 @@ all_zeros_p (const_tree exp)
 static void
 store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
                         HOST_WIDE_INT bitpos, enum machine_mode mode,
-                        tree exp, tree type, int cleared,
-                        alias_set_type alias_set)
+                        tree exp, int cleared, alias_set_type alias_set)
 {
   if (TREE_CODE (exp) == CONSTRUCTOR
       /* We can only call store_constructor recursively if the size and
@@ -5708,8 +5734,7 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
       store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
     }
   else
-    store_field (target, bitsize, bitpos, 0, 0, mode, exp, type, alias_set,
-                false);
+    store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false);
 }
 
 /* Store the value of constructor EXP into the rtx TARGET.
@@ -5767,7 +5792,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
           register whose mode size isn't equal to SIZE since
           clear_storage can't handle this case.  */
        else if (size > 0
-                && (((int)VEC_length (constructor_elt, CONSTRUCTOR_ELTS (exp))
+                && (((int)vec_safe_length (CONSTRUCTOR_ELTS (exp))
                      != fields_length (type))
                     || mostly_zeros_p (exp))
                 && (!REG_P (target)
@@ -5880,7 +5905,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
              }
 
            store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                    value, type, cleared,
+                                    value, cleared,
                                     get_alias_set (TREE_TYPE (field)));
          }
        break;
@@ -6035,7 +6060,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                          }
 
                        store_constructor_field
-                         (target, bitsize, bitpos, mode, value, type, cleared,
+                         (target, bitsize, bitpos, mode, value, cleared,
                           get_alias_set (elttype));
                      }
                  }
@@ -6139,7 +6164,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                    MEM_KEEP_ALIAS_SET_P (target) = 1;
                  }
                store_constructor_field (target, bitsize, bitpos, mode, value,
-                                        type, cleared, get_alias_set (elttype));
+                                        cleared, get_alias_set (elttype));
              }
          }
        break;
@@ -6229,7 +6254,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
         /* Store each element of the constructor into the corresponding
           element of TARGET, determined by counting the elements.  */
        for (idx = 0, i = 0;
-            VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce);
+            vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
             idx++, i += bitsize / elt_size)
          {
            HOST_WIDE_INT eltpos;
@@ -6259,9 +6284,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                  ? TYPE_MODE (TREE_TYPE (value))
                  : eltmode;
                bitpos = eltpos * elt_size;
-               store_constructor_field (target, bitsize, bitpos,
-                                        value_mode, value, type,
-                                        cleared, alias);
+               store_constructor_field (target, bitsize, bitpos, value_mode,
+                                        value, cleared, alias);
              }
          }
 
@@ -6290,8 +6314,6 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
    Always return const0_rtx unless we have something particular to
    return.
 
-   TYPE is the type of the underlying object,
-
    ALIAS_SET is the alias set for the destination.  This value will
    (in general) be different from that for TARGET, since TARGET is a
    reference to the containing structure.
@@ -6302,7 +6324,7 @@ static rtx
 store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
             unsigned HOST_WIDE_INT bitregion_start,
             unsigned HOST_WIDE_INT bitregion_end,
-            enum machine_mode mode, tree exp, tree type,
+            enum machine_mode mode, tree exp,
             alias_set_type alias_set, bool nontemporal)
 {
   if (TREE_CODE (exp) == ERROR_MARK)
@@ -6313,37 +6335,6 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
   if (bitsize == 0)
     return expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-  /* If we are storing into an unaligned field of an aligned union that is
-     in a register, we may have the mode of TARGET being an integer mode but
-     MODE == BLKmode.  In that case, get an aligned object whose size and
-     alignment are the same as TARGET and store TARGET into it (we can avoid
-     the store if the field being stored is the entire width of TARGET).  Then
-     call ourselves recursively to store the field into a BLKmode version of
-     that object.  Finally, load from the object into TARGET.  This is not
-     very efficient in general, but should only be slightly more expensive
-     than the otherwise-required unaligned accesses.  Perhaps this can be
-     cleaned up later.  It's tempting to make OBJECT readonly, but it's set
-     twice, once with emit_move_insn and once via store_field.  */
-
-  if (mode == BLKmode
-      && (REG_P (target) || GET_CODE (target) == SUBREG))
-    {
-      rtx object = assign_temp (type, 1, 1);
-      rtx blk_object = adjust_address (object, BLKmode, 0);
-
-      if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
-       emit_move_insn (object, target);
-
-      store_field (blk_object, bitsize, bitpos,
-                  bitregion_start, bitregion_end,
-                  mode, exp, type, MEM_ALIAS_SET (blk_object), nontemporal);
-
-      emit_move_insn (target, object);
-
-      /* We want to return the BLKmode version of the data.  */
-      return blk_object;
-    }
-
   if (GET_CODE (target) == CONCAT)
     {
       /* We're storing into a struct containing a single __complex.  */
@@ -6454,26 +6445,35 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
         The Irix 6 ABI has examples of this.  */
       if (GET_CODE (temp) == PARALLEL)
        {
+         HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
          rtx temp_target;
-
-         /* We are not supposed to have a true bitfield in this case.  */
-         gcc_assert (bitsize == GET_MODE_BITSIZE (mode));
-
-         /* If we don't store at bit 0, we need an intermediate pseudo
-            since emit_group_store only stores at bit 0.  */
-         if (bitpos != 0)
-           temp_target = gen_reg_rtx (mode);
-         else
-           temp_target = target;
-
-         emit_group_store (temp_target, temp, TREE_TYPE (exp),
-                           int_size_in_bytes (TREE_TYPE (exp)));
-
-         if (temp_target == target)
-           return const0_rtx;
-
+         if (mode == BLKmode)
+           mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+         temp_target = gen_reg_rtx (mode);
+         emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
          temp = temp_target;
        }
+      else if (mode == BLKmode)
+       {
+         /* Handle calls that return BLKmode values in registers.  */
+         if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR)
+           {
+             rtx temp_target = gen_reg_rtx (GET_MODE (temp));
+             copy_blkmode_from_reg (temp_target, temp, TREE_TYPE (exp));
+             temp = temp_target;
+           }
+         else
+           {
+             HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+             rtx temp_target;
+             mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+             temp_target = gen_reg_rtx (mode);
+             temp_target
+               = extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
+                                    false, temp_target, mode, mode);
+             temp = temp_target;
+           }
+       }
 
       /* Store the value in the bitfield.  */
       store_bit_field (target, bitsize, bitpos,
@@ -6672,9 +6672,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
              if (!integer_zerop (off))
                {
                  double_int boff, coff = mem_ref_offset (exp);
-                 boff = coff.alshift (BITS_PER_UNIT == 8
-                                      ? 3 : exact_log2 (BITS_PER_UNIT),
-                                      HOST_BITS_PER_DOUBLE_INT);
+                 boff = coff.lshift (BITS_PER_UNIT == 8
+                                     ? 3 : exact_log2 (BITS_PER_UNIT));
                  bit_offset += boff;
                }
              exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
@@ -6700,8 +6699,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
     {
       double_int tem = tree_to_double_int (offset);
       tem = tem.sext (TYPE_PRECISION (sizetype));
-      tem = tem.alshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT),
-                        HOST_BITS_PER_DOUBLE_INT);
+      tem = tem.lshift (BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT));
       tem += bit_offset;
       if (tem.fits_shwi ())
        {
@@ -7144,7 +7142,7 @@ safe_from_p (const_rtx x, tree exp, int top_p)
          constructor_elt *ce;
          unsigned HOST_WIDE_INT idx;
 
-         FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce)
+         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (exp), idx, ce)
            if ((ce->index != NULL_TREE && !safe_from_p (x, ce->index, 0))
                || !safe_from_p (x, ce->value, 0))
              return 0;
@@ -7531,6 +7529,15 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
       inner = TREE_OPERAND (exp, 0);
       break;
 
+    case COMPOUND_LITERAL_EXPR:
+      /* Allow COMPOUND_LITERAL_EXPR in initializers, if e.g.
+        rtl_for_decl_init is called on DECL_INITIAL with
+        COMPOUNT_LITERAL_EXPRs in it, they aren't gimplified.  */
+      if (modifier == EXPAND_INITIALIZER
+         && COMPOUND_LITERAL_EXPR_DECL (exp))
+       return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp),
+                                       target, tmode, modifier, as);
+      /* FALLTHRU */
     default:
       /* If the object is a DECL, then expand it for its rtl.  Don't bypass
         expand_expr, as that can have various side effects; LABEL_DECLs for
@@ -7828,31 +7835,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
       return ret ? ret : const0_rtx;
     }
 
-  /* If this is an expression of some kind and it has an associated line
-     number, then emit the line number before expanding the expression.
-
-     We need to save and restore the file and line information so that
-     errors discovered during expansion are emitted with the right
-     information.  It would be better of the diagnostic routines
-     used the file/line information embedded in the tree nodes rather
-     than globals.  */
-  if (cfun && EXPR_HAS_LOCATION (exp))
-    {
-      location_t saved_location = input_location;
-      location_t saved_curr_loc = curr_insn_location ();
-      input_location = EXPR_LOCATION (exp);
-      set_curr_insn_location (input_location);
-
-      ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
-
-      input_location = saved_location;
-      set_curr_insn_location (saved_curr_loc);
-    }
-  else
-    {
-      ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
-    }
-
+  ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
   return ret;
 }
 
@@ -7876,16 +7859,19 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
   tree type = TREE_TYPE (treeop1);
   int unsignedp = TYPE_UNSIGNED (type);
   enum machine_mode mode = TYPE_MODE (type);
-
-  temp = assign_temp (type, 0, 1);
+  enum machine_mode orig_mode = mode;
 
   /* If we cannot do a conditional move on the mode, try doing it
      with the promoted mode. */
   if (!can_conditionally_move_p (mode))
-    mode = promote_mode (type, mode, &unsignedp);
-
-  if (!can_conditionally_move_p (mode))
-    return NULL_RTX;
+    {
+      mode = promote_mode (type, mode, &unsignedp);
+      if (!can_conditionally_move_p (mode))
+       return NULL_RTX;
+      temp = assign_temp (type, 0, 0); /* Use promoted mode for temp.  */
+    }
+  else
+    temp = assign_temp (type, 0, 1);
 
   start_sequence ();
   expand_operands (treeop1, treeop2,
@@ -7939,7 +7925,7 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
       rtx seq = get_insns ();
       end_sequence ();
       emit_insn (seq);
-      return temp;
+      return convert_modes (orig_mode, mode, temp, 0);
     }
 
   /* Otherwise discard the sequence and fall back to code with
@@ -8055,8 +8041,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                                                    (treeop0))
                                 * BITS_PER_UNIT),
                                (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
-                          0, 0, 0, TYPE_MODE (valtype), treeop0,
-                          type, 0, false);
+                          0, 0, 0, TYPE_MODE (valtype), treeop0, 0, false);
            }
 
          /* Return the entire union.  */
@@ -8373,6 +8358,15 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
              else
                expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0,
                                 EXPAND_NORMAL);
+             /* op0 and op1 might still be constant, despite the above
+                != INTEGER_CST check.  Handle it.  */
+             if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+               {
+                 op0 = convert_modes (innermode, mode, op0, true);
+                 op1 = convert_modes (innermode, mode, op1, false);
+                 return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
+                                                       target, unsignedp));
+               }
              goto binop3;
            }
        }
@@ -8395,6 +8389,19 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                {
                  expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
                                   EXPAND_NORMAL);
+                 /* op0 and op1 might still be constant, despite the above
+                    != INTEGER_CST check.  Handle it.  */
+                 if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+                   {
+                    widen_mult_const:
+                     op0 = convert_modes (innermode, mode, op0, zextend_p);
+                     op1
+                       = convert_modes (innermode, mode, op1,
+                                        TYPE_UNSIGNED (TREE_TYPE (treeop1)));
+                     return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
+                                                           target,
+                                                           unsignedp));
+                   }
                  temp = expand_widening_mult (mode, op0, op1, target,
                                               unsignedp, this_optab);
                  return REDUCE_BIT_FIELD (temp);
@@ -8407,9 +8414,14 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                  op0 = expand_normal (treeop0);
                  if (TREE_CODE (treeop1) == INTEGER_CST)
                    op1 = convert_modes (innermode, mode,
-                                        expand_normal (treeop1), unsignedp);
+                                        expand_normal (treeop1),
+                                        TYPE_UNSIGNED (TREE_TYPE (treeop1)));
                  else
                    op1 = expand_normal (treeop1);
+                 /* op0 and op1 might still be constant, despite the above
+                    != INTEGER_CST check.  Handle it.  */
+                 if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+                   goto widen_mult_const;
                  temp = expand_binop (mode, other_optab, op0, op1, target,
                                       unsignedp, OPTAB_LIB_WIDEN);
                  hipart = gen_highpart (innermode, temp);
@@ -8851,6 +8863,54 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
       if (!target)
        target = gen_reg_rtx (TYPE_MODE (type));
+      else
+       /* If target overlaps with op1, then either we need to force
+          op1 into a pseudo (if target also overlaps with op0),
+          or write the complex parts in reverse order.  */
+       switch (GET_CODE (target))
+         {
+         case CONCAT:
+           if (reg_overlap_mentioned_p (XEXP (target, 0), op1))
+             {
+               if (reg_overlap_mentioned_p (XEXP (target, 1), op0))
+                 {
+                 complex_expr_force_op1:
+                   temp = gen_reg_rtx (GET_MODE_INNER (GET_MODE (target)));
+                   emit_move_insn (temp, op1);
+                   op1 = temp;
+                   break;
+                 }
+             complex_expr_swap_order:
+               /* Move the imaginary (op1) and real (op0) parts to their
+                  location.  */
+               write_complex_part (target, op1, true);
+               write_complex_part (target, op0, false);
+
+               return target;
+             }
+           break;
+         case MEM:
+           temp = adjust_address_nv (target,
+                                     GET_MODE_INNER (GET_MODE (target)), 0);
+           if (reg_overlap_mentioned_p (temp, op1))
+             {
+               enum machine_mode imode = GET_MODE_INNER (GET_MODE (target));
+               temp = adjust_address_nv (target, imode,
+                                         GET_MODE_SIZE (imode));
+               if (reg_overlap_mentioned_p (temp, op0))
+                 goto complex_expr_force_op1;
+               goto complex_expr_swap_order;
+             }
+           break;
+         default:
+           if (reg_overlap_mentioned_p (target, op1))
+             {
+               if (reg_overlap_mentioned_p (target, op0))
+                 goto complex_expr_force_op1;
+               goto complex_expr_swap_order;
+             }
+           break;
+         }
 
       /* Move the real (op0) and imaginary (op1) parts to their location.  */
       write_complex_part (target, op0, false);
@@ -9066,6 +9126,24 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 }
 #undef REDUCE_BIT_FIELD
 
+
+/* Return TRUE if expression STMT is suitable for replacement.  
+   Never consider memory loads as replaceable, because those don't ever lead 
+   into constant expressions.  */
+
+static bool
+stmt_is_replaceable_p (gimple stmt)
+{
+  if (ssa_is_replaceable_p (stmt))
+    {
+      /* Don't move around loads.  */
+      if (!gimple_assign_single_p (stmt)
+         || is_gimple_val (gimple_assign_rhs1 (stmt)))
+       return true;
+    }
+  return false;
+}
+
 rtx
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    enum expand_modifier modifier, rtx *alt_rtl)
@@ -9209,8 +9287,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        g = SSA_NAME_DEF_STMT (exp);
       if (g)
        {
-         rtx r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
-                                   tmode, modifier, NULL);
+         rtx r;
+         location_t saved_loc = curr_insn_location ();
+
+         set_curr_insn_location (gimple_location (g));
+         r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
+                               tmode, modifier, NULL);
+         set_curr_insn_location (saved_loc);
          if (REG_P (r) && !REG_EXPR (r))
            set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r);
          return r;
@@ -9256,7 +9339,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Variables inherited from containing functions should have
         been lowered by this point.  */
       context = decl_function_context (exp);
-      gcc_assert (!context
+      gcc_assert (SCOPE_FILE_SCOPE_P (context)
                  || context == current_function_decl
                  || TREE_STATIC (exp)
                  || DECL_EXTERNAL (exp)
@@ -9356,9 +9439,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          }
        if (!tmp)
          {
-           VEC(constructor_elt,gc) *v;
+           vec<constructor_elt, va_gc> *v;
            unsigned i;
-           v = VEC_alloc (constructor_elt, gc, VECTOR_CST_NELTS (exp));
+           vec_alloc (v, VECTOR_CST_NELTS (exp));
            for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
              CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, VECTOR_CST_ELT (exp, i));
            tmp = build_constructor (type, v);
@@ -9440,7 +9523,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
               with non-BLKmode values.  */
            gcc_assert (GET_MODE (ret) != BLKmode);
 
-           val = build_decl (EXPR_LOCATION (exp),
+           val = build_decl (curr_insn_location (),
                              VAR_DECL, NULL, TREE_TYPE (exp));
            DECL_ARTIFICIAL (val) = 1;
            DECL_IGNORED_P (val) = 1;
@@ -9489,6 +9572,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        set_mem_addr_space (temp, as);
        align = get_object_alignment (exp);
        if (modifier != EXPAND_WRITE
+           && modifier != EXPAND_MEMORY
            && mode != BLKmode
            && align < GET_MODE_ALIGNMENT (mode)
            /* If the target does not have special handling for unaligned
@@ -9504,7 +9588,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            create_output_operand (&ops[0], NULL_RTX, mode);
            create_fixed_operand (&ops[1], temp);
            expand_insn (icode, 2, ops);
-           return ops[0].value;
+           temp = ops[0].value;
          }
        return temp;
       }
@@ -9523,34 +9607,25 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        if (mem_ref_refers_to_non_mem_p (exp))
          {
            HOST_WIDE_INT offset = mem_ref_offset (exp).low;
-           tree bit_offset;
-           tree bftype;
            base = TREE_OPERAND (base, 0);
            if (offset == 0
-               && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+               && host_integerp (TYPE_SIZE (type), 1)
                && (GET_MODE_BITSIZE (DECL_MODE (base))
-                   == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
-             return expand_expr (build1 (VIEW_CONVERT_EXPR,
-                                         TREE_TYPE (exp), base),
+                   == TREE_INT_CST_LOW (TYPE_SIZE (type))))
+             return expand_expr (build1 (VIEW_CONVERT_EXPR, type, base),
                                  target, tmode, modifier);
-           bit_offset = bitsize_int (offset * BITS_PER_UNIT);
-           bftype = TREE_TYPE (base);
-           if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
-             bftype = TREE_TYPE (exp);
-           else
+           if (TYPE_MODE (type) == BLKmode)
              {
                temp = assign_stack_temp (DECL_MODE (base),
                                          GET_MODE_SIZE (DECL_MODE (base)));
                store_expr (base, temp, 0, false);
                temp = adjust_address (temp, BLKmode, offset);
-               set_mem_size (temp, int_size_in_bytes (TREE_TYPE (exp)));
+               set_mem_size (temp, int_size_in_bytes (type));
                return temp;
              }
-           return expand_expr (build3 (BIT_FIELD_REF, bftype,
-                                       base,
-                                       TYPE_SIZE (TREE_TYPE (exp)),
-                                       bit_offset),
-                               target, tmode, modifier);
+           exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type),
+                         bitsize_int (offset * BITS_PER_UNIT));
+           return expand_expr (exp, target, tmode, modifier);
          }
        address_mode = targetm.addr_space.address_mode (as);
        base = TREE_OPERAND (exp, 0);
@@ -9577,6 +9652,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        if (TREE_THIS_VOLATILE (exp))
          MEM_VOLATILE_P (temp) = 1;
        if (modifier != EXPAND_WRITE
+           && modifier != EXPAND_MEMORY
            && mode != BLKmode
            && align < GET_MODE_ALIGNMENT (mode))
          {
@@ -9591,7 +9667,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                create_output_operand (&ops[0], NULL_RTX, mode);
                create_fixed_operand (&ops[1], temp);
                expand_insn (icode, 2, ops);
-               return ops[0].value;
+               temp = ops[0].value;
              }
            else if (SLOW_UNALIGNED_ACCESS (mode, align))
              temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
@@ -9608,6 +9684,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       {
        tree array = treeop0;
        tree index = treeop1;
+       tree init;
 
        /* Fold an expression like: "foo"[2].
           This is not done in fold so it won't happen inside &.
@@ -9654,76 +9731,71 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                 && modifier != EXPAND_INITIALIZER
                 && modifier != EXPAND_MEMORY
                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
-                && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
-                && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK
-                && const_value_known_p (array))
+                && TREE_CODE (index) == INTEGER_CST
+                && (TREE_CODE (array) == VAR_DECL
+                    || TREE_CODE (array) == CONST_DECL)
+                && (init = ctor_for_folding (array)) != error_mark_node)
          {
-           if (TREE_CODE (index) == INTEGER_CST)
+           if (TREE_CODE (init) == CONSTRUCTOR)
              {
-               tree init = DECL_INITIAL (array);
-
-               if (TREE_CODE (init) == CONSTRUCTOR)
-                 {
-                   unsigned HOST_WIDE_INT ix;
-                   tree field, value;
+               unsigned HOST_WIDE_INT ix;
+               tree field, value;
+
+               FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
+                                         field, value)
+                 if (tree_int_cst_equal (field, index))
+                   {
+                     if (TREE_SIDE_EFFECTS (value))
+                       break;
 
-                   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
-                                             field, value)
-                     if (tree_int_cst_equal (field, index))
+                     if (TREE_CODE (value) == CONSTRUCTOR)
                        {
-                         if (TREE_SIDE_EFFECTS (value))
+                         /* If VALUE is a CONSTRUCTOR, this
+                            optimization is only useful if
+                            this doesn't store the CONSTRUCTOR
+                            into memory.  If it does, it is more
+                            efficient to just load the data from
+                            the array directly.  */
+                         rtx ret = expand_constructor (value, target,
+                                                       modifier, true);
+                         if (ret == NULL_RTX)
                            break;
-
-                         if (TREE_CODE (value) == CONSTRUCTOR)
-                           {
-                             /* If VALUE is a CONSTRUCTOR, this
-                                optimization is only useful if
-                                this doesn't store the CONSTRUCTOR
-                                into memory.  If it does, it is more
-                                efficient to just load the data from
-                                the array directly.  */
-                             rtx ret = expand_constructor (value, target,
-                                                           modifier, true);
-                             if (ret == NULL_RTX)
-                               break;
-                           }
-
-                         return expand_expr (fold (value), target, tmode,
-                                             modifier);
                        }
-                 }
-               else if(TREE_CODE (init) == STRING_CST)
-                 {
-                   tree index1 = index;
-                   tree low_bound = array_ref_low_bound (exp);
-                   index1 = fold_convert_loc (loc, sizetype,
-                                              treeop1);
 
-                   /* Optimize the special-case of a zero lower bound.
-
-                      We convert the low_bound to sizetype to avoid some problems
-                      with constant folding.  (E.g. suppose the lower bound is 1,
-                      and its mode is QI.  Without the conversion,l (ARRAY
-                      +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
-                      +INDEX), which becomes (ARRAY+255+INDEX).  Opps!)  */
-
-                   if (! integer_zerop (low_bound))
-                     index1 = size_diffop_loc (loc, index1,
+                     return
+                       expand_expr (fold (value), target, tmode, modifier);
+                   }
+             }
+           else if (TREE_CODE (init) == STRING_CST)
+             {
+               tree low_bound = array_ref_low_bound (exp);
+               tree index1 = fold_convert_loc (loc, sizetype, treeop1);
+
+               /* Optimize the special case of a zero lower bound.
+
+                  We convert the lower bound to sizetype to avoid problems
+                  with constant folding.  E.g. suppose the lower bound is
+                  1 and its mode is QI.  Without the conversion
+                     (ARRAY + (INDEX - (unsigned char)1))
+                  becomes
+                     (ARRAY + (-(unsigned char)1) + INDEX)
+                  which becomes
+                     (ARRAY + 255 + INDEX).  Oops!  */
+               if (!integer_zerop (low_bound))
+                 index1 = size_diffop_loc (loc, index1,
                                            fold_convert_loc (loc, sizetype,
                                                              low_bound));
 
-                   if (0 > compare_tree_int (index1,
-                                             TREE_STRING_LENGTH (init)))
-                     {
-                       tree type = TREE_TYPE (TREE_TYPE (init));
-                       enum machine_mode mode = TYPE_MODE (type);
-
-                       if (GET_MODE_CLASS (mode) == MODE_INT
-                           && GET_MODE_SIZE (mode) == 1)
-                         return gen_int_mode (TREE_STRING_POINTER (init)
-                                              [TREE_INT_CST_LOW (index1)],
-                                              mode);
-                     }
+               if (compare_tree_int (index1, TREE_STRING_LENGTH (init)) < 0)
+                 {
+                   tree type = TREE_TYPE (TREE_TYPE (init));
+                   enum machine_mode mode = TYPE_MODE (type);
+
+                   if (GET_MODE_CLASS (mode) == MODE_INT
+                       && GET_MODE_SIZE (mode) == 1)
+                     return gen_int_mode (TREE_STRING_POINTER (init)
+                                          [TREE_INT_CST_LOW (index1)],
+                                          mode);
                  }
              }
          }
@@ -9764,7 +9836,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
                    if (TYPE_UNSIGNED (TREE_TYPE (field)))
                      {
-                       op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
+                       op1 = gen_int_mode (((HOST_WIDE_INT) 1 << bitsize) - 1,
+                                           imode);
                        op0 = expand_and (imode, op0, op1, target);
                      }
                    else
@@ -9819,11 +9892,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                          && modifier != EXPAND_STACK_PARM
                          ? target : NULL_RTX),
                         VOIDmode,
-                        (modifier == EXPAND_INITIALIZER
-                         || modifier == EXPAND_CONST_ADDRESS
-                         || modifier == EXPAND_STACK_PARM)
-                        ? modifier : EXPAND_NORMAL);
-
+                        modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
 
        /* If the bitfield is volatile, we want to access it in the
           field's mode, not the computed mode.
@@ -9961,7 +10030,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
                && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
                && modifier != EXPAND_CONST_ADDRESS
-               && modifier != EXPAND_INITIALIZER)
+               && modifier != EXPAND_INITIALIZER
+               && modifier != EXPAND_MEMORY)
            /* If the field is volatile, we always want an aligned
               access.  Do this in following two situations:
               1. the access is not already naturally
@@ -9981,6 +10051,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                      || (MEM_P (op0)
                          && (MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode1)
                              || (bitpos % GET_MODE_ALIGNMENT (mode1) != 0))))
+                    && modifier != EXPAND_MEMORY
                     && ((modifier == EXPAND_CONST_ADDRESS
                          || modifier == EXPAND_INITIALIZER)
                         ? STRICT_ALIGNMENT
@@ -10102,7 +10173,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            || modifier == EXPAND_CONST_ADDRESS
            || modifier == EXPAND_INITIALIZER)
          return op0;
-       else if (target == 0)
+
+       if (target == 0)
          target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
 
        convert_move (target, op0, unsignedp);
@@ -10149,7 +10221,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* If we are converting to BLKmode, try to avoid an intermediate
         temporary by fetching an inner memory reference.  */
       if (mode == BLKmode
-         && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
+         && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
          && TYPE_MODE (TREE_TYPE (treeop0)) != BLKmode
          && handled_component_p (treeop0))
       {
@@ -10168,7 +10240,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        if (!offset
            && (bitpos % BITS_PER_UNIT) == 0
            && bitsize >= 0
-           && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) == 0)
+           && compare_tree_int (TYPE_SIZE (type), bitsize) == 0)
          {
            /* See the normal_inner_ref case for the rationale.  */
            orig_op0
@@ -10179,10 +10251,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                              && modifier != EXPAND_STACK_PARM
                              ? target : NULL_RTX),
                             VOIDmode,
-                            (modifier == EXPAND_INITIALIZER
-                             || modifier == EXPAND_CONST_ADDRESS
-                             || modifier == EXPAND_STACK_PARM)
-                            ? modifier : EXPAND_NORMAL);
+                            modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier);
 
            if (MEM_P (orig_op0))
              {
@@ -10209,8 +10278,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       }
 
       if (!op0)
-       op0 = expand_expr (treeop0,
-                          NULL_RTX, VOIDmode, modifier);
+       op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
 
       /* If the input and output modes are both the same, we are done.  */
       if (mode == GET_MODE (op0))
@@ -10268,10 +10336,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        {
          enum insn_code icode;
 
-         op0 = copy_rtx (op0);
-
          if (TYPE_ALIGN_OK (type))
-           set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
+           {
+             /* ??? Copying the MEM without substantially changing it might
+                run afoul of the code handling volatile memory references in
+                store_expr, which assumes that TARGET is returned unmodified
+                if it has been used.  */
+             op0 = copy_rtx (op0);
+             set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
+           }
          else if (mode != BLKmode
                   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)
                   /* If the target does have special handling for unaligned
@@ -10586,17 +10659,18 @@ string_constant (tree arg, tree *ptr_offset)
           || TREE_CODE (array) == CONST_DECL)
     {
       int length;
+      tree init = ctor_for_folding (array);
 
       /* Variables initialized to string literals can be handled too.  */
-      if (!const_value_known_p (array)
-         || !DECL_INITIAL (array)
-         || TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
+      if (init == error_mark_node
+         || !init
+         || TREE_CODE (init) != STRING_CST)
        return 0;
 
       /* Avoid const char foo[4] = "abcde";  */
       if (DECL_SIZE_UNIT (array) == NULL_TREE
          || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
-         || (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0
+         || (length = TREE_STRING_LENGTH (init)) <= 0
          || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
        return 0;
 
@@ -10609,7 +10683,7 @@ string_constant (tree arg, tree *ptr_offset)
        return 0;
 
       *ptr_offset = offset;
-      return DECL_INITIAL (array);
+      return init;
     }
 
   return 0;
@@ -10817,10 +10891,14 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
 #endif
 
 /* Attempt to generate a casesi instruction.  Returns 1 if successful,
-   0 otherwise (i.e. if there is no casesi instruction).  */
+   0 otherwise (i.e. if there is no casesi instruction).
+
+   DEFAULT_PROBABILITY is the probability of jumping to the default
+   label.  */
 int
 try_casesi (tree index_type, tree index_expr, tree minval, tree range,
-           rtx table_label, rtx default_label, rtx fallback_label)
+           rtx table_label, rtx default_label, rtx fallback_label,
+            int default_probability)
 {
   struct expand_operand ops[5];
   enum machine_mode index_mode = SImode;
@@ -10842,7 +10920,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
       index = expand_normal (index_expr);
       if (default_label)
         emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
-                                omode, 1, default_label);
+                                omode, 1, default_label,
+                                 default_probability);
       /* Now we can safely truncate.  */
       index = convert_to_mode (index_mode, index, 0);
     }
@@ -10888,11 +10967,13 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
    TABLE_LABEL is a CODE_LABEL rtx for the table itself.
 
    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
-   index value is out of range.  */
+   index value is out of range.
+   DEFAULT_PROBABILITY is the probability of jumping to
+   the default label.  */
 
 static void
 do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
-             rtx default_label)
+             rtx default_label, int default_probability)
 {
   rtx temp, vector;
 
@@ -10909,7 +10990,8 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
 
   if (default_label)
     emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
-                            default_label);
+                            default_label, default_probability);
+
 
   /* If index is in range, it must fit in Pmode.
      Convert to Pmode so we can index with it.  */
@@ -10928,10 +11010,11 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
      GET_MODE_SIZE, because this indicates how large insns are.  The other
      uses should all be Pmode, because they are addresses.  This code
      could fail if addresses and insns are not the same size.  */
-  index = gen_rtx_PLUS (Pmode,
-                       gen_rtx_MULT (Pmode, index,
-                                     GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
-                       gen_rtx_LABEL_REF (Pmode, table_label));
+  index = gen_rtx_PLUS
+    (Pmode,
+     gen_rtx_MULT (Pmode, index,
+                  gen_int_mode (GET_MODE_SIZE (CASE_VECTOR_MODE), Pmode)),
+     gen_rtx_LABEL_REF (Pmode, table_label));
 #ifdef PIC_CASE_VECTOR_ADDRESS
   if (flag_pic)
     index = PIC_CASE_VECTOR_ADDRESS (index);
@@ -10952,7 +11035,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label,
 
 int
 try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
-              rtx table_label, rtx default_label)
+              rtx table_label, rtx default_label, int default_probability)
 {
   rtx index;
 
@@ -10970,7 +11053,7 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
                               TYPE_MODE (TREE_TYPE (range)),
                               expand_normal (range),
                               TYPE_UNSIGNED (TREE_TYPE (range))),
-               table_label, default_label);
+               table_label, default_label, default_probability);
   return 1;
 }