OSDN Git Service

* init.c (build_new): Allow enumeration types for the array-bounds
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 07fa592..f4ff9b2 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
-   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -19,7 +19,6 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 #include "config.h"
 #include "system.h"
 #include "machmode.h"
@@ -34,13 +33,12 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-flags.h"
 #include "insn-codes.h"
 #include "insn-config.h"
-/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
+/* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
 #include "expr.h"
 #include "recog.h"
 #include "reload.h"
 #include "output.h"
 #include "typeclass.h"
-#include "defaults.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "intl.h"
@@ -68,7 +66,7 @@ Boston, MA 02111-1307, USA.  */
 #ifdef PUSH_ROUNDING
 
 #if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
-#define PUSH_ARGS_REVERSED     /* If it's last to first */
+#define PUSH_ARGS_REVERSED     /* If it's last to first */
 #endif
 
 #endif
@@ -86,6 +84,15 @@ Boston, MA 02111-1307, USA.  */
 #define CASE_VECTOR_PC_RELATIVE 0
 #endif
 
+/* Hook called by safe_from_p for language-specific tree codes.  It is
+   up to the language front-end to install a hook if it has any such
+   codes that safe_from_p needs to know about.  Since same_from_p will
+   recursively explore the TREE_OPERANDs of an expression, this hook
+   should not reexamine those pieces.  This routine may recursively
+   call safe_from_p; it should always pass `0' as the TOP_P
+   parameter.  */
+int (*lang_safe_from_p) PARAMS ((rtx, tree));
+
 /* If this is nonzero, we do not bother generating VOLATILE
    around volatile memory references, and we are willing to
    output indirect addresses.  If cse is to follow, we reject
@@ -94,11 +101,6 @@ Boston, MA 02111-1307, USA.  */
    the same indirect address eventually.  */
 int cse_not_expected;
 
-/* Nonzero to generate code for all the subroutines within an
-   expression before generating the upper levels of the expression.
-   Nowadays this is never zero.  */
-int do_preexpand_calls = 1;
-
 /* Don't check memory usage, since code is being emitted to check a memory
    usage.  Used when current_function_check_memory_usage is true, to avoid
    infinite recursion.  */
@@ -124,10 +126,10 @@ struct move_by_pieces
   int reverse;
 };
 
-/* This structure is used by clear_by_pieces to describe the clear to
+/* This structure is used by store_by_pieces to describe the clear to
    be performed.  */
 
-struct clear_by_pieces
+struct store_by_pieces
 {
   rtx to;
   rtx to_addr;
@@ -135,6 +137,8 @@ struct clear_by_pieces
   int explicit_inc_to;
   unsigned HOST_WIDE_INT len;
   HOST_WIDE_INT offset;
+  rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
+  PTR constfundata;
   int reverse;
 };
 
@@ -148,17 +152,22 @@ static unsigned HOST_WIDE_INT move_by_pieces_ninsns
                                         unsigned int));
 static void move_by_pieces_1   PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
                                         struct move_by_pieces *));
+static rtx clear_by_pieces_1   PARAMS ((PTR, HOST_WIDE_INT,
+                                        enum machine_mode));
 static void clear_by_pieces    PARAMS ((rtx, unsigned HOST_WIDE_INT,
                                         unsigned int));
-static void clear_by_pieces_1  PARAMS ((rtx (*) (rtx, ...),
+static void store_by_pieces_1  PARAMS ((struct store_by_pieces *,
+                                        unsigned int));
+static void store_by_pieces_2  PARAMS ((rtx (*) (rtx, ...),
                                         enum machine_mode,
-                                        struct clear_by_pieces *));
+                                        struct store_by_pieces *));
 static rtx get_subtarget       PARAMS ((rtx));
 static int is_zeros_p          PARAMS ((tree));
 static int mostly_zeros_p      PARAMS ((tree));
 static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
                                             HOST_WIDE_INT, enum machine_mode,
-                                            tree, tree, unsigned int, int));
+                                            tree, tree, unsigned int, int,
+                                            int));
 static void store_constructor  PARAMS ((tree, rtx, unsigned int, int,
                                         HOST_WIDE_INT));
 static rtx store_field         PARAMS ((rtx, HOST_WIDE_INT,
@@ -169,13 +178,10 @@ static enum memory_use_mode
   get_memory_usage_from_modifier PARAMS ((enum expand_modifier));
 static tree save_noncopied_parts PARAMS ((tree, tree));
 static tree init_noncopied_parts PARAMS ((tree, tree));
-static int safe_from_p         PARAMS ((rtx, tree, int));
 static int fixed_type_p                PARAMS ((tree));
 static rtx var_rtx             PARAMS ((tree));
-static int readonly_fields_p   PARAMS ((tree));
 static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
-static void preexpand_calls    PARAMS ((tree));
 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
 static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
 static void do_compare_and_jump        PARAMS ((tree, enum rtx_code, enum rtx_code,
@@ -196,16 +202,16 @@ static char direct_store[NUM_MACHINE_MODES];
 #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
 #define MOVE_RATIO 2
 #else
-/* If we are optimizing for space (-Os), cut down the default move ratio */
+/* If we are optimizing for space (-Os), cut down the default move ratio */
 #define MOVE_RATIO (optimize_size ? 3 : 15)
 #endif
 #endif
 
 /* This macro is used to determine whether move_by_pieces should be called
-   to perform a structure copy. */
+   to perform a structure copy.  */
 #ifndef MOVE_BY_PIECES_P
 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
-  (move_by_pieces_ninsns (SIZE, ALIGN) < MOVE_RATIO)
+  (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
 #endif
 
 /* This array records the insn_code of insns to perform block moves.  */
@@ -230,15 +236,9 @@ init_expr_once ()
   enum machine_mode mode;
   int num_clobbers;
   rtx mem, mem1;
-  char *free_point;
 
   start_sequence ();
 
-  /* Since we are on the permanent obstack, we must be sure we save this
-     spot AFTER we call start_sequence, since it will reuse the rtl it
-     makes.  */
-  free_point = (char *) oballoc (0);
-
   /* Try indexing by frame ptr and try by stack ptr.
      It is known that on the Convex the stack ptr isn't a valid index.
      With luck, one or the other is valid on any machine.  */
@@ -294,7 +294,6 @@ init_expr_once ()
     }
 
   end_sequence ();
-  obfree (free_point);
 }
 
 /* This is run at the start of compiling a function.  */
@@ -545,9 +544,26 @@ convert_move (to, from, unsignedp)
       return;
     }
 
+  if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
+    {
+      if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
+       abort ();
+
+      if (VECTOR_MODE_P (to_mode))
+       from = gen_rtx_SUBREG (to_mode, from, 0);
+      else
+       to = gen_rtx_SUBREG (from_mode, to, 0);
+
+      emit_move_insn (to, from);
+      return;
+    }
+
+  if (to_real != from_real)
+    abort ();
+
   if (to_real)
     {
-      rtx value;
+      rtx value, insns;
 
       if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
        {
@@ -559,7 +575,7 @@ convert_move (to, from, unsignedp)
              return;
            }
        }
+
 #ifdef HAVE_trunchfqf2
       if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
        {
@@ -721,7 +737,7 @@ convert_move (to, from, unsignedp)
            case TFmode:
              libcall = extendsftf2_libfunc;
              break;
-             
+
            default:
              break;
            }
@@ -741,7 +757,7 @@ convert_move (to, from, unsignedp)
            case TFmode:
              libcall = extenddftf2_libfunc;
              break;
-             
+
            default:
              break;
            }
@@ -757,7 +773,7 @@ convert_move (to, from, unsignedp)
            case DFmode:
              libcall = truncxfdf2_libfunc;
              break;
-             
+
            default:
              break;
            }
@@ -773,12 +789,12 @@ convert_move (to, from, unsignedp)
            case DFmode:
              libcall = trunctfdf2_libfunc;
              break;
-             
+
            default:
              break;
            }
          break;
-         
+
        default:
          break;
        }
@@ -787,9 +803,13 @@ convert_move (to, from, unsignedp)
        /* This conversion is not implemented yet.  */
        abort ();
 
-      value = emit_library_call_value (libcall, NULL_RTX, 1, to_mode,
+      start_sequence ();
+      value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
                                       1, from, from_mode);
-      emit_move_insn (to, value);
+      insns = get_insns ();
+      end_sequence ();
+      emit_libcall_block (insns, to, value, gen_rtx_FLOAT_TRUNCATE (to_mode,
+                                                                   from));
       return;
     }
 
@@ -915,7 +935,7 @@ convert_move (to, from, unsignedp)
       return;
     }
 
-  /* Handle pointer conversion */                      /* SPEE 900220 */
+  /* Handle pointer conversion.  */                    /* SPEE 900220.  */
   if (to_mode == PQImode)
     {
       if (from_mode != QImode)
@@ -976,12 +996,19 @@ convert_move (to, from, unsignedp)
       else
        {
 #ifdef HAVE_extendpsisi2
-         if (HAVE_extendpsisi2)
+         if (! unsignedp && HAVE_extendpsisi2)
            {
              emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
              return;
            }
 #endif /* HAVE_extendpsisi2 */
+#ifdef HAVE_zero_extendpsisi2
+         if (unsignedp && HAVE_zero_extendpsisi2)
+           {
+             emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
+             return;
+           }
+#endif /* HAVE_zero_extendpsisi2 */
          abort ();
        }
     }
@@ -1076,13 +1103,13 @@ convert_move (to, from, unsignedp)
              }
 
          /* No suitable intermediate mode.
-            Generate what we need with shifts. */
+            Generate what we need with shifts.  */
          shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
                                      - GET_MODE_BITSIZE (from_mode), 0);
          from = gen_lowpart (to_mode, force_reg (from_mode, from));
          tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
                              to, unsignedp);
-         tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp,  shift_amount,
+         tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
                              to, unsignedp);
          if (tmp != to)
            emit_move_insn (to, tmp);
@@ -1090,7 +1117,7 @@ convert_move (to, from, unsignedp)
        }
     }
 
-  /* Support special truncate insns for certain modes.  */ 
+  /* Support special truncate insns for certain modes.  */
 
   if (from_mode == DImode && to_mode == SImode)
     {
@@ -1286,7 +1313,7 @@ convert_modes (mode, oldmode, x, unsignedp)
 
   if (GET_MODE (x) != VOIDmode)
     oldmode = GET_MODE (x);
+
   if (mode == oldmode)
     return x;
 
@@ -1358,13 +1385,12 @@ convert_modes (mode, oldmode, x, unsignedp)
   return temp;
 }
 \f
-
 /* This macro is used to determine what the largest unit size that
-   move_by_pieces can use is. */
+   move_by_pieces can use is.  */
 
 /* MOVE_MAX_PIECES is the number of bytes at a time which we can
    move efficiently, as opposed to  MOVE_MAX which is the maximum
-   number of bytes we can move with a single instruction. */
+   number of bytes we can move with a single instruction.  */
 
 #ifndef MOVE_MAX_PIECES
 #define MOVE_MAX_PIECES   MOVE_MAX
@@ -1414,7 +1440,7 @@ move_by_pieces (to, from, len, align)
   if (!(data.autinc_from && data.autinc_to)
       && move_by_pieces_ninsns (len, align) > 2)
     {
-      /* Find the mode of the largest move... */
+      /* Find the mode of the largest move...  */
       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
        if (GET_MODE_SIZE (tmode) < max_size)
@@ -1514,6 +1540,8 @@ move_by_pieces_ninsns (l, align)
       max_size = GET_MODE_SIZE (mode);
     }
 
+  if (l)
+    abort ();
   return n_insns;
 }
 
@@ -1685,7 +1713,7 @@ emit_block_move (x, y, size, align)
         To avoid this problem we go ahead and emit code to copy X, Y &
         SIZE into new pseudos.  We can then place those new pseudos
         into an RTL_EXPR and use them later, even after a call to
-        emit_queue. 
+        emit_queue.
 
         Note this is not strictly needed for library calls since they
         do not call emit_queue before loading their arguments.  However,
@@ -1711,7 +1739,7 @@ emit_block_move (x, y, size, align)
         examine the return value from memcpy.
 
         For targets where libcalls and normal calls have different conventions
-        for returning pointers, we could end up generating incorrect code. 
+        for returning pointers, we could end up generating incorrect code.
 
         So instead of using a libcall sequence we build up a suitable
         CALL_EXPR and expand the call in the normal fashion.  */
@@ -1722,21 +1750,18 @@ emit_block_move (x, y, size, align)
          /* This was copied from except.c, I don't know if all this is
             necessary in this context or not.  */
          fn = get_identifier ("memcpy");
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
          fntype = build_pointer_type (void_type_node);
          fntype = build_function_type (fntype, NULL_TREE);
          fn = build_decl (FUNCTION_DECL, fn, fntype);
-         ggc_add_tree_root (&fn, 1);
+         ggc_add_tree_root (&fn, 1);
          DECL_EXTERNAL (fn) = 1;
          TREE_PUBLIC (fn) = 1;
          DECL_ARTIFICIAL (fn) = 1;
-         make_decl_rtl (fn, NULL_PTR, 1);
+         make_decl_rtl (fn, NULL_PTR);
          assemble_external (fn);
-         pop_obstacks ();
        }
 
-      /* We need to make an argument list for the function call. 
+      /* We need to make an argument list for the function call.
 
         memcpy has three arguments, the first two are void * addresses and
         the last is a size_t byte count for the copy.  */
@@ -1758,7 +1783,7 @@ emit_block_move (x, y, size, align)
 
       retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 #else
