i386.c (legitimize_tls_address): Generate tls_initial_exec_64_sun only when !TARGET_X32.
[gcc.git] / gcc / expr.c
index 29bf68b672317c5fd358e943d20a14debe0afbc9..8d815c94836416c8ea8c493cadf4912064506dc2 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
-   Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -123,9 +123,6 @@ struct store_by_pieces_d
   int reverse;
 };
 
-static unsigned HOST_WIDE_INT move_by_pieces_ninsns (unsigned HOST_WIDE_INT,
-                                                    unsigned int,
-                                                    unsigned int);
 static void move_by_pieces_1 (rtx (*) (rtx, ...), enum machine_mode,
                              struct move_by_pieces_d *);
 static bool block_move_libcall_safe_for_call_parm (void);
@@ -441,21 +438,20 @@ convert_move (rtx to, rtx from, int unsignedp)
       rtx new_from;
       enum machine_mode full_mode
        = smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
+      convert_optab ctab = unsignedp ? zext_optab : sext_optab;
+      enum insn_code icode;
 
-      gcc_assert (convert_optab_handler (sext_optab, full_mode, from_mode)
-                 != CODE_FOR_nothing);
+      icode = convert_optab_handler (ctab, full_mode, from_mode);
+      gcc_assert (icode != CODE_FOR_nothing);
 
       if (to_mode == full_mode)
        {
-         emit_unop_insn (convert_optab_handler (sext_optab, full_mode,
-                                                from_mode),
-                         to, from, UNKNOWN);
+         emit_unop_insn (icode, to, from, UNKNOWN);
          return;
        }
 
       new_from = gen_reg_rtx (full_mode);
-      emit_unop_insn (convert_optab_handler (sext_optab, full_mode, from_mode),
-                     new_from, from, UNKNOWN);
+      emit_unop_insn (icode, new_from, from, UNKNOWN);
 
       /* else proceed to integer conversions below.  */
       from_mode = full_mode;
@@ -871,8 +867,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
                unsigned int align, int endp)
 {
   struct move_by_pieces_d data;
-  enum machine_mode to_addr_mode, from_addr_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (from));
+  enum machine_mode to_addr_mode;
+  enum machine_mode from_addr_mode = get_address_mode (from);
   rtx to_addr, from_addr = XEXP (from, 0);
   unsigned int max_size = MOVE_MAX_PIECES + 1;
   enum insn_code icode;
@@ -883,7 +879,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
   data.from_addr = from_addr;
   if (to)
     {
-      to_addr_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to));
+      to_addr_mode = get_address_mode (to);
       to_addr = XEXP (to, 0);
       data.to = to;
       data.autinc_to
@@ -931,7 +927,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
       if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
        {
          data.from_addr = copy_to_mode_reg (from_addr_mode,
-                                            plus_constant (from_addr, len));
+                                            plus_constant (from_addr_mode,
+                                                           from_addr, len));
          data.autinc_from = 1;
          data.explicit_inc_from = -1;
        }
@@ -946,7 +943,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
       if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
        {
          data.to_addr = copy_to_mode_reg (to_addr_mode,
-                                          plus_constant (to_addr, len));
+                                          plus_constant (to_addr_mode,
+                                                         to_addr, len));
          data.autinc_to = 1;
          data.explicit_inc_to = -1;
        }
@@ -995,7 +993,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
                emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
              else
                data.to_addr = copy_to_mode_reg (to_addr_mode,
-                                                plus_constant (data.to_addr,
+                                                plus_constant (to_addr_mode,
+                                                               data.to_addr,
                                                                -1));
            }
          to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
@@ -1016,7 +1015,7 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
 /* Return number of insns required to move L bytes by pieces.
    ALIGN (in bits) is maximum alignment we can assume.  */
 
-static unsigned HOST_WIDE_INT
+unsigned HOST_WIDE_INT
 move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
                       unsigned int max_size)
 {
@@ -1346,8 +1345,8 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall)
      pseudos.  We can then place those new pseudos into a VAR_DECL and
      use them later.  */
 
-  dst_addr = copy_to_mode_reg (Pmode, XEXP (dst, 0));
-  src_addr = copy_to_mode_reg (Pmode, XEXP (src, 0));
+  dst_addr = copy_addr_to_reg (XEXP (dst, 0));
+  src_addr = copy_addr_to_reg (XEXP (src, 0));
 
   dst_addr = convert_memory_address (ptr_mode, dst_addr);
   src_addr = convert_memory_address (ptr_mode, src_addr);
@@ -1378,8 +1377,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall)
 }
 
 /* A subroutine of emit_block_move_via_libcall.  Create the tree node
-   for the function we use for block copies.  The first time FOR_CALL
-   is true, we call assemble_external.  */
+   for the function we use for block copies.  */
 
 static GTY(()) tree block_move_fn;
 
@@ -1388,7 +1386,7 @@ init_block_move_fn (const char *asmspec)
 {
   if (!block_move_fn)
     {
-      tree args, fn;
+      tree args, fn, attrs, attr_args;
 
       fn = get_identifier ("memcpy");
       args = build_function_type_list (ptr_type_node, ptr_type_node,
@@ -1403,6 +1401,11 @@ init_block_move_fn (const char *asmspec)
       DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
       DECL_VISIBILITY_SPECIFIED (fn) = 1;
 
+      attr_args = build_tree_list (NULL_TREE, build_string (1, "1"));
+      attrs = tree_cons (get_identifier ("fn spec"), attr_args, NULL);
+
+      decl_attributes (&fn, attrs, ATTR_FLAG_BUILT_IN);
+
       block_move_fn = fn;
     }
 
@@ -1422,7 +1425,6 @@ emit_block_move_libcall_fn (int for_call)
     {
       emitted_extern = true;
       make_decl_rtl (block_move_fn);
-      assemble_external (block_move_fn);
     }
 
   return block_move_fn;
@@ -1437,10 +1439,8 @@ emit_block_move_via_loop (rtx x, rtx y, rtx size,
                          unsigned int align ATTRIBUTE_UNUSED)
 {
   rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
-  enum machine_mode x_addr_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x));
-  enum machine_mode y_addr_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (y));
+  enum machine_mode x_addr_mode = get_address_mode (x);
+  enum machine_mode y_addr_mode = get_address_mode (y);
   enum machine_mode iter_mode;
 
   iter_mode = GET_MODE (size);
@@ -1615,7 +1615,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
     {
       enum machine_mode imode = int_mode_for_mode (GET_MODE (orig_src));
       if (imode == BLKmode)
-       src = assign_stack_temp (GET_MODE (orig_src), ssize, 0);
+       src = assign_stack_temp (GET_MODE (orig_src), ssize);
       else
        src = gen_reg_rtx (imode);
       if (imode != BLKmode)
@@ -1717,7 +1717,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
              rtx mem;
 
              gcc_assert (!bytepos);
-             mem = assign_stack_temp (GET_MODE (src), slen, 0);
+             mem = assign_stack_temp (GET_MODE (src), slen);
              emit_move_insn (mem, src);
              tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
                                           0, 1, false, NULL_RTX, mode, mode);
@@ -1732,7 +1732,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
          int slen = GET_MODE_SIZE (GET_MODE (src));
          rtx mem;
 
-         mem = assign_stack_temp (GET_MODE (src), slen, 0);
+         mem = assign_stack_temp (GET_MODE (src), slen);
          emit_move_insn (mem, src);
          tmps[i] = adjust_address (mem, mode, (int) bytepos);
        }
@@ -1883,7 +1883,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
     {
       enum machine_mode imode = int_mode_for_mode (GET_MODE (orig_dst));
       if (imode == BLKmode)
-        dst = assign_stack_temp (GET_MODE (orig_dst), ssize, 0);
+        dst = assign_stack_temp (GET_MODE (orig_dst), ssize);
       else
         dst = gen_reg_rtx (imode);
       emit_group_store (dst, src, type, ssize);
@@ -1933,7 +1933,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
         it.  Allocate a temporary, and split this into a store/load to/from
         the temporary.  */
 
-      temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
+      temp = assign_stack_temp (GET_MODE (dst), ssize);
       emit_group_store (temp, src, type, ssize);
       emit_group_load (dst, temp, type, ssize);
       return;
@@ -2028,8 +2028,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
                  >= GET_MODE_ALIGNMENT (tmp_mode))
                {
                  dest = assign_stack_temp (dest_mode,
-                                           GET_MODE_SIZE (dest_mode),
-                                           0);
+                                           GET_MODE_SIZE (dest_mode));
                  emit_move_insn (adjust_address (dest,
                                                  tmp_mode,
                                                  bytepos),
@@ -2039,8 +2038,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
              else
                {
                  dest = assign_stack_temp (tmp_mode,
-                                           GET_MODE_SIZE (tmp_mode),
-                                           0);
+                                           GET_MODE_SIZE (tmp_mode));
                  emit_move_insn (dest, tmps[i]);
                  dst = adjust_address (dest, dest_mode, bytepos);
                }
@@ -2108,7 +2106,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
       tgtblk = assign_temp (build_qualified_type (type,
                                                  (TYPE_QUALS (type)
                                                   | TYPE_QUAL_CONST)),
-                           0, 1, 1);
+                           1, 1);
       preserve_temp_slots (tgtblk);
     }
 
@@ -2180,6 +2178,112 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type)
   return tgtblk;
 }
 