-      emit_library_call (bcopy_libfunc, 0,
+      emit_library_call (bcopy_libfunc, LCT_NORMAL,
                         VOIDmode, 3, y, Pmode, x, Pmode,
                         convert_to_mode (TYPE_MODE (integer_type_node), size,
                                          TREE_UNSIGNED (integer_type_node)),
@@ -1781,7 +1806,7 @@ move_block_to_reg (regno, x, nregs, mode)
 {
   int i;
 #ifdef HAVE_load_multiple
-  rtx pat; 
+  rtx pat;
   rtx last;
 #endif
 
@@ -1817,7 +1842,6 @@ move_block_to_reg (regno, x, nregs, mode)
    The number of registers to be filled is NREGS.  SIZE indicates the number
    of bytes in the object X.  */
 
-
 void
 move_block_from_reg (regno, x, nregs, size)
      int regno;
@@ -1827,11 +1851,14 @@ move_block_from_reg (regno, x, nregs, size)
 {
   int i;
 #ifdef HAVE_store_multiple
-  rtx pat; 
+  rtx pat;
   rtx last;
 #endif
   enum machine_mode mode;
 
+  if (nregs == 0)
+    return;
+
   /* If SIZE is that of a mode no bigger than a word, just use that
      mode's store operation.  */
   if (size <= UNITS_PER_WORD
@@ -1841,7 +1868,7 @@ move_block_from_reg (regno, x, nregs, size)
                      gen_rtx_REG (mode, regno));
       return;
     }
-    
+
   /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
      to the left before storing to memory.  Note that the previous test
      doesn't handle all cases (e.g. SIZE == 3).  */
@@ -1919,12 +1946,12 @@ emit_group_load (dst, orig_src, ssize, align)
   else
     start = 1;
 
-  tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (dst, 0));
+  tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
 
   /* If we won't be loading directly from memory, protect the real source
      from strange tricks we might play.  */
   src = orig_src;
-  if (GET_CODE (src) != MEM)
+  if (GET_CODE (src) != MEM && ! CONSTANT_P (src))
     {
       if (GET_MODE (src) == VOIDmode)
        src = gen_reg_rtx (GET_MODE (dst));
@@ -1942,7 +1969,7 @@ emit_group_load (dst, orig_src, ssize, align)
       int shift = 0;
 
       /* Handle trailing fragments that run over the size of the struct.  */
-      if (ssize >= 0 && bytepos + bytelen > ssize)
+      if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
        {
          shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
          bytelen = ssize - bytepos;
@@ -1967,12 +1994,16 @@ emit_group_load (dst, orig_src, ssize, align)
          if (bytepos == 0
              && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
            tmps[i] = XEXP (src, 0);
-         else if (bytepos == GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
+         else if (bytepos == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
                   && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 1))))
            tmps[i] = XEXP (src, 1);
          else
            abort ();
        }
+      else if ((CONSTANT_P (src)
+               && (GET_MODE (src) == VOIDmode || GET_MODE (src) == mode))
+              || (GET_CODE (src) == REG && GET_MODE (src) == mode))
+       tmps[i] = src;
       else
        tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
                                     bytepos * BITS_PER_UNIT, 1, NULL_RTX,
@@ -1983,7 +2014,7 @@ emit_group_load (dst, orig_src, ssize, align)
                      tmps[i], 0, OPTAB_WIDEN);
     }
 
-  emit_queue();
+  emit_queue ();
 
   /* Copy the extracted pieces into the proper (probable) hard regs.  */
   for (i = start; i < XVECLEN (dst, 0); i++)
@@ -2013,7 +2044,7 @@ emit_group_store (orig_dst, src, ssize, align)
   else
     start = 1;
 
-  tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (src, 0));
+  tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
 
   /* Copy the (probable) hard regs into pseudos.  */
   for (i = start; i < XVECLEN (src, 0); i++)
@@ -2022,7 +2053,7 @@ emit_group_store (orig_dst, src, ssize, align)
       tmps[i] = gen_reg_rtx (GET_MODE (reg));
       emit_move_insn (tmps[i], reg);
     }
-  emit_queue();
+  emit_queue ();
 
   /* If we won't be storing directly into memory, protect the real destination
      from strange tricks we might play.  */
@@ -2052,14 +2083,6 @@ emit_group_store (orig_dst, src, ssize, align)
       /* Make life a bit easier for combine.  */
       emit_move_insn (dst, const0_rtx);
     }
-  else if (! MEM_IN_STRUCT_P (dst))
-    {
-      /* store_bit_field requires that memory operations have
-        mem_in_struct_p set; we might not.  */
-
-      dst = copy_rtx (orig_dst);
-      MEM_SET_IN_STRUCT_P (dst, 1);
-    }
 
   /* Process the pieces.  */
   for (i = start; i < XVECLEN (src, 0); i++)
@@ -2069,7 +2092,7 @@ emit_group_store (orig_dst, src, ssize, align)
       unsigned int bytelen = GET_MODE_SIZE (mode);
 
       /* Handle trailing fragments that run over the size of the struct.  */
-      if (ssize >= 0 && bytepos + bytelen > ssize)
+      if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
        {
          if (BYTES_BIG_ENDIAN)
            {
@@ -2094,7 +2117,7 @@ emit_group_store (orig_dst, src, ssize, align)
                           mode, tmps[i], align, ssize);
     }
 
-  emit_queue();
+  emit_queue ();
 
   /* Copy from the pseudo into the (probable) hard reg.  */
   if (GET_CODE (dst) == REG)
@@ -2108,7 +2131,7 @@ emit_group_store (orig_dst, src, ssize, align)
    The primary 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. */
+   in registers regardless of the structure's alignment.  */
 
 rtx
 copy_blkmode_from_reg (tgtblk, srcreg, type)
@@ -2123,11 +2146,13 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
 
   if (tgtblk == 0)
     {
-      tgtblk = assign_stack_temp (BLKmode, bytes, 0);
-      MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
+      tgtblk = assign_temp (build_qualified_type (type,
+                                                 (TYPE_QUALS (type)
+                                                  | TYPE_QUAL_CONST)),
+                           0, 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
@@ -2143,7 +2168,7 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
 
   /* Copy the structure BITSIZE bites at a time.
-     
+
      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.  */
@@ -2151,7 +2176,7 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
        bitpos < bytes * BITS_PER_UNIT;
        bitpos += bitsize, xbitpos += bitsize)
     {
-      /* We need a new source operand each time xbitpos is on a 
+      /* We need a new source operand each time xbitpos is on a
         word boundary and when xbitpos == big_endian_correction
         (the first time through).  */
       if (xbitpos % BITS_PER_WORD == 0
@@ -2162,7 +2187,7 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
         a word boundary.  */
       if (bitpos % BITS_PER_WORD == 0)
        dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
-             
+
       /* Use xbitpos for the source extraction (right justified) and
         xbitpos for the destination store (left justified).  */
       store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
@@ -2185,7 +2210,7 @@ use_reg (call_fusage, reg)
 {
   if (GET_CODE (reg) != REG
       || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
-    abort();
+    abort ();
 
   *call_fusage
     = gen_rtx_EXPR_LIST (VOIDmode,
@@ -2233,6 +2258,106 @@ use_group_regs (call_fusage, regs)
     }
 }
 \f
+
+int
+can_store_by_pieces (len, constfun, constfundata, align)
+     unsigned HOST_WIDE_INT len;
+     rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
+     PTR constfundata;
+     unsigned int align;
+{
+  unsigned HOST_WIDE_INT max_size, l;
+  HOST_WIDE_INT offset = 0;
+  enum machine_mode mode, tmode;
+  enum insn_code icode;
+  int reverse;
+  rtx cst;
+
+  if (! MOVE_BY_PIECES_P (len, align))
+    return 0;
+
+  if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
+      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
+    align = MOVE_MAX * BITS_PER_UNIT;
+
+  /* We would first store what we can in the largest integer mode, then go to
+     successively smaller modes.  */
+
+  for (reverse = 0;
+       reverse <= (HAVE_PRE_DECREMENT || HAVE_POST_DECREMENT);
+       reverse++)
+    {
+      l = len;
+      mode = VOIDmode;
+      max_size = MOVE_MAX_PIECES + 1;
+      while (max_size > 1)
+       {
+         for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+              tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
+           if (GET_MODE_SIZE (tmode) < max_size)
+             mode = tmode;
+
+         if (mode == VOIDmode)
+           break;
+
+         icode = mov_optab->handlers[(int) mode].insn_code;
+         if (icode != CODE_FOR_nothing
+             && align >= GET_MODE_ALIGNMENT (mode))
+           {
+             unsigned int size = GET_MODE_SIZE (mode);
+
+             while (l >= size)
+               {
+                 if (reverse)
+                   offset -= size;
+
+                 cst = (*constfun) (constfundata, offset, mode);
+                 if (!LEGITIMATE_CONSTANT_P (cst))
+                   return 0;
+
+                 if (!reverse)
+                   offset += size;
+
+                 l -= size;
+               }
+           }
+
+         max_size = GET_MODE_SIZE (mode);
+       }
+
+      /* The code above should have handled everything.  */
+      if (l != 0)
+       abort ();
+    }
+
+  return 1;
+}
+
+/* Generate several move instructions to store LEN bytes generated by
+   CONSTFUN to block TO.  (A MEM rtx with BLKmode).  CONSTFUNDATA is a
+   pointer which will be passed as argument in every CONSTFUN call.
+   ALIGN is maximum alignment we can assume.  */
+
+void
+store_by_pieces (to, len, constfun, constfundata, align)
+     rtx to;
+     unsigned HOST_WIDE_INT len;
+     rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
+     PTR constfundata;
+     unsigned int align;
+{
+  struct store_by_pieces data;
+
+  if (! MOVE_BY_PIECES_P (len, align))
+    abort ();
+  to = protect_from_queue (to, 1);
+  data.constfun = constfun;
+  data.constfundata = constfundata;
+  data.len = len;
+  data.to = to;
+  store_by_pieces_1 (&data, align);
+}
+
 /* Generate several move instructions to clear LEN bytes of block TO.  (A MEM
    rtx with BLKmode).  The caller must pass TO through protect_from_queue
    before calling. ALIGN is maximum alignment we can assume.  */
@@ -2243,61 +2368,90 @@ clear_by_pieces (to, len, align)
      unsigned HOST_WIDE_INT len;
      unsigned int align;
 {
-  struct clear_by_pieces data;
-  rtx to_addr = XEXP (to, 0);
+  struct store_by_pieces data;
+
+  data.constfun = clear_by_pieces_1;
+  data.constfundata = NULL_PTR;
+  data.len = len;
+  data.to = to;
+  store_by_pieces_1 (&data, align);
+}
+
+/* Callback routine for clear_by_pieces.
+   Return const0_rtx unconditionally.  */
+
+static rtx
+clear_by_pieces_1 (data, offset, mode)
+     PTR data ATTRIBUTE_UNUSED;
+     HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return const0_rtx;
+}
+
+/* Subroutine of clear_by_pieces and store_by_pieces.
+   Generate several move instructions to store LEN bytes of block TO.  (A MEM
+   rtx with BLKmode).  The caller must pass TO through protect_from_queue
+   before calling.  ALIGN is maximum alignment we can assume.  */
+
+static void
+store_by_pieces_1 (data, align)
+     struct store_by_pieces *data;
+     unsigned int align;
+{
+  rtx to_addr = XEXP (data->to, 0);
   unsigned HOST_WIDE_INT max_size = MOVE_MAX_PIECES + 1;
   enum machine_mode mode = VOIDmode, tmode;
   enum insn_code icode;
 
-  data.offset = 0;
-  data.to_addr = to_addr;
-  data.to = to;
-  data.autinc_to
+  data->offset = 0;
+  data->to_addr = to_addr;
+  data->autinc_to
     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
 
-  data.explicit_inc_to = 0;
-  data.reverse
+  data->explicit_inc_to = 0;
+  data->reverse
     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
-  if (data.reverse) data.offset = len;
-  data.len = len;
+  if (data->reverse)
+    data->offset = data->len;
 
-  /* If copying requires more than two move insns,
+  /* If storing requires more than two move insns,
      copy addresses to registers (to make displacements shorter)
      and use post-increment if available.  */
-  if (!data.autinc_to
-      && move_by_pieces_ninsns (len, align) > 2)
+  if (!data->autinc_to
+      && move_by_pieces_ninsns (data->len, align) > 2)
     {
-      /* Determine the main mode we'll be using */
+      /* Determine the main mode we'll be using */
       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
        if (GET_MODE_SIZE (tmode) < max_size)
          mode = tmode;
 
-      if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
+      if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
        {
-         data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
-         data.autinc_to = 1;
-         data.explicit_inc_to = -1;
+         data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
+         data->autinc_to = 1;
+         data->explicit_inc_to = -1;
        }
 
-      if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse
-         && ! data.autinc_to)
+      if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
+         && ! data->autinc_to)
        {
-         data.to_addr = copy_addr_to_reg (to_addr);
-         data.autinc_to = 1;
-         data.explicit_inc_to = 1;
+         data->to_addr = copy_addr_to_reg (to_addr);
+         data->autinc_to = 1;
+         data->explicit_inc_to = 1;
        }
 
-      if ( !data.autinc_to && CONSTANT_P (to_addr))
-       data.to_addr = copy_addr_to_reg (to_addr);
+      if ( !data->autinc_to && CONSTANT_P (to_addr))
+       data->to_addr = copy_addr_to_reg (to_addr);
     }
 
   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
       || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
     align = MOVE_MAX * BITS_PER_UNIT;
 
-  /* First move what we can in the largest integer mode, then go to
+  /* First store what we can in the largest integer mode, then go to
      successively smaller modes.  */
 
   while (max_size > 1)
@@ -2312,28 +2466,28 @@ clear_by_pieces (to, len, align)
 
       icode = mov_optab->handlers[(int) mode].insn_code;
       if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-       clear_by_pieces_1 (GEN_FCN (icode), mode, &data);
+       store_by_pieces_2 (GEN_FCN (icode), mode, data);
 
       max_size = GET_MODE_SIZE (mode);
     }
 
   /* The code above should have handled everything.  */
-  if (data.len != 0)
+  if (data->len != 0)
     abort ();
 }
 
-/* Subroutine of clear_by_pieces.  Clear as many bytes as appropriate
+/* Subroutine of store_by_pieces_1.  Store as many bytes as appropriate
    with move instructions for mode MODE.  GENFUN is the gen_... function
    to make a move insn for that mode.  DATA has all the other info.  */
 
 static void
-clear_by_pieces_1 (genfun, mode, data)
+store_by_pieces_2 (genfun, mode, data)
      rtx (*genfun) PARAMS ((rtx, ...));
      enum machine_mode mode;