+/* Copy BLKmode value SRC into a register of mode MODE.  Return the
+   register if it contains any data, otherwise return null.
+
+   This is used on targets that return BLKmode values in registers.  */
+
+rtx
+copy_blkmode_to_reg (enum machine_mode mode, tree src)
+{
+  int i, n_regs;
+  unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0, bytes;
+  unsigned int bitsize;
+  rtx *dst_words, dst, x, src_word = NULL_RTX, dst_word = NULL_RTX;
+  enum machine_mode dst_mode;
+
+  gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode);
+
+  x = expand_normal (src);
+
+  bytes = int_size_in_bytes (TREE_TYPE (src));
+  if (bytes == 0)
+    return NULL_RTX;
+
+  /* If the structure doesn't take up a whole number of words, see
+     whether the register value should be padded on the left or on
+     the right.  Set PADDING_CORRECTION to the number of padding
+     bits needed on the left side.
+
+     In most ABIs, the structure will be returned at the least end of
+     the register, which translates to right padding on little-endian
+     targets and left padding on big-endian targets.  The opposite
+     holds if the structure is returned at the most significant
+     end of the register.  */
+  if (bytes % UNITS_PER_WORD != 0
+      && (targetm.calls.return_in_msb (TREE_TYPE (src))
+         ? !BYTES_BIG_ENDIAN
+         : BYTES_BIG_ENDIAN))
+    padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
+                                          * BITS_PER_UNIT));
+
+  n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  dst_words = XALLOCAVEC (rtx, n_regs);
+  bitsize = MIN (TYPE_ALIGN (TREE_TYPE (src)), BITS_PER_WORD);
+
+  /* Copy the structure BITSIZE bits at a time.  */
+  for (bitpos = 0, xbitpos = padding_correction;
+       bitpos < bytes * BITS_PER_UNIT;
+       bitpos += bitsize, xbitpos += bitsize)
+    {
+      /* We need a new destination pseudo 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)
+       {
+         /* Generate an appropriate register.  */
+         dst_word = gen_reg_rtx (word_mode);
+         dst_words[xbitpos / BITS_PER_WORD] = dst_word;
+
+         /* Clear the destination before we move anything into it.  */
+         emit_move_insn (dst_word, CONST0_RTX (word_mode));
+       }
+
+      /* We need a new source operand each time bitpos is on a word
+        boundary.  */
+      if (bitpos % BITS_PER_WORD == 0)
+       src_word = operand_subword_force (x, bitpos / BITS_PER_WORD, BLKmode);
+
+      /* Use bitpos for the source extraction (left justified) and
+        xbitpos for the destination store (right justified).  */
+      store_bit_field (dst_word, bitsize, xbitpos % BITS_PER_WORD,
+                      0, 0, word_mode,
+                      extract_bit_field (src_word, bitsize,
+                                         bitpos % BITS_PER_WORD, 1, false,
+                                         NULL_RTX, word_mode, word_mode));
+    }
+
+  if (mode == BLKmode)
+    {
+      /* Find the smallest integer mode large enough to hold the
+        entire structure.  */
+      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+          mode != VOIDmode;
+          mode = GET_MODE_WIDER_MODE (mode))
+       /* Have we found a large enough mode?  */
+       if (GET_MODE_SIZE (mode) >= bytes)
+         break;
+
+      /* A suitable mode should have been found.  */
+      gcc_assert (mode != VOIDmode);
+    }
+
+  if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode))
+    dst_mode = word_mode;
+  else
+    dst_mode = mode;
+  dst = gen_reg_rtx (dst_mode);
+
+  for (i = 0; i < n_regs; i++)
+    emit_move_insn (operand_subword (dst, i, 0, dst_mode), dst_words[i]);
+
+  if (mode != dst_mode)
+    dst = gen_lowpart (mode, dst);
+
+  return dst;
+}
+
 /* Add a USE expression for REG to the (possibly empty) list pointed
    to by CALL_FUSAGE.  REG must denote a hard register.  */
 
@@ -2246,6 +2350,28 @@ get_def_for_expr (tree name, enum tree_code code)
 
   return def_stmt;
 }
+
+#ifdef HAVE_conditional_move
+/* Return the defining gimple statement for SSA_NAME NAME if it is an
+   assigment and the class of the expresion on the RHS is CLASS.  Return
+   NULL otherwise.  */
+
+static gimple
+get_def_for_expr_class (tree name, enum tree_code_class tclass)
+{
+  gimple def_stmt;
+
+  if (TREE_CODE (name) != SSA_NAME)
+    return NULL;
+
+  def_stmt = get_gimple_for_ssa_name (name);
+  if (!def_stmt
+      || TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) != tclass)
+    return NULL;
+
+  return def_stmt;
+}
+#endif
 \f
 
 /* Determine whether the LEN bytes generated by CONSTFUN can be
@@ -2341,8 +2467,7 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
                 rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode),
                 void *constfundata, unsigned int align, bool memsetp, int endp)
 {
-  enum machine_mode to_addr_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to));
+  enum machine_mode to_addr_mode = get_address_mode (to);
   struct store_by_pieces_d data;
 
   if (len == 0)
@@ -2372,7 +2497,8 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
                emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
              else
                data.to_addr = copy_to_mode_reg (to_addr_mode,
-                                                plus_constant (data.to_addr,
+                                                plus_constant (to_addr_mode,
+                                                               data.to_addr,
                                                                -1));
            }
          to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
@@ -2427,8 +2553,7 @@ static void
 store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
                   unsigned int align ATTRIBUTE_UNUSED)
 {
-  enum machine_mode to_addr_mode
-    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (data->to));
+  enum machine_mode to_addr_mode = get_address_mode (data->to);
   rtx to_addr = XEXP (data->to, 0);
   unsigned int max_size = STORE_MAX_PIECES + 1;
   enum insn_code icode;
@@ -2460,7 +2585,9 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
       if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
        {
          data->to_addr = copy_to_mode_reg (to_addr_mode,
-                                           plus_constant (to_addr, data->len));
+                                           plus_constant (to_addr_mode,
+                                                          to_addr,
+                                                          data->len));
          data->autinc_to = 1;
          data->explicit_inc_to = -1;
        }
@@ -2616,7 +2743,7 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall)
   /* Emit code to copy OBJECT and SIZE into new pseudos.  We can then
      place those into new pseudos into a VAR_DECL and use them later.  */
 
-  object = copy_to_mode_reg (Pmode, XEXP (object, 0));
+  object = copy_addr_to_reg (XEXP (object, 0));
 
   size_mode = TYPE_MODE (sizetype);
   size = convert_to_mode (size_mode, size, 1);
@@ -2644,8 +2771,7 @@ set_storage_via_libcall (rtx object, rtx size, rtx val, bool tailcall)
 }
 
 /* A subroutine of set_storage_via_libcall.  Create the tree node
-   for the function we use for block clears.  The first time FOR_CALL
-   is true, we call assemble_external.  */
+   for the function we use for block clears.  */
 
 tree block_clear_fn;
 
@@ -2688,7 +2814,6 @@ clear_storage_libcall_fn (int for_call)
     {
       emitted_extern = true;
       make_decl_rtl (block_clear_fn);
-      assemble_external (block_clear_fn);
     }
 
   return block_clear_fn;
@@ -2997,7 +3122,7 @@ emit_move_resolve_push (enum machine_mode mode, rtx x)
     case POST_INC:
     case POST_DEC:
     case POST_MODIFY:
-      temp = plus_constant (stack_pointer_rtx, -adjust);
+      temp = plus_constant (Pmode, stack_pointer_rtx, -adjust);
       break;
     default:
       gcc_unreachable ();
@@ -3477,7 +3602,7 @@ push_block (rtx size, int extra, int below)
 
   size = convert_modes (Pmode, ptr_mode, size, 1);
   if (CONSTANT_P (size))
-    anti_adjust_stack (plus_constant (size, extra));
+    anti_adjust_stack (plus_constant (Pmode, size, extra));
   else if (REG_P (size) && extra == 0)
     anti_adjust_stack (size);
   else
@@ -3497,16 +3622,17 @@ push_block (rtx size, int extra, int below)
     {
       temp = virtual_outgoing_args_rtx;
       if (extra != 0 && below)
-       temp = plus_constant (temp, extra);
+       temp = plus_constant (Pmode, temp, extra);
     }
   else
     {
       if (CONST_INT_P (size))
-       temp = plus_constant (virtual_outgoing_args_rtx,
+       temp = plus_constant (Pmode, virtual_outgoing_args_rtx,
                              -INTVAL (size) - (below ? 0 : extra));
       else if (extra != 0 && !below)
        temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
-                            negate_rtx (Pmode, plus_constant (size, extra)));
+                            negate_rtx (Pmode, plus_constant (Pmode, size,
+                                                              extra)));
       else
        temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
                             negate_rtx (Pmode, size));
@@ -3539,9 +3665,11 @@ mem_autoinc_base (rtx mem)
      (1) One or more auto-inc style memory references (aka pushes),
      (2) One or more addition/subtraction with the SP as destination,
      (3) A single move insn with the SP as destination,
-     (4) A call_pop insn.
+     (4) A call_pop insn,
+     (5) Noreturn call insns if !ACCUMULATE_OUTGOING_ARGS.
 
-   Insns in the sequence that do not modify the SP are ignored.
+   Insns in the sequence that do not modify the SP are ignored,
+   except for noreturn calls.
 
    The return value is the amount of adjustment that can be trivially
    verified, via immediate operand or auto-inc.  If the adjustment
@@ -3686,7 +3814,12 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
 
       this_delta = find_args_size_adjust (insn);
       if (this_delta == 0)
-       continue;
+       {
+         if (!CALL_P (insn)
+             || ACCUMULATE_OUTGOING_ARGS
+             || find_reg_note (insn, REG_NORETURN, NULL_RTX) == NULL_RTX)
+           continue;
+       }
 
       gcc_assert (!saw_unknown);
       if (this_delta == HOST_WIDE_INT_MIN)
@@ -3895,7 +4028,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
          size = GEN_INT (GET_MODE_SIZE (mode));
          if (!MEM_P (xinner))
            {
-             temp = assign_temp (type, 0, 1, 1);
+             temp = assign_temp (type, 1, 1);
              emit_move_insn (temp, xinner);
              xinner = temp;
            }
@@ -3972,11 +4105,12 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
            }
          else if (CONST_INT_P (args_so_far))
            temp = memory_address (BLKmode,
-                                  plus_constant (args_addr,
+                                  plus_constant (Pmode, args_addr,
                                                  skip + INTVAL (args_so_far)));
          else
            temp = memory_address (BLKmode,
-                                  plus_constant (gen_rtx_PLUS (Pmode,
+                                  plus_constant (Pmode,
+                                                 gen_rtx_PLUS (Pmode,
                                                                args_addr,
                                                                args_so_far),
                                                  skip));
@@ -4089,7 +4223,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
          if (CONST_INT_P (args_so_far))
            addr
              = memory_address (mode,
-                               plus_constant (args_addr,
+                               plus_constant (Pmode, args_addr,
                                               INTVAL (args_so_far)));
          else
            addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
@@ -4277,8 +4411,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
          value = expand_and (str_mode, value, const1_rtx, NULL);
          binop = xor_optab;
        }
-      value = expand_shift (LSHIFT_EXPR, str_mode, value,
-                           bitpos, NULL_RTX, 1);
+      value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
       result = expand_binop (str_mode, binop, str_rtx,
                             value, str_rtx, 1, OPTAB_WIDEN);
       if (result != str_rtx)
@@ -4289,8 +4422,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
     case BIT_XOR_EXPR:
       if (TREE_CODE (op1) != INTEGER_CST)
        break;
-      value = expand_expr (op1, NULL_RTX, GET_MODE (str_rtx), EXPAND_NORMAL);
-      value = convert_modes (GET_MODE (str_rtx),
+      value = expand_expr (op1, NULL_RTX, str_mode, EXPAND_NORMAL);
+      value = convert_modes (str_mode,
                             TYPE_MODE (TREE_TYPE (op1)), value,
                             TYPE_UNSIGNED (TREE_TYPE (op1)));
 
@@ -4304,16 +4437,13 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
        }
 
       binop = code == BIT_IOR_EXPR ? ior_optab : xor_optab;
-      if (bitpos + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx)))
+      if (bitpos + bitsize != str_bitsize)
        {
-         rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize)
-                             - 1);
-         value = expand_and (GET_MODE (str_rtx), value, mask,
-                             NULL_RTX);
+         rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize) - 1);
+         value = expand_and (str_mode, value, mask, NULL_RTX);
        }
-      value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx), value,
-                           bitpos, NULL_RTX, 1);
-      result = expand_binop (GET_MODE (str_rtx), binop, str_rtx,
+      value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
+      result = expand_binop (str_mode, binop, str_rtx,
                             value, str_rtx, 1, OPTAB_WIDEN);
       if (result != str_rtx)
        emit_move_insn (str_rtx, result);
@@ -4329,113 +4459,105 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
 /* In the C++ memory model, consecutive bit fields in a structure are
    considered one memory location.
 
-   Given a COMPONENT_REF, this function returns the bit range of
-   consecutive bits in which this COMPONENT_REF belongs in.  The
-   values are returned in *BITSTART and *BITEND.  If either the C++
-   memory model is not activated, or this memory access is not thread
-   visible, 0 is returned in *BITSTART and *BITEND.
-
-   EXP is the COMPONENT_REF.
-   INNERDECL is the actual object being referenced.
-   BITPOS is the position in bits where the bit starts within the structure.
-   BITSIZE is size in bits of the field being referenced in EXP.
-
-   For example, while storing into FOO.A here...
-
-      struct {
-        BIT 0:
-          unsigned int a : 4;
-         unsigned int b : 1;
-       BIT 8:
-         unsigned char c;
-         unsigned int d : 6;
-      } foo;
+   Given a COMPONENT_REF EXP at position (BITPOS, OFFSET), this function
+   returns the bit range of consecutive bits in which this COMPONENT_REF
+   belongs.  The values are returned in *BITSTART and *BITEND.  *BITPOS
+   and *OFFSET may be adjusted in the process.
 
-   ...we are not allowed to store past <b>, so for the layout above, a
-   range of 0..7 (because no one cares if we store into the
-   padding).  */
+   If the access does not need to be restricted, 0 is returned in both
+   *BITSTART and *BITEND.  */
 
 static void
 get_bit_range (unsigned HOST_WIDE_INT *bitstart,
               unsigned HOST_WIDE_INT *bitend,
-              tree exp, tree innerdecl,
-              HOST_WIDE_INT bitpos, HOST_WIDE_INT bitsize)
+              tree exp,
+              HOST_WIDE_INT *bitpos,
+              tree *offset)
 {
-  tree field, record_type, fld;
-  bool found_field = false;
-  bool prev_field_is_bitfield;
+  HOST_WIDE_INT bitoffset;
+  tree field, repr;
 
   gcc_assert (TREE_CODE (exp) == COMPONENT_REF);
 
-  /* If other threads can't see this value, no need to restrict stores.  */
-  if (ALLOW_STORE_DATA_RACES
-      || ((TREE_CODE (innerdecl) == MEM_REF
-          || TREE_CODE (innerdecl) == TARGET_MEM_REF)
-         && !ptr_deref_may_alias_global_p (TREE_OPERAND (innerdecl, 0)))
-      || (DECL_P (innerdecl)
-         && ((TREE_CODE (innerdecl) == VAR_DECL
-              && DECL_THREAD_LOCAL_P (innerdecl))
-             || !TREE_STATIC (innerdecl))))
+  field = TREE_OPERAND (exp, 1);
+  repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
+  /* If we do not have a DECL_BIT_FIELD_REPRESENTATIVE there is no
+     need to limit the range we can access.  */
+  if (!repr)
     {
       *bitstart = *bitend = 0;
       return;
     }
 
-  /* Bit field we're storing into.  */
-  field = TREE_OPERAND (exp, 1);
-  record_type = DECL_FIELD_CONTEXT (field);
-
-  /* Count the contiguous bitfields for the memory location that
-     contains FIELD.  */
-  *bitstart = 0;
-  prev_field_is_bitfield = true;
-  for (fld = TYPE_FIELDS (record_type); fld; fld = DECL_CHAIN (fld))
+  /* If we have a DECL_BIT_FIELD_REPRESENTATIVE but the enclosing record is
+     part of a larger bit field, then the representative does not serve any
+     useful purpose.  This can occur in Ada.  */
+  if (handled_component_p (TREE_OPERAND (exp, 0)))
     {
-      tree t, offset;
-      enum machine_mode mode;
-      int unsignedp, volatilep;
-
-      if (TREE_CODE (fld) != FIELD_DECL)
-       continue;
-
-      t = build3 (COMPONENT_REF, TREE_TYPE (exp),
-                 unshare_expr (TREE_OPERAND (exp, 0)),
-                 fld, NULL_TREE);
-      get_inner_reference (t, &bitsize, &bitpos, &offset,
-                          &mode, &unsignedp, &volatilep, true);
-
-      if (field == fld)
-       found_field = true;
-
-      if (DECL_BIT_FIELD_TYPE (fld) && bitsize > 0)
-       {
-         if (prev_field_is_bitfield == false)
-           {
-             *bitstart = bitpos;
-             prev_field_is_bitfield = true;
-           }
-       }
-      else
+      enum machine_mode rmode;
+      HOST_WIDE_INT rbitsize, rbitpos;
+      tree roffset;
+      int unsignedp;
+      int volatilep = 0;
+      get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
+                          &roffset, &rmode, &unsignedp, &volatilep, false);
+      if ((rbitpos % BITS_PER_UNIT) != 0)
        {
-         prev_field_is_bitfield = false;
-         if (found_field)
-           break;
+         *bitstart = *bitend = 0;
+         return;
        }
     }
-  gcc_assert (found_field);
 
-  if (fld)
-    {
-      /* We found the end of the bit field sequence.  Include the
-        padding up to the next field and be done.  */
-      *bitend = bitpos - 1;
-    }
+  /* Compute the adjustment to bitpos from the offset of the field
+     relative to the representative.  DECL_FIELD_OFFSET of field and
+     repr are the same by construction if they are not constants,
+     see finish_bitfield_layout.  */
+  if (host_integerp (DECL_FIELD_OFFSET (field), 1)
+      && host_integerp (DECL_FIELD_OFFSET (repr), 1))
+    bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
+                - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
   else
+    bitoffset = 0;
+  bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+               - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+
+  /* If the adjustment is larger than bitpos, we would have a negative bit
+     position for the lower bound and this may wreak havoc later.  This can
+     occur only if we have a non-null offset, so adjust offset and bitpos
+     to make the lower bound non-negative.  */
+  if (bitoffset > *bitpos)
     {
-      /* If this is the last element in the structure, include the padding
-        at the end of structure.  */
-      *bitend = TREE_INT_CST_LOW (TYPE_SIZE (record_type)) - 1;
+      HOST_WIDE_INT adjust = bitoffset - *bitpos;
+
+      gcc_assert ((adjust % BITS_PER_UNIT) == 0);
+      gcc_assert (*offset != NULL_TREE);
+
+      *bitpos += adjust;
+      *offset
+       = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
+      *bitstart = 0;
     }