-     struct clear_by_pieces *data;
+     struct store_by_pieces *data;
 {
   unsigned int size = GET_MODE_SIZE (mode);
-  rtx to1;
+  rtx to1, cst;
 
   while (data->len >= size)
     {
@@ -2345,14 +2499,16 @@ clear_by_pieces_1 (genfun, mode, data)
          to1 = gen_rtx_MEM (mode, data->to_addr);
          MEM_COPY_ATTRIBUTES (to1, data->to);
        }
-      else 
+      else
        to1 = change_address (data->to, mode,
                              plus_constant (data->to_addr, data->offset));
 
       if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-       emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
+       emit_insn (gen_add2_insn (data->to_addr,
+                                 GEN_INT (-(HOST_WIDE_INT) size)));
 
-      emit_insn ((*genfun) (to1, const0_rtx));
+      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)));
@@ -2381,7 +2537,13 @@ clear_storage (object, size, align)
 #endif
   rtx retval = 0;
 
-  if (GET_MODE (object) == BLKmode)
+  /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
+     just move a zero.  Otherwise, do this a piece at a time.  */
+  if (GET_MODE (object) != BLKmode
+      && GET_CODE (size) == CONST_INT
+      && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size))
+    emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
+  else
     {
       object = protect_from_queue (object, 1);
       size = protect_from_queue (size, 0);
@@ -2468,7 +2630,6 @@ clear_storage (object, size, align)
          size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
 #endif
 
-
 #ifdef TARGET_MEM_FUNCTIONS
          /* It is incorrect to use the libcall calling conventions to call
             memset in this context.
@@ -2478,7 +2639,7 @@ clear_storage (object, size, align)
 
             For targets where libcalls and normal calls have different
             conventions for returning pointers, we could end up generating
-             incorrect code. 
+             incorrect code.
 
             So instead of using a libcall sequence we build up a suitable
             CALL_EXPR and expand the call in the normal fashion.  */
@@ -2489,8 +2650,6 @@ clear_storage (object, size, align)
              /* This was copied from except.c, I don't know if all this is
                 necessary in this context or not.  */
              fn = get_identifier ("memset");
-             push_obstacks_nochange ();
-             end_temporary_allocation ();
              fntype = build_pointer_type (void_type_node);
              fntype = build_function_type (fntype, NULL_TREE);
              fn = build_decl (FUNCTION_DECL, fn, fntype);
@@ -2498,12 +2657,11 @@ clear_storage (object, size, align)
              DECL_EXTERNAL (fn) = 1;
              TREE_PUBLIC (fn) = 1;
              DECL_ARTIFICIAL (fn) = 1;
-             make_decl_rtl (fn, NULL_PTR, 1);
+             make_decl_rtl (fn, NULL_PTR);
              assemble_external (fn);
-             pop_obstacks ();
            }
 
-         /* We need to make an argument list for the function call. 
+         /* We need to make an argument list for the function call.
 
             memset has three arguments, the first is a void * addresses, the
             second a integer with the initialization value, the last is a
@@ -2514,7 +2672,7 @@ clear_storage (object, size, align)
                                          object));
          TREE_CHAIN (arg_list)
            = build_tree_list (NULL_TREE,
-                               make_tree (integer_type_node, const0_rtx));
+                              make_tree (integer_type_node, const0_rtx));
          TREE_CHAIN (TREE_CHAIN (arg_list))
            = build_tree_list (NULL_TREE, make_tree (sizetype, size));
          TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
@@ -2528,14 +2686,12 @@ clear_storage (object, size, align)
 
          retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
 #else
-         emit_library_call (bzero_libfunc, 0,
+         emit_library_call (bzero_libfunc, LCT_NORMAL,
                             VOIDmode, 2, object, Pmode, size,
                             TYPE_MODE (integer_type_node));
 #endif
        }
     }
-  else
-    emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
 
   return retval;
 }
@@ -2552,6 +2708,8 @@ emit_move_insn (x, y)
      rtx x, y;
 {
   enum machine_mode mode = GET_MODE (x);
+  rtx y_cst = NULL_RTX;
+  rtx last_insn;
 
   x = protect_from_queue (x, 1);
   y = protect_from_queue (y, 0);
@@ -2563,7 +2721,10 @@ emit_move_insn (x, y)
   if (GET_CODE (y) == CONSTANT_P_RTX)
     ;
   else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
-    y = force_const_mem (mode, y);
+    {
+      y_cst = y;
+      y = force_const_mem (mode, y);
+    }
 
   /* If X or Y are memory references, verify that their addresses are valid
      for the machine.  */
@@ -2583,7 +2744,13 @@ emit_move_insn (x, y)
   if (mode == BLKmode)
     abort ();
 
-  return emit_move_insn_1 (x, y);
+  last_insn = emit_move_insn_1 (x, y);
+
+  if (y_cst && GET_CODE (x) == REG)
+    REG_NOTES (last_insn)
+      = gen_rtx_EXPR_LIST (REG_EQUAL, y_cst, REG_NOTES (last_insn));
+
+  return last_insn;
 }
 
 /* Low level part of emit_move_insn.
@@ -2600,7 +2767,7 @@ emit_move_insn_1 (x, y)
   unsigned int i;
 
   if (mode >= MAX_MACHINE_MODE)
-      abort ();
+    abort ();
 
   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
     return
@@ -2658,7 +2825,7 @@ emit_move_insn_1 (x, y)
             memory and reload.  FIXME, we should see about using extract and
             insert on integer registers, but complex short and complex char
             variables should be rarely used.  */
-         if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD
+         if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
              && (reload_in_progress | reload_completed) == 0)
            {
              int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
@@ -2669,17 +2836,17 @@ emit_move_insn_1 (x, y)
                  enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
                                               ? MODE_FLOAT : MODE_INT);
 
-                 enum machine_mode reg_mode = 
-                   mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
+                 enum machine_mode reg_mode
+                   mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
 
                  if (reg_mode != BLKmode)
                    {
                      rtx mem = assign_stack_temp (reg_mode,
                                                   GET_MODE_SIZE (mode), 0);
-
                      rtx cmem = change_address (mem, mode, NULL_RTX);
 
-                     cfun->cannot_inline = N_("function using short complex types cannot be inline");
+                     cfun->cannot_inline
+                       = N_("function using short complex types cannot be inline");
 
                      if (packed_dest_p)
                        {
@@ -2731,7 +2898,7 @@ emit_move_insn_1 (x, y)
       rtx last_insn = 0;
       rtx seq, inner;
       int need_clobber;
-      
+
 #ifdef PUSH_ROUNDING
 
       /* If X is a push on the stack, do the push now and replace
@@ -2742,7 +2909,7 @@ emit_move_insn_1 (x, y)
          x = change_address (x, VOIDmode, stack_pointer_rtx);
        }
 #endif
-                            
+
       /* If we are in reload, see if either operand is a MEM whose address
         is scheduled for replacement.  */
       if (reload_in_progress && GET_CODE (x) == MEM
@@ -2766,7 +2933,7 @@ emit_move_insn_1 (x, y)
 
       need_clobber = 0;
       for (i = 0;
-          i < (GET_MODE_SIZE (mode)  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
+          i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
           i++)
        {
          rtx xpart = operand_subword (x, i, 1, mode);
@@ -2866,7 +3033,7 @@ push_block (size, extra, below)
     {
       if (GET_CODE (size) == CONST_INT)
        temp = plus_constant (virtual_outgoing_args_rtx,
-                             - INTVAL (size) - (below ? 0 : extra));
+                             -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)));
@@ -2889,7 +3056,7 @@ gen_push_operand ()
 
 static rtx
 get_push_address (size)
-       int size;
+     int size;
 {
   register rtx temp;
 
@@ -2980,7 +3147,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
       int used = partial * UNITS_PER_WORD;
       int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
       int skip;
-      
+
       if (size == 0)
        abort ();
 
@@ -3030,19 +3197,19 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
          if (current_function_check_memory_usage && ! in_check_memory_usage)
            {
              rtx temp;
-             
+
              in_check_memory_usage = 1;
-             temp = get_push_address (INTVAL(size) - used);
+             temp = get_push_address (INTVAL (size) - used);
              if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-               emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
-                                  temp, Pmode,
-                                  XEXP (xinner, 0), Pmode,
-                                  GEN_INT (INTVAL(size) - used),
+               emit_library_call (chkr_copy_bitmap_libfunc,
+                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
+                                  Pmode, XEXP (xinner, 0), Pmode,
+                                  GEN_INT (INTVAL (size) - used),
                                   TYPE_MODE (sizetype));
              else
-               emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
-                                  temp, Pmode,
-                                  GEN_INT (INTVAL(size) - used),
+               emit_library_call (chkr_set_right_libfunc,
+                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, temp,
+                                  Pmode, GEN_INT (INTVAL (size) - used),
                                   TYPE_MODE (sizetype),
                                   GEN_INT (MEMORY_USE_RW),
                                   TYPE_MODE (integer_type_node));
@@ -3050,7 +3217,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            }
        }
       else
-#endif /* PUSH_ROUNDING */
+#endif /* PUSH_ROUNDING  */
        {
          rtx target;
 
@@ -3091,12 +3258,14 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
              in_check_memory_usage = 1;
              target = copy_to_reg (temp);
              if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-               emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
+               emit_library_call (chkr_copy_bitmap_libfunc,
+                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
                                   target, Pmode,
                                   XEXP (xinner, 0), Pmode,
                                   size, TYPE_MODE (sizetype));
              else
-               emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+               emit_library_call (chkr_set_right_libfunc,
+                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
                                   target, Pmode,
                                   size, TYPE_MODE (sizetype),
                                   GEN_INT (MEMORY_USE_RW),
@@ -3104,17 +3273,17 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
              in_check_memory_usage = 0;
            }
 
-           target = gen_rtx_MEM (BLKmode, temp);
+         target = gen_rtx_MEM (BLKmode, temp);
 
-           if (type != 0)
-             {
-               set_mem_attributes (target, type, 1);
-               /* Function incoming arguments may overlap with sibling call
-                  outgoing arguments and we cannot allow reordering of reads
-                  from function arguments with stores to outgoing arguments
-                  of sibling calls.  */
-               MEM_ALIAS_SET (target) = 0;
-             }
+         if (type != 0)
+           {
+             set_mem_attributes (target, type, 1);
+             /* Function incoming arguments may overlap with sibling call
+                outgoing arguments and we cannot allow reordering of reads
+                from function arguments with stores to outgoing arguments
+                of sibling calls.  */
+             MEM_ALIAS_SET (target) = 0;
+           }
 
          /* TEMP is the address of the block.  Copy the data there.  */
          if (GET_CODE (size) == CONST_INT
@@ -3183,13 +3352,13 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
             to force it to pop the bcopy-arguments right away.  */
          NO_DEFER_POP;
 #ifdef TARGET_MEM_FUNCTIONS
-         emit_library_call (memcpy_libfunc, 0,
+         emit_library_call (memcpy_libfunc, LCT_NORMAL,
                             VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
                             convert_to_mode (TYPE_MODE (sizetype),
                                              size, TREE_UNSIGNED (sizetype)),
                             TYPE_MODE (sizetype));
 #else
-         emit_library_call (bcopy_libfunc, 0,
+         emit_library_call (bcopy_libfunc, LCT_NORMAL,
                             VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
                             convert_to_mode (TYPE_MODE (integer_type_node),
                                              size,
@@ -3285,9 +3454,9 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
          if (GET_CODE (args_so_far) == CONST_INT)
            addr
              = memory_address (mode,
-                               plus_constant (args_addr, 
+                               plus_constant (args_addr,
                                               INTVAL (args_so_far)));
-          else
+         else
            addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
                                                       args_so_far));
          target = addr;
@@ -3313,15 +3482,15 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            target = get_push_address (GET_MODE_SIZE (mode));
 
          if (GET_CODE (x) == MEM && type && AGGREGATE_TYPE_P (type))
-           emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
-                              target, Pmode,
-                              XEXP (x, 0), Pmode,
+           emit_library_call (chkr_copy_bitmap_libfunc,
+                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
+                              Pmode, XEXP (x, 0), Pmode,
                               GEN_INT (GET_MODE_SIZE (mode)),
                               TYPE_MODE (sizetype));
          else
-           emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
-                              target, Pmode,
-                              GEN_INT (GET_MODE_SIZE (mode)),
+           emit_library_call (chkr_set_right_libfunc,
+                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3, target,
+                              Pmode, GEN_INT (GET_MODE_SIZE (mode)),
                               TYPE_MODE (sizetype),
                               GEN_INT (MEMORY_USE_RW),
                               TYPE_MODE (integer_type_node));
@@ -3345,7 +3514,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
 
   if (extra && args_addr == 0 && where_pad == stack_direction)
     anti_adjust_stack (GEN_INT (extra));
+
   if (alignment_pad && args_addr == 0)
     anti_adjust_stack (alignment_pad);
 }
@@ -3448,7 +3617,7 @@ expand_assignment (to, from, want_value, suggest_reg)
              && GET_MODE (to_rtx) == BLKmode
              && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
              && bitsize
-             && (bitpos % bitsize) == 0 
+             && (bitpos % bitsize) == 0
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
              && alignment == GET_MODE_ALIGNMENT (mode1))
            {
@@ -3522,8 +3691,8 @@ expand_assignment (to, from, want_value, suggest_reg)
          /* Check the access right of the pointer.  */
          in_check_memory_usage = 1;
          if (size)
-           emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
-                              to_addr, Pmode,
+           emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
+                              VOIDmode, 3, to_addr, Pmode,
                               GEN_INT (size), TYPE_MODE (sizetype),
                               GEN_INT (MEMORY_USE_WO),
                               TYPE_MODE (integer_type_node));
@@ -3666,22 +3835,22 @@ expand_assignment (to, from, want_value, suggest_reg)
 
       /* Copy the rights of the bitmap.  */
       if (current_function_check_memory_usage)
-       emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
-                          XEXP (to_rtx, 0), Pmode,
+       emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
+                          VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
                           XEXP (from_rtx, 0), Pmode,
                           convert_to_mode (TYPE_MODE (sizetype),
                                            size, TREE_UNSIGNED (sizetype)),
                           TYPE_MODE (sizetype));
 
 #ifdef TARGET_MEM_FUNCTIONS
-      emit_library_call (memcpy_libfunc, 0,
+      emit_library_call (memcpy_libfunc, LCT_NORMAL,
                         VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
                         XEXP (from_rtx, 0), Pmode,
                         convert_to_mode (TYPE_MODE (sizetype),
                                          size, TREE_UNSIGNED (sizetype)),
                         TYPE_MODE (sizetype));
 #else
-      emit_library_call (bcopy_libfunc, 0,
+      emit_library_call (bcopy_libfunc, LCT_NORMAL,
                         VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
                         XEXP (to_rtx, 0), Pmode,
                         convert_to_mode (TYPE_MODE (integer_type_node),
@@ -3836,7 +4005,7 @@ store_expr (exp, target, want_value)
                                        SUBREG_PROMOTED_UNSIGNED_P (target)),
                         exp);
        }
-        
+
       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
 
       /* If TEMP is a volatile MEM and we want a result value, make
@@ -3906,15 +4075,15 @@ store_expr (exp, target, want_value)
     {
       in_check_memory_usage = 1;
       if (GET_CODE (temp) == MEM)
-        emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
-                          XEXP (target, 0), Pmode,
+       emit_library_call (chkr_copy_bitmap_libfunc, LCT_CONST_MAKE_BLOCK,
+                          VOIDmode, 3, XEXP (target, 0), Pmode,
                           XEXP (temp, 0), Pmode,
                           expr_size (exp), TYPE_MODE (sizetype));
       else
-        emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
-                          XEXP (target, 0), Pmode, 
+       emit_library_call (chkr_check_addr_libfunc, LCT_CONST_MAKE_BLOCK,
+                          VOIDmode, 3, XEXP (target, 0), Pmode,
                           expr_size (exp), TYPE_MODE (sizetype),
-                          GEN_INT (MEMORY_USE_WO), 
+                          GEN_INT (MEMORY_USE_WO),
                           TYPE_MODE (integer_type_node));
       in_check_memory_usage = 0;
     }
@@ -3994,10 +4163,11 @@ store_expr (exp, target, want_value)
              if (GET_CODE (copy_size_rtx) == CONST_INT)
                {
                  addr = plus_constant (addr, TREE_STRING_LENGTH (exp));
-                 size = plus_constant (size, - TREE_STRING_LENGTH (exp));
-                 align = MIN (align, (BITS_PER_UNIT
-                                      * (INTVAL (copy_size_rtx)
-                                         & - INTVAL (copy_size_rtx))));
+                 size = plus_constant (size, -TREE_STRING_LENGTH (exp));
+                 align = MIN (align,
+                              (unsigned int) (BITS_PER_UNIT
+                                              * (INTVAL (copy_size_rtx)
+                                                 & - INTVAL (copy_size_rtx))));
                }
              else
                {
@@ -4026,10 +4196,11 @@ store_expr (exp, target, want_value)
                  /* Be sure we can write on ADDR.  */
                  in_check_memory_usage = 1;
                  if (current_function_check_memory_usage)
-                   emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+                   emit_library_call (chkr_check_addr_libfunc,
+                                      LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
                                       addr, Pmode,
                                       size, TYPE_MODE (sizetype),
-                                      GEN_INT (MEMORY_USE_WO), 
+                                      GEN_INT (MEMORY_USE_WO),
                                       TYPE_MODE (integer_type_node));
                  in_check_memory_usage = 0;
                  clear_storage (dest, size, align);
@@ -4065,7 +4236,7 @@ store_expr (exp, target, want_value)
           && ! (GET_CODE (target) == REG
                 && REGNO (target) < FIRST_PSEUDO_REGISTER))
     return copy_to_reg (target);
-  
+
   else
     return target;
 }
@@ -4103,7 +4274,7 @@ is_zeros_p (exp)
          return 0;
 
       return 1;
-      
+
     default:
       return 0;
     }
@@ -4146,6 +4317,7 @@ mostly_zeros_p (exp)
    TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
    TYPE is the type of the CONSTRUCTOR, not the element type.
    ALIGN and CLEARED are as for store_constructor.
+   ALIAS_SET is the alias set to use for any stores.
 
    This provides a recursive shortcut back to store_constructor when it isn't
    necessary to go through store_field.  This is so that we can pass through
@@ -4154,7 +4326,7 @@ mostly_zeros_p (exp)
 
 static void
 store_constructor_field (target, bitsize, bitpos,
-                        mode, exp, type, align, cleared)
+                        mode, exp, type, align, cleared, alias_set)
      rtx target;
      unsigned HOST_WIDE_INT bitsize;
      HOST_WIDE_INT bitpos;
@@ -4162,6 +4334,7 @@ store_constructor_field (target, bitsize, bitpos,
      tree exp, type;
      unsigned int align;
      int cleared;
+     int alias_set;
 {
   if (TREE_CODE (exp) == CONSTRUCTOR
       && bitpos % BITS_PER_UNIT == 0
@@ -4179,11 +4352,20 @@ store_constructor_field (target, bitsize, bitpos,
                            ? BLKmode : VOIDmode,
                            plus_constant (XEXP (target, 0),
                                           bitpos / BITS_PER_UNIT));
+
+
+      /* Show the alignment may no longer be what it was and update the alias
+        set, if required.  */
+      if (bitpos != 0)
+       align = MIN (align, (unsigned int) bitpos & - bitpos);
+      if (GET_CODE (target) == MEM)
+       MEM_ALIAS_SET (target) = alias_set;
+
       store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
     }
   else
     store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, align,
-                int_size_in_bytes (type), 0);
+                int_size_in_bytes (type), alias_set);
 }
 
 /* Store the value of constructor EXP into the rtx TARGET.
@@ -4253,11 +4435,15 @@ store_constructor (exp, target, align, cleared, size)
 
       /* If the constructor has fewer fields than the structure
         or if we are initializing the structure to mostly zeros,
-        clear the whole structure first.  */
+        clear the whole structure first.  Don't do this is TARGET is
+        register whose mode size isn't equal to SIZE since clear_storage
+        can't handle this case.  */
       else if (size > 0
               && ((list_length (CONSTRUCTOR_ELTS (exp))
                    != fields_length (type))
-                  || mostly_zeros_p (exp)))
+                  || mostly_zeros_p (exp))
+              && (GET_CODE (target) != REG
+                  || (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target)) == size))
        {
          if (! cleared)
            clear_storage (target, GEN_INT (size), align);
@@ -4312,7 +4498,7 @@ store_constructor (exp, target, align, cleared, size)
            }
          else
            bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