+  else
+    *bitstart = *bitpos - bitoffset;
+
+  *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
+}
+
+/* Returns true if the MEM_REF REF refers to an object that does not
+   reside in memory and has non-BLKmode.  */
+
+static 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)));
 }
 
 /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
@@ -4447,7 +4569,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
   rtx to_rtx = 0;
   rtx result;
   enum machine_mode mode;
-  int align;
+  unsigned int align;
   enum insn_code icode;
 
   /* Don't crash if the lhs of the assignment was erroneous.  */
@@ -4461,63 +4583,37 @@ expand_assignment (tree to, tree from, bool nontemporal)
   if (operand_equal_p (to, from, 0))
     return;
 
+  /* Handle misaligned stores.  */
   mode = TYPE_MODE (TREE_TYPE (to));
   if ((TREE_CODE (to) == MEM_REF
        || TREE_CODE (to) == TARGET_MEM_REF)
       && mode != BLKmode
-      && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
-         < (signed) GET_MODE_ALIGNMENT (mode))
-      && ((icode = optab_handler (movmisalign_optab, mode))
-         != CODE_FOR_nothing))
+      && !mem_ref_refers_to_non_mem_p (to)
+      && ((align = get_object_or_type_alignment (to))
+         < GET_MODE_ALIGNMENT (mode))
+      && (((icode = optab_handler (movmisalign_optab, mode))
+          != CODE_FOR_nothing)
+         || SLOW_UNALIGNED_ACCESS (mode, align)))
     {
-      struct expand_operand ops[2];
-      enum machine_mode address_mode;
-      rtx reg, op0, mem;
+      rtx reg, mem;
 
       reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL);
       reg = force_not_mem (reg);
+      mem = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
-      if (TREE_CODE (to) == MEM_REF)
-       {
-         addr_space_t as
-             = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 1))));
-         tree base = TREE_OPERAND (to, 0);
-         address_mode = targetm.addr_space.address_mode (as);
-         op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-         op0 = convert_memory_address_addr_space (address_mode, op0, as);
-         if (!integer_zerop (TREE_OPERAND (to, 1)))
-           {
-             rtx off
-                 = immed_double_int_const (mem_ref_offset (to), address_mode);
-             op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
-           }
-         op0 = memory_address_addr_space (mode, op0, as);
-         mem = gen_rtx_MEM (mode, op0);
-         set_mem_attributes (mem, to, 0);
-         set_mem_addr_space (mem, as);
-       }
-      else if (TREE_CODE (to) == TARGET_MEM_REF)
+      if (icode != CODE_FOR_nothing)
        {
-         addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (to));
-         struct mem_address addr;
+         struct expand_operand ops[2];
 
-         get_address_description (to, &addr);
-         op0 = addr_for_mem_ref (&addr, as, true);
-         op0 = memory_address_addr_space (mode, op0, as);
-         mem = gen_rtx_MEM (mode, op0);
-         set_mem_attributes (mem, to, 0);
-         set_mem_addr_space (mem, as);
+         create_fixed_operand (&ops[0], mem);
+         create_input_operand (&ops[1], reg, mode);
+         /* The movmisalign<mode> pattern cannot fail, else the assignment
+            would silently be omitted.  */
+         expand_insn (icode, 2, ops);
        }
       else
-       gcc_unreachable ();
-      if (TREE_THIS_VOLATILE (to))
-       MEM_VOLATILE_P (mem) = 1;
-
-      create_fixed_operand (&ops[0], mem);
-      create_input_operand (&ops[1], reg, mode);
-      /* The movmisalign<mode> pattern cannot fail, else the assignment would
-         silently be omitted.  */
-      expand_insn (icode, 2, ops);
+       store_bit_field (mem, GET_MODE_BITSIZE (mode),
+                        0, 0, 0, mode, reg);
       return;
     }
 
@@ -4525,12 +4621,10 @@ expand_assignment (tree to, tree from, bool nontemporal)
      if the structure component's rtx is not simply a MEM.
      Assignment of an array element at a constant index, and assignment of
      an array element in an unaligned packed structure field, has the same
-     problem.  */
+     problem.  Same for (partially) storing into a non-memory object.  */
   if (handled_component_p (to)
-      /* ???  We only need to handle MEM_REF here if the access is not
-         a full access of the base object.  */
       || (TREE_CODE (to) == MEM_REF
-         && TREE_CODE (TREE_OPERAND (to, 0)) == ADDR_EXPR)
+         && mem_ref_refers_to_non_mem_p (to))
       || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
     {
       enum machine_mode mode1;
@@ -4541,6 +4635,8 @@ 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,
@@ -4548,13 +4644,42 @@ expand_assignment (tree to, tree from, bool nontemporal)
 
       if (TREE_CODE (to) == COMPONENT_REF
          && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
-       get_bit_range (&bitregion_start, &bitregion_end,
-                      to, tem, bitpos, bitsize);
+       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_or_type_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);
 
-      to_rtx = expand_normal (tem);
+             mem = copy_rtx (mem);
+           }
+       }
+      else
+       {
+         misalignp = false;
+         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.
@@ -4583,8 +4708,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
            }
 
          offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
-         address_mode
-           = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx));
+         address_mode = get_address_mode (to_rtx);
          if (GET_MODE (offset_rtx) != address_mode)
            offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
@@ -4656,8 +4780,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
          else
            {
              rtx temp = assign_stack_temp (GET_MODE (to_rtx),
-                                           GET_MODE_SIZE (GET_MODE (to_rtx)),
-                                           0);
+                                           GET_MODE_SIZE (GET_MODE (to_rtx)));
              write_complex_part (temp, XEXP (to_rtx, 0), false);
              write_complex_part (temp, XEXP (to_rtx, 1), true);
              result = store_field (temp, bitsize, bitpos,
@@ -4700,9 +4823,19 @@ expand_assignment (tree to, tree from, bool nontemporal)
                                  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);
+       }
+
       if (result)
        preserve_temp_slots (result);
-      free_temp_slots ();
       pop_temp_slots ();
       return;
     }
@@ -4720,7 +4853,9 @@ expand_assignment (tree to, tree from, bool nontemporal)
   if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from)
       && COMPLETE_TYPE_P (TREE_TYPE (from))
       && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
-      && ! (((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
+      && ! (((TREE_CODE (to) == VAR_DECL
+             || TREE_CODE (to) == PARM_DECL
+             || TREE_CODE (to) == RESULT_DECL)
             && REG_P (DECL_RTL (to)))
            || TREE_CODE (to) == SSA_NAME))
     {
@@ -4748,16 +4883,12 @@ expand_assignment (tree to, tree from, bool nontemporal)
          emit_move_insn (to_rtx, value);
        }
       preserve_temp_slots (to_rtx);
-      free_temp_slots ();
       pop_temp_slots ();
       return;
     }
 
-  /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
-     Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
-
-  if (to_rtx == 0)
-    to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
+  /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.  */
+  to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
   /* Don't move directly into a return register.  */
   if (TREE_CODE (to) == RESULT_DECL
@@ -4766,16 +4897,18 @@ expand_assignment (tree to, tree from, bool nontemporal)
       rtx temp;
 
       push_temp_slots ();
-      temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL);
+      if (REG_P (to_rtx) && TYPE_MODE (TREE_TYPE (from)) == BLKmode)
+       temp = copy_blkmode_to_reg (GET_MODE (to_rtx), from);
+      else
+       temp = expand_expr (from, NULL_RTX, GET_MODE (to_rtx), EXPAND_NORMAL);
 
       if (GET_CODE (to_rtx) == PARALLEL)
        emit_group_load (to_rtx, temp, TREE_TYPE (from),
                         int_size_in_bytes (TREE_TYPE (from)));
-      else
+      else if (temp)
        emit_move_insn (to_rtx, temp);
 
       preserve_temp_slots (to_rtx);
-      free_temp_slots ();
       pop_temp_slots ();
       return;
     }
@@ -4805,7 +4938,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
                         TYPE_MODE (sizetype));
 
       preserve_temp_slots (to_rtx);
-      free_temp_slots ();
       pop_temp_slots ();
       return;
     }
@@ -4815,7 +4947,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
   push_temp_slots ();
   result = store_expr (from, to_rtx, 0, nontemporal);
   preserve_temp_slots (result);
-  free_temp_slots ();
   pop_temp_slots ();
   return;
 }
@@ -5110,8 +5241,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
            {
              enum machine_mode pointer_mode
                = targetm.addr_space.pointer_mode (MEM_ADDR_SPACE (target));
-             enum machine_mode address_mode
-               = targetm.addr_space.address_mode (MEM_ADDR_SPACE (target));
+             enum machine_mode address_mode = get_address_mode (target);
 
              /* Compute the size of the data to copy from the string.  */
              tree copy_size
@@ -5135,7 +5265,8 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
                 Do all calculations in pointer_mode.  */
              if (CONST_INT_P (copy_size_rtx))
                {
-                 size = plus_constant (size, -INTVAL (copy_size_rtx));
+                 size = plus_constant (address_mode, size,
+                                       -INTVAL (copy_size_rtx));
                  target = adjust_address (target, BLKmode,
                                           INTVAL (copy_size_rtx));
                }
@@ -5388,10 +5519,11 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
 
        case VECTOR_CST:
          {
-           tree v;
-           for (v = TREE_VECTOR_CST_ELTS (value); v; v = TREE_CHAIN (v))
+           unsigned i;
+           for (i = 0; i < VECTOR_CST_NELTS (value); ++i)
              {
-               if (!initializer_zerop (TREE_VALUE (v)))
+               tree v = VECTOR_CST_ELT (value, i);
+               if (!initializer_zerop (v))
                  nz_elts += mult;
                init_elts += mult;
              }
@@ -5677,8 +5809,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                offset_rtx = expand_normal (offset);
                gcc_assert (MEM_P (to_rtx));
 
-               address_mode
-                 = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx));
+               address_mode = get_address_mode (to_rtx);
                if (GET_MODE (offset_rtx) != address_mode)
                  offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
@@ -5704,8 +5835,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
                if (TYPE_PRECISION (type) < BITS_PER_WORD)
                  {
-                   type = lang_hooks.types.type_for_size
-                     (BITS_PER_WORD, TYPE_UNSIGNED (type));
+                   type = lang_hooks.types.type_for_mode
+                     (word_mode, TYPE_UNSIGNED (type));
                    value = fold_convert (type, value);
                  }
 
@@ -6175,7 +6306,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
   if (mode == BLKmode
       && (REG_P (target) || GET_CODE (target) == SUBREG))
     {
-      rtx object = assign_temp (type, 0, 1, 1);
+      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)))
@@ -6183,7 +6314,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
 
       store_field (blk_object, bitsize, bitpos,
                   bitregion_start, bitregion_end,
-                  mode, exp, type, alias_set, nontemporal);
+                  mode, exp, type, MEM_ALIAS_SET (blk_object), nontemporal);
 
       emit_move_insn (target, object);
 
@@ -6216,6 +6347,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
                || bitpos % GET_MODE_ALIGNMENT (mode))
               && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target)))
              || (bitpos % BITS_PER_UNIT != 0)))
+      || (bitsize >= 0 && mode != BLKmode
+         && GET_MODE_BITSIZE (mode) > bitsize)
       /* If the RHS and field are a constant size and the size of the
         RHS isn't the same size as the bitfield, we must use bitfield
         operations.  */
@@ -6267,8 +6400,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
                             GET_MODE_BITSIZE (GET_MODE (temp)) - bitsize,
                             NULL_RTX, 1);
 
-      /* Unless MODE is VOIDmode or BLKmode, convert TEMP to
-        MODE.  */
+      /* Unless MODE is VOIDmode or BLKmode, convert TEMP to MODE.  */
       if (mode != VOIDmode && mode != BLKmode
          && mode != TYPE_MODE (TREE_TYPE (exp)))
        temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
@@ -6311,8 +6443,6 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
       if (to_rtx == target)
        to_rtx = copy_rtx (to_rtx);
 
-      if (!MEM_SCALAR_P (to_rtx))
-       MEM_IN_STRUCT_P (to_rtx) = 1;
       if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
        set_mem_alias_set (to_rtx, alias_set);
 
@@ -6544,6 +6674,24 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   /* Otherwise, split it up.  */
   if (offset)
     {
+      /* Avoid returning a negative bitpos as this may wreak havoc later.  */
+      if (double_int_negative_p (bit_offset))
+        {
+         double_int mask
+           = double_int_mask (BITS_PER_UNIT == 8
+                              ? 3 : exact_log2 (BITS_PER_UNIT));
+         double_int tem = double_int_and_not (bit_offset, mask);
+         /* TEM is the bitpos rounded to BITS_PER_UNIT towards -Inf.
+            Subtract it to BIT_OFFSET and add it (scaled) to OFFSET.  */
+         bit_offset = double_int_sub (bit_offset, tem);
+         tem = double_int_rshift (tem,
+                                  BITS_PER_UNIT == 8
+                                  ? 3 : exact_log2 (BITS_PER_UNIT),
+                                  HOST_BITS_PER_DOUBLE_INT, true);
+         offset = size_binop (PLUS_EXPR, offset,
+                              double_int_to_tree (sizetype, tem));
+       }
+
       *pbitpos = double_int_to_shwi (bit_offset);
       *poffset = offset;
     }
@@ -6650,6 +6798,43 @@ array_ref_low_bound (tree exp)
   return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
 }
 
+/* Returns true if REF is an array reference to an array at the end of
+   a structure.  If this is the case, the array may be allocated larger
+   than its upper bound implies.  */
+
+bool
+array_at_struct_end_p (tree ref)
+{
+  if (TREE_CODE (ref) != ARRAY_REF
+      && TREE_CODE (ref) != ARRAY_RANGE_REF)
+    return false;
+
+  while (handled_component_p (ref))
+    {
+      /* If the reference chain contains a component reference to a
+         non-union type and there follows another field the reference
+        is not at the end of a structure.  */
+      if (TREE_CODE (ref) == COMPONENT_REF
+         && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+       {
+         tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+         while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+           nextf = DECL_CHAIN (nextf);
+         if (nextf)
+           return false;
+       }
+
+      ref = TREE_OPERAND (ref, 0);
+    }
+
+  /* If the reference is based on a declared entity, the size of the array
+     is constrained by its given domain.  */
+  if (DECL_P (ref))
+    return false;
+
+  return true;
+}
+
 /* Return a tree representing the upper bound of the array mentioned in
    EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
 
@@ -7082,8 +7267,7 @@ safe_from_p (const_rtx x, tree exp, int top_p)
         are memory and they conflict.  */
       return ! (rtx_equal_p (x, exp_rtl)
                || (MEM_P (x) && MEM_P (exp_rtl)
-                   && true_dependence (exp_rtl, VOIDmode, x,
-                                       rtx_addr_varies_p)));
+                   && true_dependence (exp_rtl, VOIDmode, x)));
     }
 
   /* If we reach here, it is safe.  */
@@ -7181,6 +7365,66 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp)
   return MAX (factor, talign);
 }
 \f
+#ifdef HAVE_conditional_move
+/* Convert the tree comparison code TCODE to the rtl one where the
+   signedness is UNSIGNEDP.  */
+
+static enum rtx_code
+convert_tree_comp_to_rtx (enum tree_code tcode, int unsignedp)
+{
+  enum rtx_code code;
+  switch (tcode)
+    {
+    case EQ_EXPR:
+      code = EQ;
+      break;
+    case NE_EXPR:
+      code = NE;
+      break;
+    case LT_EXPR:
+      code = unsignedp ? LTU : LT;
+      break;
+    case LE_EXPR:
+      code = unsignedp ? LEU : LE;
+      break;
+    case GT_EXPR:
+      code = unsignedp ? GTU : GT;
+      break;
+    case GE_EXPR:
+      code = unsignedp ? GEU : GE;
+      break;
+    case UNORDERED_EXPR:
+      code = UNORDERED;
+      break;
+    case ORDERED_EXPR:
+      code = ORDERED;
+      break;
+    case UNLT_EXPR:
+      code = UNLT;
+      break;
+    case UNLE_EXPR:
+      code = UNLE;
+      break;
+    case UNGT_EXPR:
+      code = UNGT;
+      break;
+    case UNGE_EXPR:
+      code = UNGE;
+      break;
+    case UNEQ_EXPR:
+      code = UNEQ;
+      break;
+    case LTGT_EXPR:
+      code = LTGT;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+  return code;
+}
+#endif
+
 /* Subroutine of expand_expr.  Expand the two operands of a binary
    expression EXP0 and EXP1 placing the results in OP0 and OP1.
    The value may be stored in TARGET if TARGET is nonzero.  The
@@ -7243,7 +7487,12 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
      generating ADDR_EXPR of something that isn't an LVALUE.  The only
      exception here is STRING_CST.  */
   if (CONSTANT_CLASS_P (exp))
-    return XEXP (expand_expr_constant (exp, 0, modifier), 0);
+    {
+      result = XEXP (expand_expr_constant (exp, 0, modifier), 0);
+      if (modifier < EXPAND_SUM)
+       result = force_operand (result, target);
+      return result;
+    }
 
   /* Everything must be something allowed by is_gimple_addressable.  */
   switch (TREE_CODE (exp))
@@ -7262,7 +7511,11 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case CONST_DECL:
       /* Expand the initializer like constants above.  */
-      return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
+      result = XEXP (expand_expr_constant (DECL_INITIAL (exp),
+                                          0, modifier), 0);
+      if (modifier < EXPAND_SUM)
+       result = force_operand (result, target);
+      return result;
 
     case REALPART_EXPR:
       /* The real part of the complex number is always first, therefore
@@ -7313,14 +7566,12 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
          result = XEXP (result, 0);
 
          /* ??? Is this needed anymore?  */
-         if (DECL_P (exp) && !TREE_USED (exp) == 0)
-           {
-             assemble_external (exp);
-             TREE_USED (exp) = 1;
-           }
+         if (DECL_P (exp))
+           TREE_USED (exp) = 1;
 
          if (modifier != EXPAND_INITIALIZER
-             && modifier != EXPAND_CONST_ADDRESS)
+             && modifier != EXPAND_CONST_ADDRESS
+             && modifier != EXPAND_SUM)
            result = force_operand (result, target);
          return result;
        }
@@ -7380,7 +7631,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
         of such an object.  */
       gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
 
-      result = plus_constant (result, bitpos / BITS_PER_UNIT);
+      result = plus_constant (tmode, result, bitpos / BITS_PER_UNIT);
       if (modifier < EXPAND_SUM)
        result = force_operand (result, target);
     }