-                             
+
          if (offset)
            {
              rtx offset_rtx;
@@ -4325,8 +4511,8 @@ store_constructor (exp, target, align, cleared, size)
              if (GET_CODE (to_rtx) != MEM)
                abort ();
 
-              if (GET_MODE (offset_rtx) != ptr_mode)
-                {
+             if (GET_MODE (offset_rtx) != ptr_mode)
+               {
 #ifdef POINTERS_EXTEND_UNSIGNED
                   offset_rtx = convert_memory_address (ptr_mode, offset_rtx);
 #else
@@ -4378,7 +4564,11 @@ store_constructor (exp, target, align, cleared, size)
            }
 #endif
          store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                  TREE_VALUE (elt), type, align, cleared);
+                                  TREE_VALUE (elt), type, align, cleared,
+                                  (DECL_NONADDRESSABLE_P (field)
+                                   && GET_CODE (to_rtx) == MEM)
+                                  ? MEM_ALIAS_SET (to_rtx)
+                                  : get_alias_set (TREE_TYPE (field)));
        }
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
@@ -4387,9 +4577,18 @@ store_constructor (exp, target, align, cleared, size)
       register int i;
       int need_to_clear;
       tree domain = TYPE_DOMAIN (type);
-      HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
-      HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
       tree elttype = TREE_TYPE (type);
+      int const_bounds_p = (host_integerp (TYPE_MIN_VALUE (domain), 0)
+                           && host_integerp (TYPE_MAX_VALUE (domain), 0));
+      HOST_WIDE_INT minelt;
+      HOST_WIDE_INT maxelt;
+
+      /* If we have constant bounds for the range of the type, get them.  */
+      if (const_bounds_p)
+       {
+         minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
+         maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
+       }
 
       /* If the constructor has fewer elements than the array,
          clear the whole array first.  Similarly if this is
@@ -4399,12 +4598,13 @@ store_constructor (exp, target, align, cleared, size)
       else
        {
          HOST_WIDE_INT count = 0, zero_count = 0;
-         need_to_clear = 0;
+         need_to_clear = ! const_bounds_p;
+
          /* This loop is a more accurate version of the loop in
             mostly_zeros_p (it handles RANGE_EXPR in an index).
             It is also needed to check for missing elements.  */
          for (elt = CONSTRUCTOR_ELTS (exp);
-              elt != NULL_TREE;
+              elt != NULL_TREE && ! need_to_clear;
               elt = TREE_CHAIN (elt))
            {
              tree index = TREE_PURPOSE (elt);
@@ -4427,16 +4627,19 @@ store_constructor (exp, target, align, cleared, size)
                }
              else
                this_node_count = 1;
+
              count += this_node_count;
              if (mostly_zeros_p (TREE_VALUE (elt)))
                zero_count += this_node_count;
            }
+
          /* Clear the entire array first if there are any missing elements,
             or if the incidence of zero elements is >= 75%.  */
-         if (count < maxelt - minelt + 1
-             || 4 * zero_count >= 3 * count)
+         if (! need_to_clear
+             && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
            need_to_clear = 1;
        }
+
       if (need_to_clear && size > 0)
        {
          if (! cleared)
@@ -4485,7 +4688,8 @@ store_constructor (exp, target, align, cleared, size)
              tree position;
 
              /* If the range is constant and "small", unroll the loop.  */
-             if (host_integerp (lo_index, 0)
+             if (const_bounds_p
+                 && host_integerp (lo_index, 0)
                  && host_integerp (hi_index, 0)
                  && (lo = tree_low_cst (lo_index, 0),
                      hi = tree_low_cst (hi_index, 0),
@@ -4500,8 +4704,11 @@ store_constructor (exp, target, align, cleared, size)
                  for (; lo <= hi; lo++)
                    {
                      bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
-                     store_constructor_field (target, bitsize, bitpos, mode,
-                                              value, type, align, cleared);
+                     store_constructor_field
+                       (target, bitsize, bitpos, mode, value, type, align,
+                        cleared,
+                        TYPE_NONALIASED_COMPONENT (type)
+                        ? MEM_ALIAS_SET (target) : get_alias_set (elttype));
                    }
                }
              else
@@ -4589,12 +4796,17 @@ store_constructor (exp, target, align, cleared, size)
                bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
 
              store_constructor_field (target, bitsize, bitpos, mode, value,
-                                      type, align, cleared);
+                                      type, align, cleared,
+                                      TYPE_NONALIASED_COMPONENT (type)
+                                      && GET_CODE (target) == MEM
+                                      ? MEM_ALIAS_SET (target) :
+                                      get_alias_set (elttype));
+
            }
        }
     }
 
-  /* Set constructor assignments */
+  /* Set constructor assignments */
   else if (TREE_CODE (type) == SET_TYPE)
     {
       tree elt = CONSTRUCTOR_ELTS (exp);
@@ -4611,7 +4823,7 @@ store_constructor (exp, target, align, cleared, size)
         Also, if a large set has just a single range, it may also be
         better to first clear all the first clear the set (using
         bzero/memset), and set the bits we want.  */
-       
+
       /* Check for all zeros.  */
       if (elt == NULL_TREE && size > 0)
        {
@@ -4630,7 +4842,7 @@ store_constructor (exp, target, align, cleared, size)
 
       /* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
         are "complicated" (more than one range), initialize (the
-        constant parts) by copying from a constant.  */         
+        constant parts) by copying from a constant.  */
       if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
          || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
        {
@@ -4669,7 +4881,7 @@ store_constructor (exp, target, align, cleared, size)
                          to_rtx = plus_constant (XEXP (target, 0), offset);
                          to_rtx = change_address (target, mode, to_rtx);
                        }
-                     else if (offset == 0) 
+                     else if (offset == 0)
                        to_rtx = target;
                      else
                        abort ();
@@ -4695,12 +4907,12 @@ store_constructor (exp, target, align, cleared, size)
                       - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
                       != (HOST_WIDE_INT) nbits))))
          clear_storage (target, expr_size (exp), TYPE_ALIGN (type));