@@ -7509,7 +7760,7 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
        = assign_temp (build_qualified_type (type, (TYPE_QUALS (type)
                                                    | (TREE_READONLY (exp)
                                                       * TYPE_QUAL_CONST))),
-                      0, TREE_ADDRESSABLE (exp), 1);
+                      TREE_ADDRESSABLE (exp), 1);
     }
 
   store_constructor (exp, target, 0, int_expr_size (exp));
@@ -7612,6 +7863,99 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
   return ret;
 }
 
+/* Try to expand the conditional expression which is represented by
+   TREEOP0 ? TREEOP1 : TREEOP2 using conditonal moves.  If succeseds
+   return the rtl reg which repsents the result.  Otherwise return
+   NULL_RTL.  */
+
+static rtx
+expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
+                             tree treeop1 ATTRIBUTE_UNUSED,
+                             tree treeop2 ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_conditional_move
+  rtx insn;
+  rtx op00, op01, op1, op2;
+  enum rtx_code comparison_code;
+  enum machine_mode comparison_mode;
+  gimple srcstmt;
+  rtx temp;
+  tree type = TREE_TYPE (treeop1);
+  int unsignedp = TYPE_UNSIGNED (type);
+  enum machine_mode mode = TYPE_MODE (type);
+
+  temp = assign_temp (type, 0, 1);
+
+  /* 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;
+
+  start_sequence ();
+  expand_operands (treeop1, treeop2,
+                  temp, &op1, &op2, EXPAND_NORMAL);
+
+  if (TREE_CODE (treeop0) == SSA_NAME
+      && (srcstmt = get_def_for_expr_class (treeop0, tcc_comparison)))
+    {
+      tree type = TREE_TYPE (gimple_assign_rhs1 (srcstmt));
+      enum tree_code cmpcode = gimple_assign_rhs_code (srcstmt);
+      op00 = expand_normal (gimple_assign_rhs1 (srcstmt));
+      op01 = expand_normal (gimple_assign_rhs2 (srcstmt));
+      comparison_mode = TYPE_MODE (type);
+      unsignedp = TYPE_UNSIGNED (type);
+      comparison_code = convert_tree_comp_to_rtx (cmpcode, unsignedp);
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (treeop0)) == tcc_comparison)
+    {
+      tree type = TREE_TYPE (TREE_OPERAND (treeop0, 0));
+      enum tree_code cmpcode = TREE_CODE (treeop0);
+      op00 = expand_normal (TREE_OPERAND (treeop0, 0));
+      op01 = expand_normal (TREE_OPERAND (treeop0, 1));
+      unsignedp = TYPE_UNSIGNED (type);
+      comparison_mode = TYPE_MODE (type);
+      comparison_code = convert_tree_comp_to_rtx (cmpcode, unsignedp);
+    }
+  else
+    {
+      op00 = expand_normal (treeop0);
+      op01 = const0_rtx;
+      comparison_code = NE;
+      comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
+    }
+
+  if (GET_MODE (op1) != mode)
+    op1 = gen_lowpart (mode, op1);
+
+  if (GET_MODE (op2) != mode)
+    op2 = gen_lowpart (mode, op2);
+
+  /* Try to emit the conditional move.  */
+  insn = emit_conditional_move (temp, comparison_code,
+                               op00, op01, comparison_mode,
+                               op1, op2, mode,
+                               unsignedp);
+
+  /* If we could do the conditional move, emit the sequence,
+     and return.  */
+  if (insn)
+    {
+      rtx seq = get_insns ();
+      end_sequence ();
+      emit_insn (seq);
+      return temp;
+    }
+
+  /* Otherwise discard the sequence and fall back to code with
+     branches.  */
+  end_sequence ();
+#endif
+  return NULL_RTX;
+}
+
 rtx
 expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                    enum expand_modifier modifier)
@@ -7698,7 +8042,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
              if (TYPE_MODE (type) != BLKmode)
                target = gen_reg_rtx (TYPE_MODE (type));
              else
-               target = assign_temp (type, 0, 1, 1);
+               target = assign_temp (type, 1, 1);
            }
 
          if (MEM_P (target))
@@ -7823,6 +8167,11 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
        treeop1 = fold_convert_loc (loc, type,
                                    fold_convert_loc (loc, ssizetype,
                                                      treeop1));
+      /* If sizetype precision is larger than pointer precision, truncate the
+        offset to have matching modes.  */
+      else if (TYPE_PRECISION (sizetype) > TYPE_PRECISION (type))
+       treeop1 = fold_convert_loc (loc, type, treeop1);
+
     case PLUS_EXPR:
       /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
         something else, make sure we add the register to the constant and
@@ -7842,10 +8191,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
              || DECL_RTL (treeop1) == stack_pointer_rtx
              || DECL_RTL (treeop1) == arg_pointer_rtx))
        {
-         tree t = treeop1;
-
-         treeop1 = TREE_OPERAND (treeop0, 0);
-         TREE_OPERAND (treeop0, 0) = t;
+         gcc_unreachable ();
        }
 
       /* If the result is to be ptr_mode and we are adding an integer to
@@ -7877,7 +8223,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                = immed_double_const (TREE_INT_CST_LOW (treeop0),
                                      (HOST_WIDE_INT) 0,
                                      TYPE_MODE (TREE_TYPE (treeop1)));
-             op1 = plus_constant (op1, INTVAL (constant_part));
+             op1 = plus_constant (mode, op1, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op1 = force_operand (op1, target);
              return REDUCE_BIT_FIELD (op1);
@@ -7910,7 +8256,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                = immed_double_const (TREE_INT_CST_LOW (treeop1),
                                      (HOST_WIDE_INT) 0,
                                      TYPE_MODE (TREE_TYPE (treeop0)));
-             op0 = plus_constant (op0, INTVAL (constant_part));
+             op0 = plus_constant (mode, op0, INTVAL (constant_part));
              if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                op0 = force_operand (op0, target);
              return REDUCE_BIT_FIELD (op0);
@@ -7972,7 +8318,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
          /* If the last operand is a CONST_INT, use plus_constant of
             the negated constant.  Else make the MINUS.  */
          if (CONST_INT_P (op1))
-           return REDUCE_BIT_FIELD (plus_constant (op0, - INTVAL (op1)));
+           return REDUCE_BIT_FIELD (plus_constant (mode, op0,
+                                                   -INTVAL (op1)));
          else
            return REDUCE_BIT_FIELD (gen_rtx_MINUS (mode, op0, op1));
        }
@@ -8401,8 +8748,9 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       if (modifier == EXPAND_STACK_PARM)
        target = 0;
       /* In case we have to reduce the result to bitfield precision
-        expand this as XOR with a proper constant instead.  */
-      if (reduce_bit_field)
+        for unsigned bitfield expand this as XOR with a proper constant
+        instead.  */
+      if (reduce_bit_field && TYPE_UNSIGNED (type))
        temp = expand_binop (mode, xor_optab, op0,
                             immed_double_int_const
                               (double_int_mask (TYPE_PRECISION (type)), mode),
@@ -8533,30 +8881,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
         return temp;
       }
 
-    case VEC_EXTRACT_EVEN_EXPR:
-    case VEC_EXTRACT_ODD_EXPR:
-      {
-        expand_operands (treeop0,  treeop1,
-                         NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-        this_optab = optab_for_tree_code (code, type, optab_default);
-        temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
-                             OPTAB_WIDEN);
-        gcc_assert (temp);
-        return temp;
-      }
-
-    case VEC_INTERLEAVE_HIGH_EXPR:
-    case VEC_INTERLEAVE_LOW_EXPR:
-      {
-        expand_operands (treeop0,  treeop1,
-                         NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-        this_optab = optab_for_tree_code (code, type, optab_default);
-        temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
-                             OPTAB_WIDEN);
-        gcc_assert (temp);
-        return temp;
-      }
-
     case VEC_LSHIFT_EXPR:
     case VEC_RSHIFT_EXPR:
       {
@@ -8600,12 +8924,49 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
        return target;
       }
 
+    case VEC_WIDEN_LSHIFT_HI_EXPR:
+    case VEC_WIDEN_LSHIFT_LO_EXPR:
+      {
+        tree oprnd0 = treeop0;
+        tree oprnd1 = treeop1;
+
+        expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+        target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
+                                            target, unsignedp);
+        gcc_assert (target);
+        return target;
+      }
+
     case VEC_PACK_TRUNC_EXPR:
     case VEC_PACK_SAT_EXPR:
     case VEC_PACK_FIX_TRUNC_EXPR:
       mode = TYPE_MODE (TREE_TYPE (treeop0));
       goto binop;
 
+    case VEC_PERM_EXPR:
+      expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
+      op2 = expand_normal (treeop2);
+
+      /* Careful here: if the target doesn't support integral vector modes,
+        a constant selection vector could wind up smooshed into a normal
+        integral constant.  */
+      if (CONSTANT_P (op2) && GET_CODE (op2) != CONST_VECTOR)
+       {
+         tree sel_type = TREE_TYPE (treeop2);
+         enum machine_mode vmode
+           = mode_for_vector (TYPE_MODE (TREE_TYPE (sel_type)),
+                              TYPE_VECTOR_SUBPARTS (sel_type));
+         gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
+         op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
+         gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
+       }
+      else
+        gcc_assert (GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT);
+
+      temp = expand_vec_perm (mode, op0, op1, op2, target);
+      gcc_assert (temp);
+      return temp;
+
     case DOT_PROD_EXPR:
       {
        tree oprnd0 = treeop0;
@@ -8652,6 +9013,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                  && TREE_TYPE (treeop1) != void_type_node
                  && TREE_TYPE (treeop2) != void_type_node);
 
+      temp = expand_cond_expr_using_cmove (treeop0, treeop1, treeop2);
+      if (temp)
+       return temp;
+
       /* If we are not to produce a result, we have no target.  Otherwise,
         if a target was specified use it; it will not be used as an
         intermediate target unless it is safe.  If no target, use a
@@ -8661,14 +9026,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
          && original_target
          && safe_from_p (original_target, treeop0, 1)
          && GET_MODE (original_target) == mode
-#ifdef HAVE_conditional_move
-         && (! can_conditionally_move_p (mode)
-             || REG_P (original_target))
-#endif
          && !MEM_P (original_target))
        temp = original_target;
       else
-       temp = assign_temp (type, 0, 0, 1);
+       temp = assign_temp (type, 0, 1);
 
       do_pending_stack_adjust ();
       NO_DEFER_POP;
@@ -8862,8 +9223,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
        g = SSA_NAME_DEF_STMT (exp);
       if (g)
-       return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode,
-                                modifier, NULL);
+       {
+         rtx r = expand_expr_real (gimple_assign_rhs_to_tree (g), target,
+                                   tmode, modifier, NULL);
+         if (REG_P (r) && !REG_EXPR (r))
+           set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r);
+         return r;
+       }
 
       ssa_name = exp;
       decl_rtl = get_rtx_for_ssa_name (ssa_name);
@@ -8897,11 +9263,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* Ensure variable marked as used even if it doesn't go through
         a parser.  If it hasn't be used yet, write out an external
         definition.  */
-      if (! TREE_USED (exp))
-       {
-         assemble_external (exp);
-         TREE_USED (exp) = 1;
-       }
+      TREE_USED (exp) = 1;
 
       /* Show we haven't gotten RTL for this yet.  */
       temp = 0;
@@ -8918,7 +9280,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       /* This is the case of an array whose size is to be determined
         from its initializer, while the initializer is still being parsed.
-        See expand_decl.  */
+        ??? We aren't parsing while expanding anymore.  */
 
       if (MEM_P (decl_rtl) && REG_P (XEXP (decl_rtl, 0)))
        temp = validize_mem (decl_rtl);
@@ -8950,10 +9312,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          return temp;
        }
 
-      /* If the mode of DECL_RTL does not match that of the decl, it
-        must be a promoted value.  We return a SUBREG of the wanted mode,
-        but mark it so that we know that it was already extended.  */
-      if (REG_P (decl_rtl) && GET_MODE (decl_rtl) != DECL_MODE (exp))
+      /* If the mode of DECL_RTL does not match that of the decl,
+        there are two cases: we are dealing with a BLKmode value
+        that is returned in a register, or we are dealing with
+        a promoted value.  In the latter case, return a SUBREG
+        of the wanted mode, but mark it so that we know that it
+        was already extended.  */
+      if (REG_P (decl_rtl)
+         && DECL_MODE (exp) != BLKmode
+         && GET_MODE (decl_rtl) != DECL_MODE (exp))
        {
          enum machine_mode pmode;
 
@@ -9003,8 +9370,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR, type_for_mode, exp);
          }
        if (!tmp)
-         tmp = build_constructor_from_list (type,
-                                            TREE_VECTOR_CST_ELTS (exp));
+         {
+           VEC(constructor_elt,gc) *v;
+           unsigned i;
+           v = VEC_alloc (constructor_elt, gc, 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);
+         }
        return expand_expr (tmp, ignore ? const0_rtx : target,
                            tmode, modifier);
       }
@@ -9117,10 +9490,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case TARGET_MEM_REF:
       {
-       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
+       addr_space_t as
+         = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
        struct mem_address addr;
        enum insn_code icode;
-       int align;
+       unsigned int align;
 
        get_address_description (exp, &addr);
        op0 = addr_for_mem_ref (&addr, as, true);
@@ -9128,9 +9502,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        temp = gen_rtx_MEM (mode, op0);
        set_mem_attributes (temp, exp, 0);
        set_mem_addr_space (temp, as);
-       align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
-       if (mode != BLKmode
-           && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+       align = get_object_or_type_alignment (exp);
+       if (modifier != EXPAND_WRITE
+           && mode != BLKmode
+           && align < GET_MODE_ALIGNMENT (mode)
            /* If the target does not have special handling for unaligned
               loads of mode then it can use regular moves for them.  */
            && ((icode = optab_handler (movmisalign_optab, mode))
@@ -9152,52 +9527,45 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case MEM_REF:
       {
        addr_space_t as
-         = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))));
+         = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
        enum machine_mode address_mode;
        tree base = TREE_OPERAND (exp, 0);
        gimple def_stmt;
        enum insn_code icode;
-       int align;
+       unsigned align;
        /* Handle expansion of non-aliased memory with non-BLKmode.  That
           might end up in a register.  */
-       if (TREE_CODE (base) == ADDR_EXPR)
+       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 (!DECL_P (base))
-             {
-               HOST_WIDE_INT off;
-               base = get_addr_base_and_unit_offset (base, &off);
-               gcc_assert (base);
-               offset += off;
-             }
-           /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
-              decl we must use bitfield operations.  */
-           if (DECL_P (base)
-               && !TREE_ADDRESSABLE (base)
-               && DECL_MODE (base) != BLKmode
-               && DECL_RTL_SET_P (base)
-               && !MEM_P (DECL_RTL (base)))
+           if (offset == 0
+               && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 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),
+                                 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
              {
-               tree bftype;
-               if (offset == 0
-                   && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 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),
-                                     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);
-               return expand_expr (build3 (BIT_FIELD_REF, bftype,
-                                           base,
-                                           TYPE_SIZE (TREE_TYPE (exp)),
-                                           bit_offset),
-                                   target, tmode, modifier);
+               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)));
+               return temp;
              }
+           return expand_expr (build3 (BIT_FIELD_REF, bftype,
+                                       base,
+                                       TYPE_SIZE (TREE_TYPE (exp)),
+                                       bit_offset),
+                               target, tmode, modifier);
          }
        address_mode = targetm.addr_space.address_mode (as);
        base = TREE_OPERAND (exp, 0);
@@ -9208,7 +9576,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                           gimple_assign_rhs1 (def_stmt), mask);
            TREE_OPERAND (exp, 0) = base;
          }
-       align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+       align = get_object_or_type_alignment (exp);
        op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address_addr_space (address_mode, op0, as);
        if (!integer_zerop (TREE_OPERAND (exp, 1)))
@@ -9223,22 +9591,29 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        set_mem_addr_space (temp, as);
        if (TREE_THIS_VOLATILE (exp))
          MEM_VOLATILE_P (temp) = 1;
-       if (mode != BLKmode
-           && (unsigned) align < GET_MODE_ALIGNMENT (mode)
-           /* If the target does not have special handling for unaligned
-              loads of mode then it can use regular moves for them.  */
-           && ((icode = optab_handler (movmisalign_optab, mode))
-               != CODE_FOR_nothing))
+       if (modifier != EXPAND_WRITE
+           && mode != BLKmode
+           && align < GET_MODE_ALIGNMENT (mode))
          {
-           struct expand_operand ops[2];
-
-           /* We've already validated the memory, and we're creating a
-              new pseudo destination.  The predicates really can't fail,
-              nor can the generator.  */
-           create_output_operand (&ops[0], NULL_RTX, mode);
-           create_fixed_operand (&ops[1], temp);
-           expand_insn (icode, 2, ops);
-           return ops[0].value;
+           if ((icode = optab_handler (movmisalign_optab, mode))
+               != CODE_FOR_nothing)
+             {
+               struct expand_operand ops[2];
+
+               /* We've already validated the memory, and we're creating a
+                  new pseudo destination.  The predicates really can't fail,
+                  nor can the generator.  */
+               create_output_operand (&ops[0], NULL_RTX, mode);
+               create_fixed_operand (&ops[1], temp);
+               expand_insn (icode, 2, ops);
+               return ops[0].value;
+             }
+           else if (SLOW_UNALIGNED_ACCESS (mode, align))
+             temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode),
+                                       0, TYPE_UNSIGNED (TREE_TYPE (exp)),
+                                       true, (modifier == EXPAND_STACK_PARM
+                                              ? NULL_RTX : target),
+                                       mode, mode);
          }
        return temp;
       }
@@ -9435,6 +9810,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
                                        &mode1, &unsignedp, &volatilep, true);
        rtx orig_op0, memloc;