-         
+
       for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
        {
-         /* start of range of element or NULL */
+         /* Start of range of element or NULL.  */
          tree startbit = TREE_PURPOSE (elt);
-         /* end of range of element, or element value */
+         /* End of range of element, or element value.  */
          tree endbit   = TREE_VALUE (elt);
 #ifdef TARGET_MEM_FUNCTIONS
          HOST_WIDE_INT startb, endb;
@@ -4710,7 +4922,7 @@ store_constructor (exp, target, align, cleared, size)
          bitlength_rtx = expand_expr (bitlength,
                                       NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
 
-         /* handle non-range tuple element like [ expr ]  */
+         /* Handle non-range tuple element like [ expr ].  */
          if (startbit == NULL_TREE)
            {
              startbit = save_expr (endbit);
@@ -4724,16 +4936,18 @@ store_constructor (exp, target, align, cleared, size)
              startbit = size_binop (MINUS_EXPR, startbit, domain_min);
              endbit = size_binop (MINUS_EXPR, endbit, domain_min);
            }
-         startbit_rtx = expand_expr (startbit, NULL_RTX, MEM, 
+         startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
                                      EXPAND_CONST_ADDRESS);
-         endbit_rtx = expand_expr (endbit, NULL_RTX, MEM, 
+         endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
                                    EXPAND_CONST_ADDRESS);
 
          if (REG_P (target))
            {
-             targetx = assign_stack_temp (GET_MODE (target),
-                                          GET_MODE_SIZE (GET_MODE (target)),
-                                          0);
+             targetx
+               = assign_temp
+                 ((build_qualified_type (type_for_mode (GET_MODE (target), 0),
+                                         TYPE_QUAL_CONST)),
+                  0, 1, 1);
              emit_move_insn (targetx, target);
            }
 
@@ -4751,7 +4965,7 @@ store_constructor (exp, target, align, cleared, size)
              && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
              && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
            {
-             emit_library_call (memset_libfunc, 0,
+             emit_library_call (memset_libfunc, LCT_NORMAL,
                                 VOIDmode, 3,
                                 plus_constant (XEXP (targetx, 0),
                                                startb / BITS_PER_UNIT),
@@ -4763,8 +4977,8 @@ store_constructor (exp, target, align, cleared, size)
          else
 #endif
            emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
-                              0, VOIDmode, 4, XEXP (targetx, 0), Pmode,
-                              bitlength_rtx, TYPE_MODE (sizetype),
+                              LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
+                              Pmode, bitlength_rtx, TYPE_MODE (sizetype),
                               startbit_rtx, TYPE_MODE (sizetype),
                               endbit_rtx, TYPE_MODE (sizetype));
 
@@ -4790,7 +5004,7 @@ store_constructor (exp, target, align, cleared, size)
    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
 
    ALIGN is the alignment that TARGET is known to have.
-   TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.  
+   TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.
 
    ALIAS_SET is the alias set for the destination.  This value will
    (in general) be different from that for TARGET, since TARGET is a
@@ -4832,15 +5046,16 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
   if (mode == BLKmode
       && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
     {
-      rtx object = assign_stack_temp (GET_MODE (target),
-                                     GET_MODE_SIZE (GET_MODE (target)), 0);
+      rtx object
+       = assign_temp
+         (build_qualified_type (type_for_mode (GET_MODE (target), 0),
+                                TYPE_QUAL_CONST),
+          0, 1, 1);
       rtx blk_object = copy_rtx (object);
 
-      MEM_SET_IN_STRUCT_P (object, 1);
-      MEM_SET_IN_STRUCT_P (blk_object, 1);
       PUT_MODE (blk_object, BLKmode);
 
-      if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
+      if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
 
       store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
@@ -4930,8 +5145,9 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
            align >>= 1;
 
          emit_block_move (target, temp,
-                          GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-                                   / BITS_PER_UNIT),
+                          bitsize == -1 ? expr_size (exp)
+                          : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+                                     / BITS_PER_UNIT),
                           align);
 
          return value_mode == VOIDmode ? const0_rtx : target;
@@ -5063,7 +5279,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
       else
        *pbitsize = GET_MODE_BITSIZE (mode);
     }
-      
+
   if (size_tree != 0)
     {
       if (! host_integerp (size_tree, 1))
@@ -5203,10 +5419,10 @@ get_memory_usage_from_modifier (modifier)
     }
 }
 \f
-/* Given an rtx VALUE that may contain additions and multiplications,
-   return an equivalent value that just refers to a register or memory.
-   This is done by generating instructions to perform the arithmetic
-   and returning a pseudo-register containing the value.
+/* Given an rtx VALUE that may contain additions and multiplications, return
+   an equivalent value that just refers to a register, memory, or constant.
+   This is done by generating instructions to perform the arithmetic and
+   returning a pseudo-register containing the value.
 
    The returned value may be a REG, SUBREG, MEM or constant.  */
 
@@ -5249,7 +5465,7 @@ force_operand (value, target)
       tmp = force_operand (XEXP (value, 0), subtarget);
       return expand_mult (GET_MODE (value), tmp,
                          force_operand (op2, NULL_RTX),
-                         target, 0);
+                         target, 1);
     }
 
   if (binoptab)
@@ -5283,7 +5499,7 @@ force_operand (value, target)
                               force_operand (XEXP (XEXP (value, 0), 1), 0),
                               target, 0, OPTAB_LIB_WIDEN);
        }
-                                  
+
       tmp = force_operand (XEXP (value, 0), subtarget);
       return expand_binop (GET_MODE (value), binoptab, tmp,
                           force_operand (op2, NULL_RTX),
@@ -5315,7 +5531,12 @@ save_noncopied_parts (lhs, list)
        tree part = TREE_VALUE (tail);
        tree part_type = TREE_TYPE (part);
        tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
-       rtx target = assign_temp (part_type, 0, 1, 1);
+       rtx target
+         = assign_temp (build_qualified_type (part_type,
+                                              (TYPE_QUALS (part_type)
+                                               | TYPE_QUAL_CONST)),
+                        0, 1, 1);
+
        if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0)))
          target = change_address (target, TYPE_MODE (part_type), NULL_RTX);
        parts = tree_cons (to_be_saved,
@@ -5360,7 +5581,7 @@ init_noncopied_parts (lhs, list)
    It is always safe for this routine to return zero since it merely
    searches for optimization opportunities.  */
 
-static int
+int
 safe_from_p (x, exp, top_p)
      rtx x;
      tree exp;
@@ -5368,10 +5589,7 @@ safe_from_p (x, exp, top_p)
 {
   rtx exp_rtl = 0;
   int i, nops;
-  static int save_expr_count;
-  static int save_expr_size = 0;
-  static tree *save_expr_rewritten;
-  static tree save_expr_trees[256];
+  static tree save_expr_list;
 
   if (x == 0
       /* If EXP has varying size, we MUST use a target since we currently
@@ -5386,31 +5604,14 @@ safe_from_p (x, exp, top_p)
              || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
              || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
              != INTEGER_CST)
-         && GET_MODE (x) == BLKmode))
+         && GET_MODE (x) == BLKmode)
+      /* If X is in the outgoing argument area, it is always safe.  */
+      || (GET_CODE (x) == MEM
+         && (XEXP (x, 0) == virtual_outgoing_args_rtx
+             || (GET_CODE (XEXP (x, 0)) == PLUS
+                 && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
     return 1;
 
-  if (top_p && save_expr_size == 0)
-    {
-      int rtn;
-
-      save_expr_count = 0;
-      save_expr_size = sizeof (save_expr_trees) / sizeof (save_expr_trees[0]);
-      save_expr_rewritten = &save_expr_trees[0];
-
-      rtn = safe_from_p (x, exp, 1);
-
-      for (i = 0; i < save_expr_count; ++i)
-       {
-         if (TREE_CODE (save_expr_trees[i]) != ERROR_MARK)
-           abort ();
-         TREE_SET_CODE (save_expr_trees[i], SAVE_EXPR);
-       }
-
-      save_expr_size = 0;
-
-      return rtn;
-    }
-
   /* If this is a subreg of a hard register, declare it unsafe, otherwise,
      find the underlying pseudo.  */
   if (GET_CODE (x) == SUBREG)
@@ -5420,13 +5621,31 @@ safe_from_p (x, exp, top_p)
        return 0;
     }
 
-  /* If X is a location in the outgoing argument area, it is always safe.  */
-  if (GET_CODE (x) == MEM
-      && (XEXP (x, 0) == virtual_outgoing_args_rtx
-         || (GET_CODE (XEXP (x, 0)) == PLUS
-             && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx)))
-    return 1;
+  /* A SAVE_EXPR might appear many times in the expression passed to the
+     top-level safe_from_p call, and if it has a complex subexpression,
+     examining it multiple times could result in a combinatorial explosion.
+     E.g. on an Alpha running at least 200MHz, a Fortran test case compiled
+     with optimization took about 28 minutes to compile -- even though it was
+     only a few lines long.  So we mark each SAVE_EXPR we see with TREE_PRIVATE
+     and turn that off when we are done.  We keep a list of the SAVE_EXPRs
+     we have processed.  Note that the only test of top_p was above.  */
+
+  if (top_p)
+    {
+      int rtn;
+      tree t;
+
+      save_expr_list = 0;
+
+      rtn = safe_from_p (x, exp, 0);
+
+      for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
+       TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
 
+      return rtn;
+    }
+
+  /* Now look at our tree code and possibly recurse.  */
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
     case 'd':
@@ -5466,25 +5685,22 @@ safe_from_p (x, exp, top_p)
        {
        case ADDR_EXPR:
          return (staticp (TREE_OPERAND (exp, 0))
-                 || safe_from_p (x, TREE_OPERAND (exp, 0), 0)
-                 || TREE_STATIC (exp));
+                 || TREE_STATIC (exp)
+                 || safe_from_p (x, TREE_OPERAND (exp, 0), 0));
 
        case INDIRECT_REF:
-         if (GET_CODE (x) == MEM)
+         if (GET_CODE (x) == MEM
+             && alias_sets_conflict_p (MEM_ALIAS_SET (x),
+                                       get_alias_set (exp)))
            return 0;
          break;
 
        case CALL_EXPR:
-         exp_rtl = CALL_EXPR_RTL (exp);
-         if (exp_rtl == 0)
-           {
-             /* Assume that the call will clobber all hard registers and
-                all of memory.  */
-             if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
-                 || GET_CODE (x) == MEM)
-               return 0;
-           }
-
+         /* Assume that the call will clobber all hard registers and
+            all of memory.  */
+         if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
+             || GET_CODE (x) == MEM)
+           return 0;
          break;
 
        case RTL_EXPR:
@@ -5509,37 +5725,20 @@ safe_from_p (x, exp, top_p)
          if (exp_rtl)
            break;
 
-         /* This SAVE_EXPR might appear many times in the top-level
-            safe_from_p() expression, and if it has a complex
-            subexpression, examining it multiple times could result
-            in a combinatorial explosion.  E.g. on an Alpha
-            running at least 200MHz, a Fortran test case compiled with
-            optimization took about 28 minutes to compile -- even though
-            it was only a few lines long, and the complicated line causing
-            so much time to be spent in the earlier version of safe_from_p()
-            had only 293 or so unique nodes.
-
-            So, turn this SAVE_EXPR into an ERROR_MARK for now, but remember
-            where it is so we can turn it back in the top-level safe_from_p()
-            when we're done.  */
-
-         /* For now, don't bother re-sizing the array. */
-         if (save_expr_count >= save_expr_size)
-           return 0;
-         save_expr_rewritten[save_expr_count++] = exp;
+         /* If we've already scanned this, don't do it again.  Otherwise,
+            show we've scanned it and record for clearing the flag if we're
+            going on.  */
+         if (TREE_PRIVATE (exp))
+           return 1;
 
-         nops = TREE_CODE_LENGTH (SAVE_EXPR);
-         for (i = 0; i < nops; i++)
+         TREE_PRIVATE (exp) = 1;
+         if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
            {
-             tree operand = TREE_OPERAND (exp, i);
-             if (operand == NULL_TREE)
-               continue;
-             TREE_SET_CODE (exp, ERROR_MARK);
-             if (!safe_from_p (x, operand, 0))
-               return 0;
-             TREE_SET_CODE (exp, SAVE_EXPR);
+             TREE_PRIVATE (exp) = 0;
+             return 0;
            }
-         TREE_SET_CODE (exp, ERROR_MARK);
+
+         save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
          return 1;
 
        case BIND_EXPR:
@@ -5550,7 +5749,7 @@ safe_from_p (x, exp, top_p)
        case METHOD_CALL_EXPR:
          /* This takes a rtx argument, but shouldn't appear here.  */
          abort ();
-         
+
        default:
          break;
        }
@@ -5559,11 +5758,18 @@ safe_from_p (x, exp, top_p)
       if (exp_rtl)
        break;
 
-      nops = TREE_CODE_LENGTH (TREE_CODE (exp));
+      nops = first_rtl_op (TREE_CODE (exp));
       for (i = 0; i < nops; i++)
        if (TREE_OPERAND (exp, i) != 0
            && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
          return 0;
+
+      /* If this is a language-specific tree code, it may require
+        special handling.  */
+      if (TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE
+         && lang_safe_from_p
+         && !(*lang_safe_from_p) (x, exp))
+       return 0;
     }
 
   /* If we have an rtl, find any enclosed object.  Then see if we conflict
@@ -5579,10 +5785,11 @@ safe_from_p (x, exp, top_p)
        }
 
       /* If the rtl is X, then it is not safe.  Otherwise, it is unless both
-        are memory and EXP is not readonly.  */
+        are memory and they conflict.  */
       return ! (rtx_equal_p (x, exp_rtl)
                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
-                   && ! TREE_READONLY (exp)));
+                   && true_dependence (exp_rtl, GET_MODE (x), x,
+                                       rtx_addr_varies_p)));
     }
 
   /* If we reach here, it is safe.  */
@@ -5624,9 +5831,10 @@ var_rtx (exp)
 }
 
 #ifdef MAX_INTEGER_COMPUTATION_MODE
+
 void
 check_max_integer_computation_mode (exp)
-    tree exp;
+     tree exp;
 {
   enum tree_code code;
   enum machine_mode mode;
@@ -5649,7 +5857,7 @@ check_max_integer_computation_mode (exp)
       mode = TYPE_MODE (TREE_TYPE (exp));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 
   /* Check operand of a unary op.  */
@@ -5658,45 +5866,24 @@ check_max_integer_computation_mode (exp)
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
-       
+
   /* Check operands of a binary/comparison op.  */
   if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
     {
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
 
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 }
 #endif
-
-\f
-/* Utility function used by expand_expr to see if TYPE, a RECORD_TYPE,
-   has any readonly fields.  If any of the fields have types that
-   contain readonly fields, return true as well.  */
-
-static int
-readonly_fields_p (type)
-     tree type;
-{
-  tree field;
-
-  for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
-    if (TREE_CODE (field) == FIELD_DECL 
-       && (TREE_READONLY (field)
-           || (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-               && readonly_fields_p (TREE_TYPE (field)))))
-      return 1;
-
-  return 0;
-}
 \f
 /* expand_expr: generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.
@@ -5752,8 +5939,8 @@ expand_expr (exp, target, tmode, modifier)
   /* Used by check-memory-usage to make modifier read only.  */
   enum expand_modifier ro_modifier;
 
-  /* Handle ERROR_MARK before anybody tries to access its type. */
-  if (TREE_CODE (exp) == ERROR_MARK)
+  /* Handle ERROR_MARK before anybody tries to access its type.  */
+  if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
     {
       op0 = CONST0_RTX (tmode);
       if (op0 != 0)
@@ -5807,7 +5994,7 @@ expand_expr (exp, target, tmode, modifier)
        return expand_expr (TREE_OPERAND (exp, 0), const0_rtx,
                            VOIDmode, ro_modifier);
       else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
-            || code == ARRAY_REF)
+              || code == ARRAY_REF)
        {
          expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, ro_modifier);
          expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, ro_modifier);
@@ -5826,7 +6013,7 @@ expand_expr (exp, target, tmode, modifier)
          expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, ro_modifier);
          return const0_rtx;
        }
-;
+      ;
       target = 0;
     }
 
@@ -5851,7 +6038,7 @@ expand_expr (exp, target, tmode, modifier)
 
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 
   if (tmode != mode
@@ -5866,7 +6053,7 @@ expand_expr (exp, target, tmode, modifier)
       && TREE_CODE (exp) != RTL_EXPR
       && GET_MODE_CLASS (tmode) == MODE_INT
       && tmode > MAX_INTEGER_COMPUTATION_MODE)
-    fatal ("unsupported wide integer operation");
+    internal_error ("unsupported wide integer operation");
 
   check_max_integer_computation_mode (exp);
 #endif
@@ -5890,15 +6077,9 @@ expand_expr (exp, target, tmode, modifier)
            && function != inline_function_decl && function != 0)
          {
            struct function *p = find_function_data (function);
-           /* Allocate in the memory associated with the function
-              that the label is in.  */
-           push_obstacks (p->function_obstack,
-                          p->function_maybepermanent_obstack);
-
            p->expr->x_forced_labels
              = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (exp),
                                   p->expr->x_forced_labels);
-           pop_obstacks ();
          }
        else
          {
@@ -5931,11 +6112,8 @@ expand_expr (exp, target, tmode, modifier)
       if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
          && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
        {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
          layout_decl (exp, 0);
          PUT_MODE (DECL_RTL (exp), DECL_MODE (exp));
-         pop_obstacks ();
        }
 
       /* Although static-storage variables start off initialized, according to
@@ -5956,7 +6134,8 @@ expand_expr (exp, target, tmode, modifier)
 
          in_check_memory_usage = 1;
          if (memory_usage != MEMORY_USE_DONT)
-           emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+           emit_library_call (chkr_check_addr_libfunc,
+                              LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
                               XEXP (DECL_RTL (exp), 0), Pmode,
                               GEN_INT (int_size_in_bytes (type)),
                               TYPE_MODE (sizetype),
@@ -6009,7 +6188,7 @@ expand_expr (exp, target, tmode, modifier)
            abort ();
          addr = XEXP (DECL_RTL (exp), 0);
          if (GET_CODE (addr) == MEM)
-           addr = change_address (addr, Pmode, 
+           addr = change_address (addr, Pmode,
                                   fix_lexical_addr (XEXP (addr, 0), exp));
          else
            addr = fix_lexical_addr (addr, exp);
@@ -6078,12 +6257,12 @@ expand_expr (exp, target, tmode, modifier)
 
     case CONST_DECL:
       return expand_expr (DECL_INITIAL (exp), target, VOIDmode,
-                         EXPAND_MEMORY_USE_BAD);
+                         EXPAND_MEMORY_USE_BAD);
 
     case REAL_CST:
       /* If optimized, generate immediate CONST_DOUBLE
-        which will be turned into memory by reload if necessary. 
-     
+        which will be turned into memory by reload if necessary.
+
         We used to force a register so that loop.c could see it.  But
         this does not allow gen_* patterns to perform optimizations with
         the constants.  It also produces two insns in cases like "x = 1.0;".
@@ -6096,7 +6275,7 @@ expand_expr (exp, target, tmode, modifier)
     case COMPLEX_CST:
     case STRING_CST:
       if (! TREE_CST_RTL (exp))
-       output_constant_def (exp);
+       output_constant_def (exp, 1);
 
       /* TREE_CST_RTL probably contains a constant address.
         On RISC machines where a constant address isn't valid,
@@ -6121,7 +6300,7 @@ expand_expr (exp, target, tmode, modifier)
        lineno = EXPR_WFL_LINENO (exp);
        if (EXPR_WFL_EMIT_LINE_NOTE (exp))
          emit_line_note (input_filename, lineno);
-       /* Possibly avoid switching back and force here */
+       /* Possibly avoid switching back and force here */
        to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
        input_filename = saved_input_filename;
        lineno = saved_lineno;
@@ -6166,7 +6345,10 @@ expand_expr (exp, target, tmode, modifier)
          if (mode == VOIDmode)
            temp = const0_rtx;
          else
-           temp = assign_temp (type, 3, 0, 0);
+           temp = assign_temp (build_qualified_type (type,
+                                                     (TYPE_QUALS (type)
+                                                      | TYPE_QUAL_CONST)),
+                               3, 0, 0);
 
          SAVE_EXPR_RTL (exp) = temp;
          if (!optimize && GET_CODE (temp) == REG)
@@ -6237,7 +6419,7 @@ expand_expr (exp, target, tmode, modifier)
            tree elt;
 
            /* Find the outermost reference that is of the type we want.
-              If none, see if any object has a type that is a pointer to 
+              If none, see if any object has a type that is a pointer to
               the type we want.  */
            for (elt = TREE_PURPOSE (placeholder_expr);
                 elt != 0 && object == 0;
@@ -6399,13 +6581,13 @@ expand_expr (exp, target, tmode, modifier)
                     && ! (target != 0 && safe_from_p (target, exp, 1)))
                    || TREE_ADDRESSABLE (exp)
                    || (host_integerp (TYPE_SIZE_UNIT (type), 1)
-                       && (! MOVE_BY_PIECES_P 
+                       && (! MOVE_BY_PIECES_P
                            (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
                             TYPE_ALIGN (type)))
                        && ! mostly_zeros_p (exp))))
               || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
        {
-         rtx constructor = output_constant_def (exp);
+         rtx constructor = output_constant_def (exp, 1);
 
          if (modifier != EXPAND_CONST_ADDRESS
              && modifier != EXPAND_INITIALIZER
@@ -6418,27 +6600,18 @@ expand_expr (exp, target, tmode, modifier)
                                          XEXP (constructor, 0));
          return constructor;
        }