+       bool mem_attrs_from_type = false;
 
        /* If we got back the original object, something is wrong.  Perhaps
           we are evaluating an expression too early.  In any event, don't
@@ -9537,9 +9913,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            tree nt = build_qualified_type (TREE_TYPE (tem),
                                            (TYPE_QUALS (TREE_TYPE (tem))
                                             | TYPE_QUAL_CONST));
-           memloc = assign_temp (nt, 1, 1, 1);
+           memloc = assign_temp (nt, 1, 1);
            emit_move_insn (memloc, op0);
            op0 = memloc;
+           mem_attrs_from_type = true;
          }
 
        if (offset)
@@ -9550,8 +9927,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
            gcc_assert (MEM_P (op0));
 
-           address_mode
-             = targetm.addr_space.address_mode (MEM_ADDR_SPACE (op0));
+           address_mode = get_address_mode (op0);
            if (GET_MODE (offset_rtx) != address_mode)
              offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
 
@@ -9601,11 +9977,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                && modifier != EXPAND_CONST_ADDRESS
                && modifier != EXPAND_INITIALIZER)
            /* If the field is volatile, we always want an aligned
-              access.  Only do this if the access is not already naturally
+              access.  Do this in following two situations:
+              1. the access is not already naturally
               aligned, otherwise "normal" (non-bitfield) volatile fields
-              become non-addressable.  */
+              become non-addressable.
+              2. the bitsize is narrower than the access size. Need
+              to extract bitfields from the access.  */
            || (volatilep && flag_strict_volatile_bitfields > 0
-               && (bitpos % GET_MODE_ALIGNMENT (mode) != 0))
+               && (bitpos % GET_MODE_ALIGNMENT (mode) != 0 
+                   || (mode1 != BLKmode
+                       && bitsize < GET_MODE_SIZE (mode1) * BITS_PER_UNIT)))
            /* If the field isn't aligned enough to fetch as a memref,
               fetch it as a bit field.  */
            || (mode1 != BLKmode
@@ -9639,7 +10020,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            if (ext_mode == BLKmode)
              {
                if (target == 0)
-                 target = assign_temp (type, 0, 1, 1);
+                 target = assign_temp (type, 1, 1);
 
                if (bitsize == 0)
                  return target;
@@ -9691,23 +10072,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
               necessarily be constant.  */
            if (mode == BLKmode)
              {
-               HOST_WIDE_INT size = GET_MODE_BITSIZE (ext_mode);
                rtx new_rtx;
 
-               /* If the reference doesn't use the alias set of its type,
-                  we cannot create the temporary using that type.  */
-               if (component_uses_parent_alias_set (exp))
-                 {
-                   new_rtx = assign_stack_local (ext_mode, size, 0);
-                   set_mem_alias_set (new_rtx, get_alias_set (exp));
-                 }
-               else
-                 new_rtx = assign_stack_temp_for_type (ext_mode, size, 0, type);
-
+               new_rtx = assign_stack_temp_for_type (ext_mode,
+                                                  GET_MODE_BITSIZE (ext_mode),
+                                                  type);
                emit_move_insn (new_rtx, op0);
                op0 = copy_rtx (new_rtx);
                PUT_MODE (op0, BLKmode);
-               set_mem_attributes (op0, exp, 1);
              }
 
            return op0;
@@ -9728,7 +10100,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        if (op0 == orig_op0)
          op0 = copy_rtx (op0);
 
-       set_mem_attributes (op0, exp, 0);
+       /* If op0 is a temporary because of forcing to memory, pass only the
+          type to set_mem_attributes so that the original expression is never
+          marked as ADDRESSABLE through MEM_EXPR of the temporary.  */
+       if (mem_attrs_from_type)
+         set_mem_attributes (op0, type, 0);
+       else
+         set_mem_attributes (op0, exp, 0);
+
        if (REG_P (XEXP (op0, 0)))
          mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
 
@@ -9889,7 +10268,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            target
              = assign_stack_temp_for_type
                (TYPE_MODE (inner_type),
-                GET_MODE_SIZE (TYPE_MODE (inner_type)), 0, inner_type);
+                GET_MODE_SIZE (TYPE_MODE (inner_type)), inner_type);
 
          emit_move_insn (target, op0);
          op0 = target;
@@ -9901,10 +10280,32 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         results.  */
       if (MEM_P (op0))
        {
+         enum insn_code icode;
+
          op0 = copy_rtx (op0);
 
          if (TYPE_ALIGN_OK (type))
            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
+                     loads of mode then use them.  */
+                  && ((icode = optab_handler (movmisalign_optab, mode))
+                      != CODE_FOR_nothing))
+           {
+             rtx reg, insn;
+
+             op0 = adjust_address (op0, mode, 0);
+             /* We've already validated the memory, and we're creating a
+                new pseudo destination.  The predicates really can't
+                fail.  */
+             reg = gen_reg_rtx (mode);
+
+             /* Nor can the insn generator.  */
+             insn = GEN_FCN (icode) (reg, op0);
+             emit_insn (insn);
+             return reg;
+           }
          else if (STRICT_ALIGNMENT
                   && mode != BLKmode
                   && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode))
@@ -9914,7 +10315,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                = MAX (int_size_in_bytes (inner_type),
                       (HOST_WIDE_INT) GET_MODE_SIZE (mode));
              rtx new_rtx
-               = assign_stack_temp_for_type (mode, temp_size, 0, type);
+               = assign_stack_temp_for_type (mode, temp_size, type);
              rtx new_with_op0_mode
                = adjust_address (new_rtx, GET_MODE (op0), 0);
 
@@ -10015,6 +10416,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case POSTDECREMENT_EXPR:
     case LOOP_EXPR:
     case EXIT_EXPR:
+    case COMPOUND_LITERAL_EXPR:
       /* Lowered by gimplify.c.  */
       gcc_unreachable ();
 
@@ -10029,27 +10431,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return expand_expr_real (treeop0, original_target, tmode,
                               modifier, alt_rtl);
 
-    case COMPOUND_LITERAL_EXPR:
-      {
-       /* Initialize the anonymous variable declared in the compound
-          literal, then return the variable.  */
-       tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
-
-       /* Create RTL for this variable.  */
-       if (!DECL_RTL_SET_P (decl))
-         {
-           if (DECL_HARD_REGISTER (decl))
-             /* The user specified an assembler name for this variable.
-                Set that up now.  */
-             rest_of_decl_compilation (decl, 0, 0);
-           else
-             expand_decl (decl);
-         }
-
-       return expand_expr_real (decl, original_target, tmode,
-                                modifier, alt_rtl);
-      }
-
     default:
       return expand_expr_real_2 (&ops, target, tmode, modifier);
     }
@@ -10308,6 +10689,28 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
 
   STRIP_NOPS (arg0);
   STRIP_NOPS (arg1);
+  
+  /* For vector typed comparisons emit code to generate the desired
+     all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
+     expander for this.  */
+  if (TREE_CODE (ops->type) == VECTOR_TYPE)
+    {
+      tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
+      tree if_true = constant_boolean_node (true, ops->type);
+      tree if_false = constant_boolean_node (false, ops->type);
+      return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target);
+    }
+
+  /* For vector typed comparisons emit code to generate the desired
+     all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
+     expander for this.  */
+  if (TREE_CODE (ops->type) == VECTOR_TYPE)
+    {
+      tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
+      tree if_true = constant_boolean_node (true, ops->type);
+      tree if_false = constant_boolean_node (false, ops->type);
+      return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target);
+    }
 
   /* Get the rtx comparison code to use.  We know that EXP is a comparison
      operation of some type.  Some comparisons against 1 and -1 can be
@@ -10396,15 +10799,22 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
      so we just call into the folder and expand its result.  */
 
   if ((code == NE || code == EQ)
-      && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
-      && integer_pow2p (TREE_OPERAND (arg0, 1))
+      && integer_zerop (arg1)
       && (TYPE_PRECISION (ops->type) != 1 || TYPE_UNSIGNED (ops->type)))
     {
-      tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
-      return expand_expr (fold_single_bit_test (loc,
-                                               code == NE ? NE_EXPR : EQ_EXPR,
-                                               arg0, arg1, type),
-                         target, VOIDmode, EXPAND_NORMAL);
+      gimple srcstmt = get_def_for_expr (arg0, BIT_AND_EXPR);
+      if (srcstmt
+         && integer_pow2p (gimple_assign_rhs2 (srcstmt)))
+       {
+         enum tree_code tcode = code == NE ? NE_EXPR : EQ_EXPR;
+         tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
+         tree temp = fold_build2_loc (loc, BIT_AND_EXPR, TREE_TYPE (arg1),
+                                      gimple_assign_rhs1 (srcstmt),
+                                      gimple_assign_rhs2 (srcstmt));
+         temp = fold_single_bit_test (loc, tcode, temp, arg1, type);
+         if (temp)
+           return expand_expr (temp, target, VOIDmode, EXPAND_NORMAL);
+       }
     }
 
   if (! get_subtarget (target)
@@ -10440,7 +10850,6 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
 {
   struct expand_operand ops[5];
   enum machine_mode index_mode = SImode;
-  int index_bits = GET_MODE_BITSIZE (index_mode);
   rtx op1, op2, index;
 
   if (! HAVE_casesi)
@@ -10467,7 +10876,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
     {
       if (TYPE_MODE (index_type) != index_mode)
        {
-         index_type = lang_hooks.types.type_for_size (index_bits, 0);
+         index_type = lang_hooks.types.type_for_mode (index_mode, 0);
          index_expr = fold_convert (index_type, index_expr);
        }
 
@@ -10596,8 +11005,9 @@ static rtx
 const_vector_from_tree (tree exp)
 {
   rtvec v;
-  int units, i;
-  tree link, elt;
+  unsigned i;
+  int units;
+  tree elt;
   enum machine_mode inner, mode;
 
   mode = TYPE_MODE (TREE_TYPE (exp));
@@ -10610,10 +11020,9 @@ const_vector_from_tree (tree exp)
 
   v = rtvec_alloc (units);
 
-  link = TREE_VECTOR_CST_ELTS (exp);
-  for (i = 0; link; link = TREE_CHAIN (link), ++i)
+  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
     {
-      elt = TREE_VALUE (link);
+      elt = VECTOR_CST_ELT (exp, i);
 
       if (TREE_CODE (elt) == REAL_CST)
        RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
@@ -10626,10 +11035,6 @@ const_vector_from_tree (tree exp)
                                                   inner);
     }
 
-  /* Initialize remaining elements to 0.  */
-  for (; i < units; ++i)
-    RTVEC_ELT (v, i) = CONST0_RTX (inner);
-
   return gen_rtx_CONST_VECTOR (mode, v);
 }