-
       else
        {
          /* Handle calls that pass values in multiple non-contiguous
             locations.  The Irix 6 ABI has examples of this.  */
          if (target == 0 || ! safe_from_p (target, exp, 1)
              || GET_CODE (target) == PARALLEL)
-           {
-             if (mode != BLKmode && ! TREE_ADDRESSABLE (exp))
-               target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-             else
-               target = assign_temp (type, 0, 1, 1);
-           }
-
-         if (TREE_READONLY (exp))
-           {
-             if (GET_CODE (target) == MEM)
-               target = copy_rtx (target);
-
-             RTX_UNCHANGING_P (target) = 1;
-           }
+           target
+             = assign_temp (build_qualified_type (type,
+                                                  (TYPE_QUALS (type)
+                                                   | (TREE_READONLY (exp)
+                                                      * TYPE_QUAL_CONST))),
+                            TREE_ADDRESSABLE (exp), 1, 1);
 
          store_constructor (exp, target, TYPE_ALIGN (TREE_TYPE (exp)), 0,
                             int_size_in_bytes (TREE_TYPE (exp)));
@@ -6449,8 +6622,8 @@ expand_expr (exp, target, tmode, modifier)
       {
        tree exp1 = TREE_OPERAND (exp, 0);
        tree index;
-       tree string = string_constant (exp1, &index);
+       tree string = string_constant (exp1, &index);
+
        /* Try to optimize reads from const strings.  */
        if (string
            && TREE_CODE (string) == STRING_CST
@@ -6474,9 +6647,9 @@ expand_expr (exp, target, tmode, modifier)
             if (memory_usage != MEMORY_USE_DONT)
              {
                in_check_memory_usage = 1;
-               emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
-                                  op0, Pmode,
-                                  GEN_INT (int_size_in_bytes (type)),
+               emit_library_call (chkr_check_addr_libfunc,
+                                  LCT_CONST_MAKE_BLOCK, VOIDmode, 3, op0,
+                                  Pmode, GEN_INT (int_size_in_bytes (type)),
                                   TYPE_MODE (sizetype),
                                   GEN_INT (memory_usage),
                                   TYPE_MODE (integer_type_node));
@@ -6497,8 +6670,7 @@ expand_expr (exp, target, tmode, modifier)
        /* If we are writing to this object and its type is a record with
           readonly fields, we must mark it as readonly so it will
           conflict with readonly references to those fields.  */
-       if (modifier == EXPAND_MEMORY_USE_WO
-           && TREE_CODE (type) == RECORD_TYPE && readonly_fields_p (type))
+       if (modifier == EXPAND_MEMORY_USE_WO && readonly_fields_p (type))
          RTX_UNCHANGING_P (temp) = 1;
 
        return temp;
@@ -6546,7 +6718,7 @@ expand_expr (exp, target, tmode, modifier)
 
        if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
            && TREE_CODE (index) == INTEGER_CST
-           && 0 > compare_tree_int (index, 
+           && 0 > compare_tree_int (index,
                                     list_length (CONSTRUCTOR_ELTS
                                                  (TREE_OPERAND (exp, 0)))))
          {
@@ -6561,7 +6733,7 @@ expand_expr (exp, target, tmode, modifier)
              return expand_expr (fold (TREE_VALUE (elem)), target,
                                  tmode, ro_modifier);
          }
-         
+
        else if (optimize >= 1
                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
                 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
@@ -6588,14 +6760,20 @@ expand_expr (exp, target, tmode, modifier)
                else if (TREE_CODE (init) == STRING_CST
                         && 0 > compare_tree_int (index,
                                                  TREE_STRING_LENGTH (init)))
-                 return (GEN_INT
-                         (TREE_STRING_POINTER
-                          (init)[TREE_INT_CST_LOW (index)]));
+                 {
+                   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
+                             (TREE_STRING_POINTER
+                              (init)[TREE_INT_CST_LOW (index)]));
+                 }
              }
          }
       }
-
-      /* ... fall through ... */
+      /* Fall through.  */
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -6625,7 +6803,7 @@ expand_expr (exp, target, tmode, modifier)
                        && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
                            <= HOST_BITS_PER_WIDE_INT))))
              {
-               op0 =  expand_expr (TREE_VALUE (elt), target, tmode, modifier);
+               op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
                if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
                  {
                    HOST_WIDE_INT bitsize
@@ -6674,7 +6852,7 @@ expand_expr (exp, target, tmode, modifier)
        /* If TEM's type is a union of variable size, pass TARGET to the inner
           computation, since it will need a temporary and TARGET is known
           to have to do.  This occurs in unchecked conversion in Ada.  */
-  
+
        op0 = expand_expr (tem,
                           (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
                            && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
@@ -6708,7 +6886,10 @@ expand_expr (exp, target, tmode, modifier)
            if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
              {
-               rtx memloc = assign_temp (TREE_TYPE (tem), 1, 1, 1);
+               tree nt = build_qualified_type (TREE_TYPE (tem),
+                                               (TYPE_QUALS (TREE_TYPE (tem))
+                                                | TYPE_QUAL_CONST));
+               rtx memloc = assign_temp (nt, 1, 1, 1);
 
                mark_temp_addr_taken (memloc);
                emit_move_insn (memloc, op0);
@@ -6733,7 +6914,7 @@ expand_expr (exp, target, tmode, modifier)
                && GET_MODE (op0) == BLKmode
                && GET_MODE (XEXP (op0, 0)) != VOIDmode
                && bitsize != 0
-               && (bitpos % bitsize) == 0 
+               && (bitpos % bitsize) == 0
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
                && alignment == GET_MODE_ALIGNMENT (mode1))
              {
@@ -6750,7 +6931,6 @@ expand_expr (exp, target, tmode, modifier)
                bitpos = 0;
              }
 
-
            op0 = change_address (op0, VOIDmode,
                                  gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
                                                force_reg (ptr_mode,
@@ -6767,7 +6947,7 @@ expand_expr (exp, target, tmode, modifier)
        /* Check the access.  */
        if (cfun != 0 && current_function_check_memory_usage
            && GET_CODE (op0) == MEM)
-          {
+         {
            enum memory_use_mode memory_usage;
            memory_usage = get_memory_usage_from_modifier (modifier);
 
@@ -6782,11 +6962,11 @@ expand_expr (exp, target, tmode, modifier)
                /* Check the access right of the pointer.  */
                in_check_memory_usage = 1;
                if (size > BITS_PER_UNIT)
-                 emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
-                                    to, Pmode,
-                                    GEN_INT (size / BITS_PER_UNIT),
+                 emit_library_call (chkr_check_addr_libfunc,
+                                    LCT_CONST_MAKE_BLOCK, VOIDmode, 3, to,
+                                    Pmode, GEN_INT (size / BITS_PER_UNIT),
                                     TYPE_MODE (sizetype),
-                                    GEN_INT (memory_usage), 
+                                    GEN_INT (memory_usage),
                                     TYPE_MODE (integer_type_node));
                in_check_memory_usage = 0;
              }
@@ -6853,10 +7033,11 @@ expand_expr (exp, target, tmode, modifier)
                  target = assign_temp (type, 0, 1, 1);
 
                emit_block_move (target, op0,
-                                GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-                                         / BITS_PER_UNIT),
+                                bitsize == -1 ? expr_size  (exp)
+                                : GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+                                           / BITS_PER_UNIT),
                                 BITS_PER_UNIT);
-               
+
                return target;
              }
 
@@ -6883,13 +7064,13 @@ expand_expr (exp, target, tmode, modifier)
 
            if (mode == BLKmode)
              {
-               rtx new = assign_stack_temp (ext_mode,
-                                            bitsize / BITS_PER_UNIT, 0);
+               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
+                                               TYPE_QUAL_CONST);
+               rtx new = assign_temp (nt, 0, 1, 1);
 
                emit_move_insn (new, op0);
                op0 = copy_rtx (new);
                PUT_MODE (op0, BLKmode);
-               MEM_SET_IN_STRUCT_P (op0, 1);
              }
 
            return op0;
@@ -6903,8 +7084,14 @@ expand_expr (exp, target, tmode, modifier)
        /* Get a reference to just this component.  */
        if (modifier == EXPAND_CONST_ADDRESS
            || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-         op0 = gen_rtx_MEM (mode1, plus_constant (XEXP (op0, 0),
-                                                  (bitpos / BITS_PER_UNIT)));
+         {
+           rtx new = gen_rtx_MEM (mode1,
+                                  plus_constant (XEXP (op0, 0),
+                                                 (bitpos / BITS_PER_UNIT)));
+
+           MEM_COPY_ATTRIBUTES (new, op0);
+           op0 = new;
+         }
        else
          op0 = change_address (op0, mode1,
                                plus_constant (XEXP (op0, 0),
@@ -6958,8 +7145,6 @@ expand_expr (exp, target, tmode, modifier)
        rtx rlow;
        rtx diff, quo, rem, addr, bit, result;
 
-       preexpand_calls (exp);
-
        /* If domain is empty, answer is no.  Likewise if index is constant
           and out of bounds.  */
        if (((TREE_CODE (set_high_bound) == INTEGER_CST
@@ -7000,7 +7185,7 @@ expand_expr (exp, target, tmode, modifier)
           of the set.  */
        if (GET_CODE (lo_r) == CONST_INT)
          rlow = GEN_INT (INTVAL (lo_r)
-                         & ~ ((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
+                         & ~((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
        else
          rlow = expand_binop (index_mode, and_optab, lo_r,
                               GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)),
@@ -7019,7 +7204,7 @@ expand_expr (exp, target, tmode, modifier)
                                             setaddr, NULL_RTX, iunsignedp,
                                             OPTAB_LIB_WIDEN));
 
-       /* Extract the bit we want to examine */
+       /* Extract the bit we want to examine */
        bit = expand_shift (RSHIFT_EXPR, byte_mode,
                            gen_rtx_MEM (byte_mode, addr),
                            make_tree (TREE_TYPE (index), rem),
@@ -7074,12 +7259,13 @@ expand_expr (exp, target, tmode, modifier)
          && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
              == FUNCTION_DECL)
          && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-       return expand_builtin (exp, target, subtarget, tmode, ignore);
-
-      /* If this call was expanded already by preexpand_calls,
-        just return the result we got.  */
-      if (CALL_EXPR_RTL (exp) != 0)
-       return CALL_EXPR_RTL (exp);
+        {
+         if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
+             == BUILT_IN_FRONTEND)
+           return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+         else
+           return expand_builtin (exp, target, subtarget, tmode, ignore);
+       }
 
       return expand_call (exp, target, ignore);
 
@@ -7087,6 +7273,9 @@ expand_expr (exp, target, tmode, modifier)
     case NOP_EXPR:
     case CONVERT_EXPR:
     case REFERENCE_EXPR:
+      if (TREE_OPERAND (exp, 0) == error_mark_node)
+       return const0_rtx;
+
       if (TREE_CODE (type) == UNION_TYPE)
        {
          tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
@@ -7101,12 +7290,7 @@ expand_expr (exp, target, tmode, modifier)
                                modifier);
 
          if (target == 0)
-           {
-             if (mode != BLKmode)
-               target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-             else
-               target = assign_temp (type, 0, 1, 1);
-           }
+           target = assign_temp (type, 0, 1, 1);
 
          if (GET_CODE (target) == MEM)
            /* Store data into beginning of memory target.  */
@@ -7119,7 +7303,7 @@ expand_expr (exp, target, tmode, modifier)
                         MIN ((int_size_in_bytes (TREE_TYPE
                                                  (TREE_OPERAND (exp, 0)))
                               * BITS_PER_UNIT),
-                             GET_MODE_BITSIZE (mode)),
+                             (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
                         0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
                         VOIDmode, 0, BITS_PER_UNIT,
                         int_size_in_bytes (type), 0);
@@ -7171,7 +7355,9 @@ expand_expr (exp, target, tmode, modifier)
       /* We come here from MINUS_EXPR when the second operand is a
          constant.  */
     plus_expr:
-      this_optab = add_optab;
+      this_optab = ! unsignedp && flag_trapv
+                   && (GET_MODE_CLASS(mode) == MODE_INT)
+                   ? addv_optab : add_optab;
 
       /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
         something else, make sure we add the register to the constant and
@@ -7206,7 +7392,7 @@ expand_expr (exp, target, tmode, modifier)
 
         If this is an EXPAND_SUM call, always return the sum.  */
       if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
-         || mode == ptr_mode)
+          || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
        {
          if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
@@ -7271,7 +7457,6 @@ expand_expr (exp, target, tmode, modifier)
          || mode != ptr_mode)
        goto binop;
 
-      preexpand_calls (exp);
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
 
@@ -7307,7 +7492,7 @@ expand_expr (exp, target, tmode, modifier)
          op0 = eliminate_constant_term (op0, &constant_term);
 
          /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so
-            their sum should be a constant.  Form it into OP1, since the 
+            their sum should be a constant.  Form it into OP1, since the
             result we want will then be OP0 + OP1.  */
 
          temp = simplify_binary_operation (PLUS, mode, constant_term,
@@ -7364,11 +7549,12 @@ expand_expr (exp, target, tmode, modifier)
              goto plus_expr;
            }
        }
-      this_optab = sub_optab;
+      this_optab = ! unsignedp && flag_trapv
+                   && (GET_MODE_CLASS(mode) == MODE_INT)
+                   ? subv_optab : sub_optab;
       goto binop;
 
     case MULT_EXPR:
-      preexpand_calls (exp);
       /* If first operand is constant, swap them.
         Thus the following special case checks need only
         check the second operand.  */
@@ -7467,8 +7653,10 @@ expand_expr (exp, target, tmode, modifier)
                  op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                                     NULL_RTX, VOIDmode, 0);
                  if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
-                   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
-                                      VOIDmode, 0);
+                   op1 = convert_modes (innermode, mode,
+                                        expand_expr (TREE_OPERAND (exp, 1),
+                                                     NULL_RTX, VOIDmode, 0),
+                                        unsignedp);
                  else
                    op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
                                       NULL_RTX, VOIDmode, 0);
@@ -7493,7 +7681,6 @@ expand_expr (exp, target, tmode, modifier)
     case CEIL_DIV_EXPR:
     case ROUND_DIV_EXPR:
     case EXACT_DIV_EXPR:
-      preexpand_calls (exp);
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
       /* Possible optimization: compute the dividend with EXPAND_SUM
@@ -7511,7 +7698,6 @@ expand_expr (exp, target, tmode, modifier)
     case FLOOR_MOD_EXPR:
     case CEIL_MOD_EXPR:
     case ROUND_MOD_EXPR:
-      preexpand_calls (exp);
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
@@ -7545,7 +7731,10 @@ expand_expr (exp, target, tmode, modifier)
 
     case NEGATE_EXPR:
       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-      temp = expand_unop (mode, neg_optab, op0, target, 0);
+      temp = expand_unop (mode,
+                          ! unsignedp && flag_trapv
+                          && (GET_MODE_CLASS(mode) == MODE_INT)
+                          ? negv_optab : neg_optab, op0, target, 0);
       if (temp == 0)
        abort ();
       return temp;
@@ -7563,7 +7752,7 @@ expand_expr (exp, target, tmode, modifier)
       if (TREE_UNSIGNED (type))
        return op0;
 
-      return expand_abs (mode, op0, target,
+      return expand_abs (mode, op0, target, unsignedp,
                         safe_from_p (target, TREE_OPERAND (exp, 0), 1));
 
     case MAX_EXPR:
@@ -7592,7 +7781,7 @@ expand_expr (exp, target, tmode, modifier)
 
       /* At this point, a MEM target is no longer useful; we will get better
         code without it.  */
-        
+
       if (GET_CODE (target) == MEM)
        target = gen_reg_rtx (mode);
 
@@ -7670,7 +7859,6 @@ expand_expr (exp, target, tmode, modifier)
     case RSHIFT_EXPR:
     case LROTATE_EXPR:
     case RROTATE_EXPR:
-      preexpand_calls (exp);
       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
        subtarget = 0;
       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
@@ -7692,7 +7880,6 @@ expand_expr (exp, target, tmode, modifier)
     case UNGT_EXPR:
     case UNGE_EXPR:
     case UNEQ_EXPR:
-      preexpand_calls (exp);
       temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0);
       if (temp != 0)
        return temp;
@@ -7847,7 +8034,7 @@ expand_expr (exp, target, tmode, modifier)
 
        /* 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 
+          intermediate target unless it is safe.  If no target, use a
           temporary.  */
 
        if (ignore)
@@ -7885,10 +8072,14 @@ expand_expr (exp, target, tmode, modifier)
            && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
          {
            rtx result;
-           optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab
-                           : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab
-                           : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
-                           : xor_optab);
+           optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
+                            ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
+                               ? addv_optab : add_optab)
+                            : TREE_CODE (binary_op) == MINUS_EXPR
+                              ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
+                                 ? subv_optab : sub_optab)
+                            : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
+                            : xor_optab);
 
            /* If we had X ? A : A + 1, do this as A + (X == 0).
 
@@ -7925,7 +8116,7 @@ expand_expr (exp, target, tmode, modifier)
              TREE_OPERAND (exp, 0)
                = invert_truthvalue (TREE_OPERAND (exp, 0));
          }
-           
+
        do_pending_stack_adjust ();
        NO_DEFER_POP;
        op0 = gen_label_rtx ();
@@ -7982,7 +8173,8 @@ expand_expr (exp, target, tmode, modifier)
                     || TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR)
                 && safe_from_p (temp, TREE_OPERAND (exp, 2), 1))
          {
-           if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
+           if (GET_CODE (temp) == REG
+               && REGNO (temp) < FIRST_PSEUDO_REGISTER)
              temp = gen_reg_rtx (mode);
            store_expr (TREE_OPERAND (exp, 1), temp, 0);
            jumpif (TREE_OPERAND (exp, 0), op0);
@@ -8000,7 +8192,8 @@ expand_expr (exp, target, tmode, modifier)
                     || TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR)
                 && safe_from_p (temp, TREE_OPERAND (exp, 1), 1))
          {
-           if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
+           if (GET_CODE (temp) == REG
+               && REGNO (temp) < FIRST_PSEUDO_REGISTER)
              temp = gen_reg_rtx (mode);
            store_expr (TREE_OPERAND (exp, 2), temp, 0);
            jumpifnot (TREE_OPERAND (exp, 0), op0);
@@ -8015,11 +8208,11 @@ expand_expr (exp, target, tmode, modifier)
            jumpifnot (TREE_OPERAND (exp, 0), op0);
 
            start_cleanup_deferral ();
-           
+
            /* One branch of the cond can be void, if it never returns. For
-               example A ? throw : E  */
+              example A ? throw : E  */
            if (temp != 0
-               && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
+               && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
              store_expr (TREE_OPERAND (exp, 1), temp, 0);
            else
              expand_expr (TREE_OPERAND (exp, 1),
@@ -8031,7 +8224,7 @@ expand_expr (exp, target, tmode, modifier)
            emit_label (op0);
            start_cleanup_deferral ();
            if (temp != 0
-               && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
+               && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
              store_expr (TREE_OPERAND (exp, 2), temp, 0);
            else
              expand_expr (TREE_OPERAND (exp, 2),
@@ -8070,7 +8263,7 @@ expand_expr (exp, target, tmode, modifier)
 
        /* Set this here so that if we get a target that refers to a
           register variable that's already been used, put_reg_into_stack
-          knows that it should fix up those uses.  */     
+          knows that it should fix up those uses.  */
        TREE_USED (slot) = 1;
 
        if (target == 0)
@@ -8090,10 +8283,7 @@ expand_expr (exp, target, tmode, modifier)
                preserve_temp_slots (target);
                DECL_RTL (slot) = target;
                if (TREE_ADDRESSABLE (slot))
-                 {
-                   TREE_ADDRESSABLE (slot) = 0;
-                   mark_addressable (slot);
-                 }
+                 put_var_into_stack (slot);
 
                /* Since SLOT is not known to the called function
                   to belong to its stack frame, we must build an explicit
@@ -8118,12 +8308,12 @@ expand_expr (exp, target, tmode, modifier)
               not target that we were passed in, as our target
               parameter is only a hint.  */
            if (DECL_RTL (slot) != 0)
-              {
-                target = DECL_RTL (slot);
-                /* If we have already expanded the slot, so don't do
+             {
+               target = DECL_RTL (slot);
+               /* If we have already expanded the slot, so don't do
                    it again.  (mrs)  */
-                if (TREE_OPERAND (exp, 1) == NULL_TREE)
-                  return target;
+               if (TREE_OPERAND (exp, 1) == NULL_TREE)
+                 return target;
              }
            else
              {
@@ -8131,10 +8321,7 @@ expand_expr (exp, target, tmode, modifier)
                /* If we must have an addressable slot, then make sure that
                   the RTL that we just stored in slot is OK.  */
                if (TREE_ADDRESSABLE (slot))
-                 {
-                   TREE_ADDRESSABLE (slot) = 0;
-                   mark_addressable (slot);
-                 }
+                 put_var_into_stack (slot);
              }
          }
 
@@ -8145,7 +8332,7 @@ expand_expr (exp, target, tmode, modifier)
        store_expr (exp1, target, 0);
 
        expand_decl_cleanup (NULL_TREE, cleanups);
-       
+
        return target;
       }
 
@@ -8190,7 +8377,6 @@ expand_expr (exp, target, tmode, modifier)
            && TREE_CODE (lhs) != PARM_DECL
            && ! (TREE_CODE (lhs) == INDIRECT_REF
                  && TYPE_READONLY (TREE_TYPE (TREE_OPERAND (lhs, 0)))))
-         preexpand_calls (exp);
 
        /* Check for |= or &= of a bitfield of size one into another bitfield
           of size 1.  In this case, (unless we need the result of the
@@ -8304,21 +8490,32 @@ expand_expr (exp, target, tmode, modifier)
            }
 
          else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-                  || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
+                  || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
+                  || GET_CODE (op0) == PARALLEL)
            {
              /* If this object is in a register, it must be not
                 be BLKmode.  */
              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-             rtx memloc = assign_temp (inner_type, 1, 1, 1);
+             tree nt = build_qualified_type (inner_type,
+                                             (TYPE_QUALS (inner_type)
+                                              | TYPE_QUAL_CONST));
+             rtx memloc = assign_temp (nt, 1, 1, 1);
 
              mark_temp_addr_taken (memloc);
-             emit_move_insn (memloc, op0);
+             if (GET_CODE (op0) == PARALLEL)
+               /* Handle calls that pass values in multiple non-contiguous
+                  locations.  The Irix 6 ABI has examples of this.  */
+               emit_group_store (memloc, op0,
+                                 int_size_in_bytes (inner_type),
+                                 TYPE_ALIGN (inner_type));
+             else
+               emit_move_insn (memloc, op0);
              op0 = memloc;
            }
 
          if (GET_CODE (op0) != MEM)
            abort ();
-  
+
          if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
            {
              temp = XEXP (op0, 0);
@@ -8393,7 +8590,7 @@ expand_expr (exp, target, tmode, modifier)
     case REALPART_EXPR:
       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
       return gen_realpart (mode, op0);
-      
+
     case IMAGPART_EXPR:
       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
       return gen_imagpart (mode, op0);
@@ -8403,12 +8600,12 @@ expand_expr (exp, target, tmode, modifier)
        enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
        rtx imag_t;
        rtx insns;
-       
-       op0  = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
+
+       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
 
        if (! target)
          target = gen_reg_rtx (mode);
-                                                                   
+
        start_sequence ();
 
        /* Store the realpart and the negated imagpart to target.  */
@@ -8416,15 +8613,18 @@ expand_expr (exp, target, tmode, modifier)
                        gen_realpart (partmode, op0));
 
        imag_t = gen_imagpart (partmode, target);
-       temp = expand_unop (partmode, neg_optab,
-                              gen_imagpart (partmode, op0), imag_t, 0);
+       temp = expand_unop (partmode,
+                            ! unsignedp && flag_trapv
+                            && (GET_MODE_CLASS(partmode) == MODE_INT)
+                            ? negv_optab : neg_optab,
+                           gen_imagpart (partmode, op0), imag_t, 0);
        if (temp != imag_t)
          emit_move_insn (imag_t, temp);
 
        insns = get_insns ();
        end_sequence ();
 
-       /* Conjugate should appear as a single unit 
+       /* Conjugate should appear as a single unit
           If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
           each with a separate pseudo as destination.
           It's not correct for flow to treat them as a unit.  */
@@ -8479,12 +8679,13 @@ expand_expr (exp, target, tmode, modifier)
        return op0;
       }
 
-      case GOTO_SUBROUTINE_EXPR:
+    case GOTO_SUBROUTINE_EXPR:
       {
        rtx subr = (rtx) TREE_OPERAND (exp, 0);
        rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
        rtx return_address = gen_label_rtx ();
-       emit_move_insn (return_link, gen_rtx_LABEL_REF (Pmode, return_address));
+       emit_move_insn (return_link,
+                       gen_rtx_LABEL_REF (Pmode, return_address));
        emit_jump (subr);
        emit_label (return_address);
        return const0_rtx;
@@ -8514,7 +8715,6 @@ expand_expr (exp, target, tmode, modifier)
   /* Here to do an ordinary binary operator, generating an instruction
      from the optab already placed in `this_optab'.  */
  binop:
-  preexpand_calls (exp);
   if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
     subtarget = 0;
   op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
@@ -8593,21 +8793,22 @@ expand_expr_unaligned (exp, palign)
           that was declared const.  */
 
        if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
-           && 0 > compare_tree_int (index, 
+           && host_integerp (index, 0)
+           && 0 > compare_tree_int (index,
                                     list_length (CONSTRUCTOR_ELTS
                                                  (TREE_OPERAND (exp, 0)))))
          {
            tree elem;
 
            for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
-                i = TREE_INT_CST_LOW (index);
+                i = tree_low_cst (index, 0);
                 elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
              ;
 
            if (elem)
              return expand_expr_unaligned (fold (TREE_VALUE (elem)), palign);
          }
-         
+
        else if (optimize >= 1
                 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
                 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
@@ -8633,8 +8834,7 @@ expand_expr_unaligned (exp, palign)
              }
          }
       }
-
-      /* ... fall through ... */
+      /* Fall through.  */
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -8699,7 +8899,10 @@ expand_expr_unaligned (exp, palign)
            if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
              {
-               rtx memloc = assign_temp (TREE_TYPE (tem), 1, 1, 1);
+               tree nt = build_qualified_type (TREE_TYPE (tem),
+                                               (TYPE_QUALS (TREE_TYPE (tem))
+                                                | TYPE_QUAL_CONST));
+               rtx memloc = assign_temp (nt, 1, 1, 1);
 
                mark_temp_addr_taken (memloc);
                emit_move_insn (memloc, op0);
@@ -8733,7 +8936,7 @@ expand_expr_unaligned (exp, palign)
 
        /* Check the access.  */
        if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
-          {
+         {
            rtx to;
            int size;
 
@@ -8743,10 +8946,11 @@ expand_expr_unaligned (exp, palign)
            /* Check the access right of the pointer.  */
            in_check_memory_usage = 1;
            if (size > BITS_PER_UNIT)
-             emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
+             emit_library_call (chkr_check_addr_libfunc,
+                                LCT_CONST_MAKE_BLOCK, VOIDmode, 3,
                                 to, ptr_mode, GEN_INT (size / BITS_PER_UNIT),
                                 TYPE_MODE (sizetype),
-                                GEN_INT (MEMORY_USE_RO), 
+                                GEN_INT (MEMORY_USE_RO),
                                 TYPE_MODE (integer_type_node));
            in_check_memory_usage = 0;
          }
@@ -8780,8 +8984,9 @@ expand_expr_unaligned (exp, palign)
              }
            else
              {
-               rtx new = assign_stack_temp (ext_mode,
-                                            bitsize / BITS_PER_UNIT, 0);
+               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
+                                               TYPE_QUAL_CONST);
+               rtx new = assign_temp (nt, 0, 1, 1);
 
                op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
                                         unsignedp, NULL_RTX, ext_mode,
@@ -8800,7 +9005,6 @@ expand_expr_unaligned (exp, palign)
                                                - bitsize),
                                      op0, 1);
 
-
                emit_move_insn (new, op0);
                op0 = copy_rtx (new);
                PUT_MODE (op0, BLKmode);
@@ -8809,8 +9013,8 @@ expand_expr_unaligned (exp, palign)
        else
          /* Get a reference to just this component.  */
          op0 = change_address (op0, mode1,
-                                 plus_constant (XEXP (op0, 0),
-                                                (bitpos / BITS_PER_UNIT)));
+                               plus_constant (XEXP (op0, 0),
+                                              (bitpos / BITS_PER_UNIT)));
 
        MEM_ALIAS_SET (op0) = get_alias_set (exp);
 
@@ -8966,10 +9170,13 @@ expand_increment (exp, post, ignore)
   if (this_optab == sub_optab
       && GET_CODE (op1) == CONST_INT)
     {
-      op1 = GEN_INT (- INTVAL (op1));
+      op1 = GEN_INT (-INTVAL (op1));
       this_optab = add_optab;
     }
 
+  if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
+     this_optab = this_optab == add_optab ? addv_optab : subv_optab;
+
   /* For a preincrement, see if we can do this with a single instruction.  */
   if (!post)
     {
@@ -9074,7 +9281,7 @@ expand_increment (exp, post, ignore)
 
   /* Increment however we can.  */
   op1 = expand_binop (mode, this_optab, value, op1,
-                     current_function_check_memory_usage ? NULL_RTX : op0,
+                     current_function_check_memory_usage ? NULL_RTX : op0,
                      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
   /* Make sure the value is stored into OP0.  */
   if (op1 != op0)
@@ -9083,88 +9290,6 @@ expand_increment (exp, post, ignore)
   return temp;
 }
 \f
-/* Expand all function calls contained within EXP, innermost ones first.
-   But don't look within expressions that have sequence points.
-   For each CALL_EXPR, record the rtx for its value
-   in the CALL_EXPR_RTL field.  */
-
-static void
-preexpand_calls (exp)
-     tree exp;
-{
-  register int nops, i;
-  int class = TREE_CODE_CLASS (TREE_CODE (exp));
-
-  if (! do_preexpand_calls)
-    return;
-
-  /* Only expressions and references can contain calls.  */
-
-  if (! IS_EXPR_CODE_CLASS (class) && class != 'r')
-    return;
-
-  switch (TREE_CODE (exp))
-    {
-    case CALL_EXPR:
-      /* Do nothing if already expanded.  */
-      if (CALL_EXPR_RTL (exp) != 0
-         /* Do nothing if the call returns a variable-sized object.  */
-         || (TREE_CODE (TREE_TYPE (exp)) != VOID_TYPE
-             && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
-         /* Do nothing to built-in functions.  */
-         || (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
-             && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-                 == FUNCTION_DECL)
-             && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
-       return;
-
-      CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
-      return;
-
-    case COMPOUND_EXPR:
-    case COND_EXPR:
-    case TRUTH_ANDIF_EXPR:
-    case TRUTH_ORIF_EXPR:
-      /* If we find one of these, then we can be sure
-        the adjust will be done for it (since it makes jumps).
-        Do it now, so that if this is inside an argument
-        of a function, we don't get the stack adjustment
-        after some other args have already been pushed.  */
-      do_pending_stack_adjust ();
-      return;
-
-    case BLOCK:
-    case RTL_EXPR:
-    case WITH_CLEANUP_EXPR:
-    case CLEANUP_POINT_EXPR:
-    case TRY_CATCH_EXPR:
-      return;
-
-    case SAVE_EXPR:
-      if (SAVE_EXPR_RTL (exp) != 0)
-       return;
-      
-    default:
-      break;
-    }
-
-  nops = TREE_CODE_LENGTH (TREE_CODE (exp));
-  for (i = 0; i < nops; i++)
-    if (TREE_OPERAND (exp, i) != 0)
-      {
-       if (TREE_CODE (exp) == TARGET_EXPR && i == 2)
-         /* We don't need to preexpand the cleanup for a TARGET_EXPR.
-            It doesn't happen before the call is made.  */
-         ;
-       else
-         {
-           class = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
-           if (IS_EXPR_CODE_CLASS (class) || class == 'r')
-             preexpand_calls (TREE_OPERAND (exp, i));
-         }
-      }
-}
-\f
 /* At the start of a function, record that we have no previously-pushed
    arguments waiting to be popped.  */
 
@@ -9582,7 +9707,7 @@ do_jump (exp, if_false_label, if_true_label)
          cmp = UNORDERED, rcmp = ORDERED;
        else
          cmp = ORDERED, rcmp = UNORDERED;
-        mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
 
        do_rev = 0;
        if (! can_compare_p (cmp, mode, ccp_jump)
@@ -9635,7 +9760,7 @@ do_jump (exp, if_false_label, if_true_label)
            tree op1 = save_expr (TREE_OPERAND (exp, 1));
            tree cmp0, cmp1;
 
-           /* If the target doesn't support combined unordered 
+           /* If the target doesn't support combined unordered
               compares, decompose into UNORDERED + comparison.  */
            cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
            cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
@@ -9661,7 +9786,9 @@ do_jump (exp, if_false_label, if_true_label)
       /* Do any postincrements in the expression that was tested.  */
       emit_queue ();
 
-      if (GET_CODE (temp) == CONST_INT || GET_CODE (temp) == LABEL_REF)
+      if (GET_CODE (temp) == CONST_INT 
+         || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
+         || GET_CODE (temp) == LABEL_REF)
        {
          rtx target = temp == const0_rtx ? if_false_label : if_true_label;
          if (target)
@@ -9914,7 +10041,7 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
       unsignedp = 1;
     }
 #endif
-       
+
   emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align);
 
   return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
@@ -10055,8 +10182,22 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
     return;
 
   op1 = expand_expr_unaligned (TREE_OPERAND (exp, 1), &align1);
+  if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
+    return;
+
   type = TREE_TYPE (TREE_OPERAND (exp, 0));
   mode = TYPE_MODE (type);
+  if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
+      && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
+         || (GET_MODE_BITSIZE (mode)
+             > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
+                                                                     1)))))))
+    {
+      /* op0 might have been replaced by promoted constant, in which
+        case the type of second argument should be used.  */
+      type = TREE_TYPE (TREE_OPERAND (exp, 1));
+      mode = TYPE_MODE (type);
+    }
   unsignedp = TREE_UNSIGNED (type);
   code = unsignedp ? unsigned_code : signed_code;
 
@@ -10144,6 +10285,11 @@ do_store_flag (exp, target, mode, only_cheap)
 
   arg0 = TREE_OPERAND (exp, 0);
   arg1 = TREE_OPERAND (exp, 1);
+
+  /* Don't crash if the comparison was erroneous.  */
+  if (arg0 == error_mark_node || arg1 == error_mark_node)
+    return const0_rtx;
+
   type = TREE_TYPE (arg0);
   operand_mode = TYPE_MODE (type);
   unsignedp = TREE_UNSIGNED (type);
@@ -10289,7 +10435,7 @@ do_store_flag (exp, target, mode, only_cheap)
       op0 = expand_expr (inner, subtarget, VOIDmode, 0);
 
       if (bitnum != 0)
-       op0 = expand_shift (RSHIFT_EXPR, GET_MODE (op0), op0,
+       op0 = expand_shift (RSHIFT_EXPR, operand_mode, op0,
                            size_int (bitnum), subtarget, ops_unsignedp);
 
       if (GET_MODE (op0) != mode)
@@ -10330,8 +10476,7 @@ do_store_flag (exp, target, mode, only_cheap)
       else
        return 0;
     }
-      
-  preexpand_calls (exp);
+
   if (! get_subtarget (target)
       || GET_MODE (subtarget) != operand_mode
       || ! safe_from_p (subtarget, arg1, 1))
@@ -10459,4 +10604,4 @@ do_tablejump (index, mode, range, table_label, default_label)
     emit_barrier ();
 }
 
-#endif /* HAVE_tablejump */
+#endif /* HAVE_tablejump  */