OSDN Git Service

Replace inclusion of <stdio.h> with "system.h"
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 447382b..ce4ecc7 100644 (file)
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA.  */
 /* 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"
@@ -45,6 +46,19 @@ Boston, MA 02111-1307, USA.  */
 #include "intl.h"
 #include "tm_p.h"
 
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
+
+/* Supply a default definition for PUSH_ARGS.  */
+#ifndef PUSH_ARGS
+#ifdef PUSH_ROUNDING
+#define PUSH_ARGS      !ACCUMULATE_OUTGOING_ARGS
+#else
+#define PUSH_ARGS      0
+#endif
+#endif
+
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
 
@@ -191,8 +205,8 @@ static char direct_store[NUM_MACHINE_MODES];
 /* This macro is used to determine whether move_by_pieces should be called
    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)
+#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
+  (move_by_pieces_ninsns (SIZE, ALIGN) < MOVE_RATIO)
 #endif
 
 /* This array records the insn_code of insns to perform block moves.  */
@@ -293,7 +307,7 @@ init_expr ()
 
   pending_chain = 0;
   pending_stack_adjust = 0;
-  arg_space_so_far = 0;
+  stack_pointer_delta = 0;
   inhibit_defer_pop = 0;
   saveregs_value = 0;
   apply_args_value = 0;
@@ -1352,7 +1366,7 @@ convert_modes (mode, oldmode, x, unsignedp)
 
 /* 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 bhytes 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
@@ -1362,7 +1376,7 @@ convert_modes (mode, oldmode, x, unsignedp)
    from block FROM to block TO.  (These are MEM rtx's with BLKmode).
    The caller must pass FROM and TO
     through protect_from_queue before calling.
-   ALIGN (in bytes) is maximum alignment we can assume.  */
+   ALIGN is maximum alignment we can assume.  */
 
 void
 move_by_pieces (to, from, len, align)
@@ -1444,8 +1458,8 @@ move_by_pieces (to, from, len, align)
     }
 
   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
-    align = MOVE_MAX;
+      || 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
      successively smaller modes.  */
@@ -1461,9 +1475,7 @@ move_by_pieces (to, from, len, align)
        break;
 
       icode = mov_optab->handlers[(int) mode].insn_code;
-      if (icode != CODE_FOR_nothing
-         && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
-                          (unsigned int) GET_MODE_SIZE (mode)))
+      if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        move_by_pieces_1 (GEN_FCN (icode), mode, &data);
 
       max_size = GET_MODE_SIZE (mode);
@@ -1486,8 +1498,8 @@ move_by_pieces_ninsns (l, align)
   unsigned int max_size = MOVE_MAX + 1;
 
   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
-    align = MOVE_MAX;
+      || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
+    align = MOVE_MAX * BITS_PER_UNIT;
 
   while (max_size > 1)
     {
@@ -1503,8 +1515,7 @@ move_by_pieces_ninsns (l, align)
        break;
 
       icode = mov_optab->handlers[(int) mode].insn_code;
-      if (icode != CODE_FOR_nothing
-         && align >= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
+      if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
 
       max_size = GET_MODE_SIZE (mode);
@@ -1571,8 +1582,7 @@ move_by_pieces_1 (genfun, mode, data)
    Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
    with mode BLKmode.
    SIZE is an rtx that says how long they are.
-   ALIGN is the maximum alignment we can assume they have,
-   measured in bytes. 
+   ALIGN is the maximum alignment we can assume they have.
 
    Return the address of the new block, if memcpy is called and returns it,
    0 otherwise.  */
@@ -1614,9 +1624,12 @@ emit_block_move (x, y, size, align)
         including more than one in the machine description unless
         the more limited one has some advantage.  */
 
-      rtx opalign = GEN_INT (align);
+      rtx opalign = GEN_INT (align / BITS_PER_UNIT);
       enum machine_mode mode;
 
+      /* Since this is a move insn, we don't care about volatility.  */
+      volatile_ok = 1;
+
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
           mode = GET_MODE_WIDER_MODE (mode))
        {
@@ -1652,6 +1665,7 @@ emit_block_move (x, y, size, align)
              if (pat)
                {
                  emit_insn (pat);
+                 volatile_ok = 0;
                  return 0;
                }
              else
@@ -1659,6 +1673,8 @@ emit_block_move (x, y, size, align)
            }
        }
 
+      volatile_ok = 0;
+
       /* X, Y, or SIZE may have been passed through protect_from_queue.
 
         It is unsafe to save the value generated by protect_from_queue
@@ -1939,7 +1955,7 @@ emit_group_load (dst, orig_src, ssize, align)
 
       /* Optimize the access just a bit.  */
       if (GET_CODE (src) == MEM
-         && align * BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
+         && align >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
        {
@@ -1961,18 +1977,15 @@ emit_group_load (dst, orig_src, ssize, align)
            abort ();
        }
       else
-       {
-         tmps[i] = extract_bit_field (src, bytelen*BITS_PER_UNIT,
-                                      bytepos*BITS_PER_UNIT, 1, NULL_RTX,
-                                      mode, mode, align, ssize);
-       }
+       tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
+                                    bytepos * BITS_PER_UNIT, 1, NULL_RTX,
+                                    mode, mode, align, ssize);
 
       if (BYTES_BIG_ENDIAN && shift)
-       {
-         expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
-                       tmps[i], 0, OPTAB_WIDEN);
-       }
+       expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
+                     tmps[i], 0, OPTAB_WIDEN);
     }
+
   emit_queue();
 
   /* Copy the extracted pieces into the proper (probable) hard regs.  */
@@ -2072,7 +2085,7 @@ emit_group_store (orig_dst, src, ssize, align)
 
       /* Optimize the access just a bit.  */
       if (GET_CODE (dst) == MEM
-         && align * BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
+         && align >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
        emit_move_insn (change_address (dst, mode,
@@ -2101,74 +2114,69 @@ emit_group_store (orig_dst, src, ssize, align)
    in registers regardless of the structure's alignment. */
 
 rtx
-copy_blkmode_from_reg (tgtblk,srcreg,type)
+copy_blkmode_from_reg (tgtblk, srcreg, type)
      rtx tgtblk;
      rtx srcreg;
      tree type;
 {
-      int bytes = int_size_in_bytes (type);
-      rtx src = NULL, dst = NULL;
-      int bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
-      int bitpos, xbitpos, big_endian_correction = 0;
-      
-      if (tgtblk == 0)
-       {
-         tgtblk = assign_stack_temp (BLKmode, bytes, 0);
-         MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
-         preserve_temp_slots (tgtblk);
-       }
+  unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
+  rtx src = NULL, dst = NULL;
+  unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
+  unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
+
+  if (tgtblk == 0)
+    {
+      tgtblk = assign_stack_temp (BLKmode, bytes, 0);
+      MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
+      preserve_temp_slots (tgtblk);
+    }
       
-      /* This code assumes srcreg is at least a full word.  If it isn't,
-        copy it into a new pseudo which is a full word.  */
-      if (GET_MODE (srcreg) != BLKmode
-         && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
-       srcreg = convert_to_mode (word_mode, srcreg,
-                                 TREE_UNSIGNED (type));
-
-      /* Structures whose size is not a multiple of a word are aligned
-        to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
-        machine, this means we must skip the empty high order bytes when
-        calculating the bit offset.  */
-      if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
-       big_endian_correction = (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.  */
-      for (bitpos = 0, xbitpos = big_endian_correction;
-          bitpos < bytes * BITS_PER_UNIT;
-          bitpos += bitsize, xbitpos += bitsize)
-       {
-
-         /* 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
-             || xbitpos == big_endian_correction)
-           src = operand_subword_force (srcreg,
-                                        xbitpos / BITS_PER_WORD, 
-                                        BLKmode);
-
-         /* We need a new destination operand each time bitpos is on
-            a word boundary.  */
-         if (bitpos % BITS_PER_WORD == 0)
-           dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
+  /* This code assumes srcreg is at least a full word.  If it isn't,
+     copy it into a new pseudo which is a full word.  */
+  if (GET_MODE (srcreg) != BLKmode
+      && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
+    srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
+
+  /* Structures whose size is not a multiple of a word are aligned
+     to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
+     machine, this means we must skip the empty high order bytes when
+     calculating the bit offset.  */
+  if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+    big_endian_correction
+      = (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.  */
+  for (bitpos = 0, xbitpos = big_endian_correction;
+       bitpos < bytes * BITS_PER_UNIT;
+       bitpos += bitsize, xbitpos += bitsize)
+    {
+      /* 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
+         || xbitpos == big_endian_correction)
+       src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD, BLKmode);
+
+      /* We need a new destination operand each time bitpos is on
+        a word boundary.  */
+      if (bitpos % BITS_PER_WORD == 0)
+       dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
              
-         /* 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,
-                          extract_bit_field (src, bitsize,
-                                             xbitpos % BITS_PER_WORD, 1,
-                                             NULL_RTX, word_mode,
-                                             word_mode,
-                                             bitsize / BITS_PER_UNIT,
-                                             BITS_PER_WORD),
-                          bitsize / BITS_PER_UNIT, BITS_PER_WORD);
-       }
-      return tgtblk;
+      /* 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,
+                      extract_bit_field (src, bitsize,
+                                         xbitpos % BITS_PER_WORD, 1,
+                                         NULL_RTX, word_mode, word_mode,
+                                         bitsize, BITS_PER_WORD),
+                      bitsize, BITS_PER_WORD);
+    }
+
+  return tgtblk;
 }
 
 
@@ -2229,10 +2237,9 @@ use_group_regs (call_fusage, regs)
     }
 }
 \f
-/* 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 (in bytes) is maximum alignment
-   we can assume.  */
+/* 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.  */
 
 static void
 clear_by_pieces (to, len, align)
@@ -2290,8 +2297,8 @@ clear_by_pieces (to, len, align)
     }
 
   if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-      || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
-    align = MOVE_MAX;
+      || 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
      successively smaller modes.  */
@@ -2307,8 +2314,7 @@ clear_by_pieces (to, len, align)
        break;
 
       icode = mov_optab->handlers[(int) mode].insn_code;
-      if (icode != CODE_FOR_nothing
-         && align >= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
+      if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
        clear_by_pieces_1 (GEN_FCN (icode), mode, &data);
 
       max_size = GET_MODE_SIZE (mode);
@@ -2356,9 +2362,8 @@ clear_by_pieces_1 (genfun, mode, data)
     }
 }
 \f
-/* Write zeros through the storage of OBJECT.
-   If OBJECT has BLKmode, SIZE is its length in bytes and ALIGN is
-   the maximum alignment we can is has, measured in bytes.
+/* Write zeros through the storage of OBJECT.  If OBJECT has BLKmode, SIZE is
+   its length in bytes and ALIGN is the maximum alignment we can is has.
 
    If we call a function that returns the length of the block, return it.  */
 
@@ -2382,14 +2387,13 @@ clear_storage (object, size, align)
       if (GET_CODE (size) == CONST_INT
          && MOVE_BY_PIECES_P (INTVAL (size), align))
        clear_by_pieces (object, INTVAL (size), align);
-
       else
        {
          /* Try the most limited insn first, because there's no point
             including more than one in the machine description unless
             the more limited one has some advantage.  */
 
-         rtx opalign = GEN_INT (align);
+         rtx opalign = GEN_INT (align / BITS_PER_UNIT);
          enum machine_mode mode;
 
          for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
@@ -2723,7 +2727,7 @@ emit_move_insn_1 (x, y)
   else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
     {
       rtx last_insn = 0;
-      rtx seq;
+      rtx seq, inner;
       int need_clobber;
       
 #ifdef PUSH_ROUNDING
@@ -2737,6 +2741,29 @@ emit_move_insn_1 (x, y)
        }
 #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
+         && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
+       {
+         rtx new = gen_rtx_MEM (GET_MODE (x), inner);
+
+         RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
+         MEM_COPY_ATTRIBUTES (new, x);
+         MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
+         x = new;
+       }
+      if (reload_in_progress && GET_CODE (y) == MEM
+         && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
+       {
+         rtx new = gen_rtx_MEM (GET_MODE (y), inner);
+
+         RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (y);
+         MEM_COPY_ATTRIBUTES (new, y);
+         MEM_ALIAS_SET (new) = MEM_ALIAS_SET (y);
+         y = new;
+       }
+
       start_sequence ();
 
       need_clobber = 0;
@@ -2813,34 +2840,42 @@ push_block (size, extra, below)
     anti_adjust_stack (size);
   else
     {
-      rtx temp = copy_to_mode_reg (Pmode, size);
+      temp = copy_to_mode_reg (Pmode, size);
       if (extra != 0)
        temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
                             temp, 0, OPTAB_LIB_WIDEN);
       anti_adjust_stack (temp);
     }
 
-#if defined (STACK_GROWS_DOWNWARD) \
-    || (defined (ARGS_GROW_DOWNWARD) \
-       && !defined (ACCUMULATE_OUTGOING_ARGS))
-
-  /* Return the lowest stack address when STACK or ARGS grow downward and
-     we are not aaccumulating outgoing arguments (the c4x port uses such
-     conventions).  */
-  temp = virtual_outgoing_args_rtx;
-  if (extra != 0 && below)
-    temp = plus_constant (temp, extra);
+#ifndef STACK_GROWS_DOWNWARD
+#ifdef ARGS_GROW_DOWNWARD
+  if (!ACCUMULATE_OUTGOING_ARGS)
 #else
-  if (GET_CODE (size) == CONST_INT)
-    temp = plus_constant (virtual_outgoing_args_rtx,
-                         - INTVAL (size) - (below ? 0 : extra));
-  else if (extra != 0 && !below)
-    temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
-                   negate_rtx (Pmode, plus_constant (size, extra)));
-  else
-    temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
-                        negate_rtx (Pmode, size));
+  if (0)
 #endif
+#else
+  if (1)
+#endif
+    {
+      /* Return the lowest stack address when STACK or ARGS grow downward and
+        we are not aaccumulating outgoing arguments (the c4x port uses such
+        conventions).  */
+      temp = virtual_outgoing_args_rtx;
+      if (extra != 0 && below)
+       temp = plus_constant (temp, extra);
+    }
+  else
+    {
+      if (GET_CODE (size) == CONST_INT)
+       temp = plus_constant (virtual_outgoing_args_rtx,
+                             - INTVAL (size) - (below ? 0 : extra));
+      else if (extra != 0 && !below)
+       temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
+                       negate_rtx (Pmode, plus_constant (size, extra)));
+      else
+       temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
+                            negate_rtx (Pmode, size));
+    }
 
   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
 }
@@ -2877,7 +2912,7 @@ get_push_address (size)
    SIZE is an rtx for the size of data to be copied (in bytes),
    needed only if X is BLKmode.
 
-   ALIGN (in bytes) is maximum alignment we can assume.
+   ALIGN is maximum alignment we can assume.
 
    If PARTIAL and REG are both nonzero, then copy that many of the first
    words of X into registers starting with REG, and push the rest of X.
@@ -2971,6 +3006,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
         and if there is no difficulty with push insns that skip bytes
         on the stack for alignment purposes.  */
       if (args_addr == 0
+         && PUSH_ARGS
          && GET_CODE (size) == CONST_INT
          && skip == 0
          && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
@@ -2978,7 +3014,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
             forces many pushes of a small amount of data,
             and such small pushes do rounding that causes trouble.  */
          && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
-             || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT
+             || align >= BIGGEST_ALIGNMENT
              || PUSH_ROUNDING (align) == align)
          && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
        {
@@ -2989,6 +3025,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
              && where_pad != none && where_pad != stack_direction)
            anti_adjust_stack (GEN_INT (extra));
 
+         stack_pointer_delta += INTVAL (size) - used;
          move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
                          INTVAL (size) - used, align);
 
@@ -3079,7 +3116,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            }
          else
            {
-             rtx opalign = GEN_INT (align);
+             rtx opalign = GEN_INT (align / BITS_PER_UNIT);
              enum machine_mode mode;
              rtx target = gen_rtx_MEM (BLKmode, temp);
 
@@ -3123,15 +3160,16 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                }
            }
 
-#ifndef ACCUMULATE_OUTGOING_ARGS
-         /* If the source is referenced relative to the stack pointer,
-            copy it to another register to stabilize it.  We do not need
-            to do this if we know that we won't be changing sp.  */
+         if (!ACCUMULATE_OUTGOING_ARGS)
+           {
+             /* If the source is referenced relative to the stack pointer,
+                copy it to another register to stabilize it.  We do not need
+                to do this if we know that we won't be changing sp.  */
 
-         if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
-             || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
-           temp = copy_to_reg (temp);
-#endif
+             if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
+                 || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
+               temp = copy_to_reg (temp);
+           }
 
          /* Make inhibit_defer_pop nonzero around the library call
             to force it to pop the bcopy-arguments right away.  */
@@ -3227,8 +3265,11 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
        anti_adjust_stack (GEN_INT (extra));
 
 #ifdef PUSH_ROUNDING
-      if (args_addr == 0)
-       addr = gen_push_operand ();
+      if (args_addr == 0 && PUSH_ARGS)
+       {
+         addr = gen_push_operand ();
+         stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+       }
       else
 #endif
        {
@@ -3369,7 +3410,7 @@ expand_assignment (to, from, want_value, suggest_reg)
              && bitsize
              && (bitpos % bitsize) == 0 
              && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-             && (alignment * BITS_PER_UNIT) == GET_MODE_ALIGNMENT (mode1))
+             && alignment == GET_MODE_ALIGNMENT (mode1))
            {
              rtx temp = change_address (to_rtx, mode1,
                                         plus_constant (XEXP (to_rtx, 0),
@@ -3459,7 +3500,7 @@ expand_assignment (to, from, want_value, suggest_reg)
                                             bitpos / BITS_PER_UNIT));
 
          emit_block_move (inner_to_rtx, from_rtx, expr_size (from),
-                          MIN (alignment, from_align / BITS_PER_UNIT));
+                          MIN (alignment, from_align));
          free_temp_slots ();
          pop_temp_slots ();
          return to_rtx;
@@ -3473,7 +3514,6 @@ expand_assignment (to, from, want_value, suggest_reg)
                                    TYPE_MODE (TREE_TYPE (to)))
                                 : VOIDmode),
                                unsignedp,
-                               /* Required alignment of containing datum.  */
                                alignment,
                                int_size_in_bytes (TREE_TYPE (tem)),
                                get_alias_set (to));
@@ -3518,10 +3558,10 @@ expand_assignment (to, from, want_value, suggest_reg)
         The Irix 6 ABI has examples of this.  */
       if (GET_CODE (to_rtx) == PARALLEL)
        emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)),
-                        TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+                        TYPE_ALIGN (TREE_TYPE (from)));
       else if (GET_MODE (to_rtx) == BLKmode)
        emit_block_move (to_rtx, value, expr_size (from),
-                        TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+                        TYPE_ALIGN (TREE_TYPE (from)));
       else
        {
 #ifdef POINTERS_EXTEND_UNSIGNED
@@ -3558,7 +3598,7 @@ expand_assignment (to, from, want_value, suggest_reg)
 
       if (GET_CODE (to_rtx) == PARALLEL)
        emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)),
-                        TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
+                        TYPE_ALIGN (TREE_TYPE (from)));
       else
        emit_move_insn (to_rtx, temp);
 
@@ -3884,8 +3924,7 @@ store_expr (exp, target, want_value)
          size = expr_size (exp);
          if (GET_CODE (size) == CONST_INT
              && INTVAL (size) < TREE_STRING_LENGTH (exp))
-           emit_block_move (target, temp, size,
-                            TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+           emit_block_move (target, temp, size, TYPE_ALIGN (TREE_TYPE (exp)));
          else
            {
              /* Compute the size of the data to copy from the string.  */
@@ -3893,13 +3932,14 @@ store_expr (exp, target, want_value)
                = size_binop (MIN_EXPR,
                              make_tree (sizetype, size),
                              size_int (TREE_STRING_LENGTH (exp)));
+             int align = TYPE_ALIGN (TREE_TYPE (exp));
              rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX,
                                               VOIDmode, 0);
              rtx label = 0;
 
              /* Copy that much.  */
              emit_block_move (target, temp, copy_size_rtx,
-                              TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+                              TYPE_ALIGN (TREE_TYPE (exp)));
 
              /* Figure out how much is left in TARGET that we have to clear.
                 Do all calculations in ptr_mode.  */
@@ -3911,6 +3951,9 @@ store_expr (exp, target, want_value)
                {
                  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))));
                }
              else
                {
@@ -3923,10 +3966,12 @@ store_expr (exp, target, want_value)
                                       copy_size_rtx, NULL_RTX, 0,
                                       OPTAB_LIB_WIDEN);
 
+                 align = BITS_PER_UNIT;
                  label = gen_label_rtx ();
                  emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
                                           GET_MODE (size), 0, 0, label);
                }
+             align = MIN (align, expr_align (copy_size));
 
              if (size != const0_rtx)
                {
@@ -3937,22 +3982,7 @@ store_expr (exp, target, want_value)
                                       size, TYPE_MODE (sizetype),
                                       GEN_INT (MEMORY_USE_WO), 
                                       TYPE_MODE (integer_type_node));
-#ifdef TARGET_MEM_FUNCTIONS
-                 emit_library_call (memset_libfunc, 0, VOIDmode, 3,
-                                    addr, ptr_mode,
-                                    const0_rtx, TYPE_MODE (integer_type_node),
-                                    convert_to_mode (TYPE_MODE (sizetype),
-                                                     size,
-                                                     TREE_UNSIGNED (sizetype)),
-                                    TYPE_MODE (sizetype));
-#else
-                 emit_library_call (bzero_libfunc, 0, VOIDmode, 2,
-                                    addr, ptr_mode,
-                                    convert_to_mode (TYPE_MODE (integer_type_node),
-                                                     size,
-                                                     TREE_UNSIGNED (integer_type_node)),
-                                    TYPE_MODE (integer_type_node));
-#endif
+                 clear_storage (gen_rtx_MEM (BLKmode, addr), size, align);
                }
 
              if (label)
@@ -3963,10 +3993,10 @@ store_expr (exp, target, want_value)
         The Irix 6 ABI has examples of this.  */
       else if (GET_CODE (target) == PARALLEL)
        emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)),
-                        TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+                        TYPE_ALIGN (TREE_TYPE (exp)));
       else if (GET_MODE (temp) == BLKmode)
        emit_block_move (target, temp, expr_size (exp),
-                        TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
+                        TYPE_ALIGN (TREE_TYPE (exp)));
       else
        emit_move_insn (target, temp);
     }
@@ -4102,14 +4132,13 @@ store_constructor_field (target, bitsize, bitpos,
       store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
     }
   else
-    store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, 
-                (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT,
+    store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, align,
                 int_size_in_bytes (type), 0);
 }
 
 /* Store the value of constructor EXP into the rtx TARGET.
    TARGET is either a REG or a MEM.
-   ALIGN is the maximum known alignment for TARGET, in bits.
+   ALIGN is the maximum known alignment for TARGET.
    CLEARED is true if TARGET is known to have been zero'd.
    SIZE is the number of bytes of TARGET we are allowed to modify: this
    may not be the same as the size of EXP if we are assigning to a field
@@ -4156,8 +4185,7 @@ store_constructor (exp, target, align, cleared, size)
 
          /* If the constructor is empty, clear the union.  */
          if (! CONSTRUCTOR_ELTS (exp)  && ! cleared)
-           clear_storage (target, expr_size (exp),
-                          TYPE_ALIGN (type) / BITS_PER_UNIT);
+           clear_storage (target, expr_size (exp), TYPE_ALIGN (type));
        }
 
       /* If we are building a static constructor into a register,
@@ -4182,8 +4210,7 @@ store_constructor (exp, target, align, cleared, size)
                   || mostly_zeros_p (exp)))
        {
          if (! cleared)
-           clear_storage (target, GEN_INT (size),
-                          (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+           clear_storage (target, GEN_INT (size), align);
 
          cleared = 1;
        }
@@ -4241,12 +4268,9 @@ store_constructor (exp, target, align, cleared, size)
              rtx offset_rtx;
 
              if (contains_placeholder_p (offset))
-               offset = build (WITH_RECORD_EXPR, bitsizetype,
+               offset = build (WITH_RECORD_EXPR, sizetype,
                                offset, make_tree (TREE_TYPE (exp), target));
 
-             offset = size_binop (EXACT_DIV_EXPR, offset, bitsize_unit_node);
-             offset = convert (sizetype, offset);
-
              offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
              if (GET_CODE (to_rtx) != MEM)
                abort ();
@@ -4265,6 +4289,7 @@ store_constructor (exp, target, align, cleared, size)
                                  gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
                                                force_reg (ptr_mode,
                                                           offset_rtx)));
+             align = DECL_OFFSET_ALIGN (field);
            }
 
          if (TREE_READONLY (field))
@@ -4303,10 +4328,7 @@ store_constructor (exp, target, align, cleared, size)
            }
 #endif
          store_constructor_field (to_rtx, bitsize, bitpos, mode,
-                                  TREE_VALUE (elt), type, 
-                                  MIN (align,
-                                       DECL_ALIGN (TREE_PURPOSE (elt))),
-                                  cleared);
+                                  TREE_VALUE (elt), type, align, cleared);
        }
     }
   else if (TREE_CODE (type) == ARRAY_TYPE)
@@ -4337,19 +4359,21 @@ store_constructor (exp, target, align, cleared, size)
            {
              tree index = TREE_PURPOSE (elt);
              HOST_WIDE_INT this_node_count;
+
              if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
                {
                  tree lo_index = TREE_OPERAND (index, 0);
                  tree hi_index = TREE_OPERAND (index, 1);
 
-                 if (TREE_CODE (lo_index) != INTEGER_CST
-                     || TREE_CODE (hi_index) != INTEGER_CST)
+                 if (! host_integerp (lo_index, 1)
+                     || ! host_integerp (hi_index, 1))
                    {
                      need_to_clear = 1;
                      break;
                    }
-                 this_node_count = (TREE_INT_CST_LOW (hi_index)
-                                    - TREE_INT_CST_LOW (lo_index) + 1);
+
+                 this_node_count = (tree_low_cst (hi_index, 1)
+                                    - tree_low_cst (lo_index, 1) + 1);
                }
              else
                this_node_count = 1;
@@ -4366,8 +4390,7 @@ store_constructor (exp, target, align, cleared, size)
       if (need_to_clear && size > 0)
        {
          if (! cleared)
-           clear_storage (target, GEN_INT (size),
-                          (align + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+           clear_storage (target, GEN_INT (size), align);
          cleared = 1;
        }
       else
@@ -4382,8 +4405,8 @@ store_constructor (exp, target, align, cleared, size)
           elt = TREE_CHAIN (elt), i++)
        {
          register enum machine_mode mode;
-         int bitsize;
-         int bitpos;
+         HOST_WIDE_INT bitsize;
+         HOST_WIDE_INT bitpos;
          int unsignedp;
          tree value = TREE_VALUE (elt);
          unsigned int align = TYPE_ALIGN (TREE_TYPE (value));
@@ -4396,13 +4419,9 @@ store_constructor (exp, target, align, cleared, size)
          unsignedp = TREE_UNSIGNED (elttype);
          mode = TYPE_MODE (elttype);
          if (mode == BLKmode)
-           {
-             if (TREE_CODE (TYPE_SIZE (elttype)) == INTEGER_CST
-                 && TREE_INT_CST_HIGH (TYPE_SIZE (elttype)) == 0)
-               bitsize = TREE_INT_CST_LOW (TYPE_SIZE (elttype));
-             else
-               bitsize = -1;
-           }
+           bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
+                      ? tree_low_cst (TYPE_SIZE (elttype), 1)
+                      : -1);
          else
            bitsize = GET_MODE_BITSIZE (mode);
 
@@ -4416,21 +4435,21 @@ store_constructor (exp, target, align, cleared, size)
              tree position;
 
              /* If the range is constant and "small", unroll the loop.  */
-             if (TREE_CODE (lo_index) == INTEGER_CST
-                 && TREE_CODE (hi_index) == INTEGER_CST
-                 && (lo = TREE_INT_CST_LOW (lo_index),
-                     hi = TREE_INT_CST_LOW (hi_index),
+             if (host_integerp (lo_index, 0)
+                 && host_integerp (hi_index, 0)
+                 && (lo = tree_low_cst (lo_index, 0),
+                     hi = tree_low_cst (hi_index, 0),
                      count = hi - lo + 1,
                      (GET_CODE (target) != MEM
                       || count <= 2
-                      || (TREE_CODE (TYPE_SIZE (elttype)) == INTEGER_CST
-                          && TREE_INT_CST_LOW (TYPE_SIZE (elttype)) * count
-                          <= 40 * 8))))
+                      || (host_integerp (TYPE_SIZE (elttype), 1)
+                          && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
+                              <= 40 * 8)))))
                {
                  lo -= minelt;  hi -= minelt;
                  for (; lo <= hi; lo++)
                    {
-                     bitpos = lo * TREE_INT_CST_LOW (TYPE_SIZE (elttype));
+                     bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
                      store_constructor_field (target, bitsize, bitpos, mode,
                                               value, type, align, cleared);
                    }
@@ -4489,8 +4508,8 @@ store_constructor (exp, target, align, cleared, size)
                  emit_label (loop_end);
                }
            }
-         else if ((index != 0 && TREE_CODE (index) != INTEGER_CST)
-             || TREE_CODE (TYPE_SIZE (elttype)) != INTEGER_CST)
+         else if ((index != 0 && ! host_integerp (index, 0))
+                  || ! host_integerp (TYPE_SIZE (elttype), 1))
            {
              rtx pos_rtx, addr;
              tree position;
@@ -4502,6 +4521,7 @@ store_constructor (exp, target, align, cleared, size)
                index = convert (ssizetype,
                                 fold (build (MINUS_EXPR, index,
                                              TYPE_MIN_VALUE (domain))));
+
              position = size_binop (MULT_EXPR, index,
                                     convert (ssizetype,
                                              TYPE_SIZE_UNIT (elttype)));
@@ -4513,20 +4533,22 @@ store_constructor (exp, target, align, cleared, size)
          else
            {
              if (index != 0)
-               bitpos = ((TREE_INT_CST_LOW (index) - minelt)
-                         * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
+               bitpos = ((tree_low_cst (index, 0) - minelt)
+                         * tree_low_cst (TYPE_SIZE (elttype), 1));
              else
-               bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
+               bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
+
              store_constructor_field (target, bitsize, bitpos, mode, value,
                                       type, align, cleared);
            }
        }
     }
-  /* set constructor assignments */
+
+  /* Set constructor assignments */
   else if (TREE_CODE (type) == SET_TYPE)
     {
       tree elt = CONSTRUCTOR_ELTS (exp);
-      int nbytes = int_size_in_bytes (type), nbits;
+      unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
       tree domain = TYPE_DOMAIN (type);
       tree domain_min, domain_max, bitlength;
 
@@ -4544,8 +4566,7 @@ store_constructor (exp, target, align, cleared, size)
       if (elt == NULL_TREE && size > 0)
        {
          if (!cleared)
-           clear_storage (target, GEN_INT (size),
-                          TYPE_ALIGN (type) / BITS_PER_UNIT);
+           clear_storage (target, GEN_INT (size), TYPE_ALIGN (type));
          return;
        }
 
@@ -4555,9 +4576,7 @@ store_constructor (exp, target, align, cleared, size)
                              size_diffop (domain_max, domain_min),
                              ssize_int (1));
 
-      if (nbytes < 0 || TREE_CODE (bitlength) != INTEGER_CST)
-       abort ();
-      nbits = TREE_INT_CST_LOW (bitlength);
+      nbits = tree_low_cst (bitlength, 1);
 
       /* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
         are "complicated" (more than one range), initialize (the
@@ -4565,13 +4584,14 @@ store_constructor (exp, target, align, cleared, size)
       if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
          || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
        {
-         int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
+         unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
          enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
          char *bit_buffer = (char *) alloca (nbits);
          HOST_WIDE_INT word = 0;
-         int bit_pos = 0;
-         int ibit = 0;
-         int offset = 0;  /* In bytes from beginning of set.  */
+         unsigned int bit_pos = 0;
+         unsigned int ibit = 0;
+         unsigned int offset = 0;  /* In bytes from beginning of set.  */
+
          elt = get_set_constructor_bits (exp, bit_buffer, nbits);
          for (;;)
            {
@@ -4582,6 +4602,7 @@ store_constructor (exp, target, align, cleared, size)
                  else
                    word |= 1 << bit_pos;
                }
+
              bit_pos++;  ibit++;
              if (bit_pos >= set_word_size || ibit == nbits)
                {
@@ -4589,6 +4610,7 @@ store_constructor (exp, target, align, cleared, size)
                    {
                      rtx datum = GEN_INT (word);
                      rtx to_rtx;
+
                      /* The assumption here is that it is safe to use
                         XEXP if the set is multi-word, but not if
                         it's single-word.  */
@@ -4603,6 +4625,7 @@ store_constructor (exp, target, align, cleared, size)
                        abort ();
                      emit_move_insn (to_rtx, datum);
                    }
+
                  if (ibit == nbits)
                    break;
                  word = 0;
@@ -4612,19 +4635,16 @@ store_constructor (exp, target, align, cleared, size)
            }
        }
       else if (!cleared)
-       {
-         /* Don't bother clearing storage if the set is all ones.  */
-         if (TREE_CHAIN (elt) != NULL_TREE
-             || (TREE_PURPOSE (elt) == NULL_TREE
-                 ? nbits != 1
-                 : (TREE_CODE (TREE_VALUE (elt)) != INTEGER_CST
-                    || TREE_CODE (TREE_PURPOSE (elt)) != INTEGER_CST
-                    || ((HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (elt))
-                        - (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_PURPOSE (elt)) + 1
-                        != nbits))))
-           clear_storage (target, expr_size (exp),
-                          TYPE_ALIGN (type) / BITS_PER_UNIT);
-       }
+       /* Don't bother clearing storage if the set is all ones.  */
+       if (TREE_CHAIN (elt) != NULL_TREE
+           || (TREE_PURPOSE (elt) == NULL_TREE
+               ? nbits != 1
+               : ( ! host_integerp (TREE_VALUE (elt), 0)
+                  || ! host_integerp (TREE_PURPOSE (elt), 0)
+                  || (tree_low_cst (TREE_VALUE (elt), 0)
+                      - 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))
        {
@@ -4635,10 +4655,10 @@ store_constructor (exp, target, align, cleared, size)
 #ifdef TARGET_MEM_FUNCTIONS
          HOST_WIDE_INT startb, endb;
 #endif
-         rtx  bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
+         rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
 
          bitlength_rtx = expand_expr (bitlength,
-                           NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
+                                      NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
 
          /* handle non-range tuple element like [ expr ]  */
          if (startbit == NULL_TREE)
@@ -4646,6 +4666,7 @@ store_constructor (exp, target, align, cleared, size)
              startbit = save_expr (endbit);
              endbit = startbit;
            }
+
          startbit = convert (sizetype, startbit);
          endbit = convert (sizetype, endbit);
          if (! integer_zerop (domain_min))
@@ -4665,6 +4686,7 @@ store_constructor (exp, target, align, cleared, size)
                                           0);
              emit_move_insn (targetx, target);
            }
+
          else if (GET_CODE (target) == MEM)
            targetx = target;
          else
@@ -4690,13 +4712,12 @@ 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),
-                                startbit_rtx, TYPE_MODE (sizetype),
-                                endbit_rtx, TYPE_MODE (sizetype));
-           }
+           emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
+                              0, VOIDmode, 4, XEXP (targetx, 0), Pmode,
+                              bitlength_rtx, TYPE_MODE (sizetype),
+                              startbit_rtx, TYPE_MODE (sizetype),
+                              endbit_rtx, TYPE_MODE (sizetype));
+
          if (REG_P (target))
            emit_move_insn (target, targetx);
        }
@@ -4718,7 +4739,7 @@ store_constructor (exp, target, align, cleared, size)
    has mode VALUE_MODE if that is convenient to do.
    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
 
-   ALIGN is the alignment that TARGET is known to have, measured in bytes.
+   ALIGN is the alignment that TARGET is known to have.
    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
@@ -4804,10 +4825,10 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
       /* If the field isn't aligned enough to store as an ordinary memref,
         store it as a bit field.  */
       || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
-         && (align * BITS_PER_UNIT < GET_MODE_ALIGNMENT (mode)
+         && (align < GET_MODE_ALIGNMENT (mode)
              || bitpos % GET_MODE_ALIGNMENT (mode)))
       || (mode == BLKmode && SLOW_UNALIGNED_ACCESS (mode, align)
-         && (TYPE_ALIGN (TREE_TYPE (exp)) > align * BITS_PER_UNIT
+         && (TYPE_ALIGN (TREE_TYPE (exp)) > align
              || bitpos % TYPE_ALIGN (TREE_TYPE (exp)) != 0))
       /* If the RHS and field are a constant size and the size of the
         RHS isn't the same size as the bitfield, we must use bitfield
@@ -4841,7 +4862,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
         boundary.  If so, we simply do a block copy.  */
       if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
        {
-         unsigned int exp_align = expr_align (exp) / BITS_PER_UNIT;
+         unsigned int exp_align = expr_align (exp);
 
          if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
              || bitpos % BITS_PER_UNIT != 0)
@@ -4855,7 +4876,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
          align = MIN (exp_align, align);
 
          /* Find an alignment that is consistent with the bit position.  */
-         while ((bitpos % (align * BITS_PER_UNIT)) != 0)
+         while ((bitpos % align) != 0)
            align >>= 1;
 
          emit_block_move (target, temp,
@@ -4933,7 +4954,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
    giving the variable offset (in units) in *POFFSET.
    This offset is in addition to the bit position.
    If the position is not variable, we store 0 in *POFFSET.
-   We set *PALIGNMENT to the alignment in bytes of the address that will be
+   We set *PALIGNMENT to the alignment of the address that will be
    computed.  This is the alignment of the thing we return if *POFFSET
    is zero, but can be more less strictly aligned if *POFFSET is nonzero.
 
@@ -5021,18 +5042,20 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
                   && contains_placeholder_p (this_offset))
            this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
 
-         offset = size_binop (PLUS_EXPR, offset, DECL_FIELD_OFFSET (field));
+         offset = size_binop (PLUS_EXPR, offset, this_offset);
          bit_offset = size_binop (PLUS_EXPR, bit_offset,
                                   DECL_FIELD_BIT_OFFSET (field));
 
          if (! host_integerp (offset, 0))
            alignment = MIN (alignment, DECL_OFFSET_ALIGN (field));
        }
+
       else if (TREE_CODE (exp) == ARRAY_REF)
        {
          tree index = TREE_OPERAND (exp, 1);
          tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
          tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
+         tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
 
          /* We assume all arrays have sizes that are a multiple of a byte.
             First subtract the lower bound, if any, in the type of the
@@ -5042,15 +5065,23 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
            index = fold (build (MINUS_EXPR, TREE_TYPE (index),
                                 index, low_bound));
 
+         /* If the index has a self-referential type, pass it to a
+            WITH_RECORD_EXPR; if the component size is, pass our
+            component to one.  */
          if (! TREE_CONSTANT (index)
              && contains_placeholder_p (index))
            index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
+         if (! TREE_CONSTANT (unit_size)
+             && contains_placeholder_p (unit_size))
+           unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size,
+                              TREE_OPERAND (exp, 0));
 
          offset = size_binop (PLUS_EXPR, offset,
                               size_binop (MULT_EXPR,
                                           convert (sizetype, index),
-                                          TYPE_SIZE_UNIT (TREE_TYPE (exp))));
+                                          unit_size));
        }
+
       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
               && ! ((TREE_CODE (exp) == NOP_EXPR
                      || TREE_CODE (exp) == CONVERT_EXPR)
@@ -5087,7 +5118,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
     *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
 
   *pmode = mode;
-  *palignment = alignment / BITS_PER_UNIT;
+  *palignment = alignment;
   return exp;
 }
 
@@ -5971,8 +6002,7 @@ expand_expr (exp, target, tmode, modifier)
       if (temp != 0)
        {
          if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
-           mark_reg_pointer (XEXP (temp, 0),
-                             DECL_ALIGN (exp) / BITS_PER_UNIT);
+           mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
 
          return temp;
        }
@@ -6324,15 +6354,15 @@ expand_expr (exp, target, tmode, modifier)
                && ((mode == BLKmode
                     && ! (target != 0 && safe_from_p (target, exp, 1)))
                    || TREE_ADDRESSABLE (exp)
-                   || (TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
-                       && TREE_INT_CST_HIGH (TYPE_SIZE_UNIT (type)) == 0
+                   || (host_integerp (TYPE_SIZE_UNIT (type), 1)
                        && (! MOVE_BY_PIECES_P 
-                           (TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type)),
-                            TYPE_ALIGN (type) / BITS_PER_UNIT))
+                           (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);
+
          if (modifier != EXPAND_CONST_ADDRESS
              && modifier != EXPAND_INITIALIZER
              && modifier != EXPAND_SUM
@@ -6674,7 +6704,7 @@ expand_expr (exp, target, tmode, modifier)
                && bitsize != 0
                && (bitpos % bitsize) == 0 
                && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-               && (alignment * BITS_PER_UNIT) == GET_MODE_ALIGNMENT (mode1))
+               && alignment == GET_MODE_ALIGNMENT (mode1))
              {
                rtx temp = change_address (op0, mode1,
                                           plus_constant (XEXP (op0, 0),
@@ -6704,7 +6734,8 @@ expand_expr (exp, target, tmode, modifier)
          }
 
        /* Check the access.  */
-       if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
+       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);
@@ -6748,7 +6779,7 @@ expand_expr (exp, target, tmode, modifier)
                    || (mode1 != BLKmode
                        && SLOW_UNALIGNED_ACCESS (mode1, alignment)
                        && ((TYPE_ALIGN (TREE_TYPE (tem))
-                            < (unsigned int) GET_MODE_ALIGNMENT (mode))
+                            < GET_MODE_ALIGNMENT (mode))
                            || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
                    /* If the type and the field are a constant size and the
                       size of the type isn't the same size as the bitfield,
@@ -6762,7 +6793,7 @@ expand_expr (exp, target, tmode, modifier)
                && modifier != EXPAND_INITIALIZER
                && mode == BLKmode
                && SLOW_UNALIGNED_ACCESS (mode, alignment)
-               && (TYPE_ALIGN (type) > alignment * BITS_PER_UNIT
+               && (TYPE_ALIGN (type) > alignment
                    || bitpos % TYPE_ALIGN (type) != 0)))
          {
            enum machine_mode ext_mode = mode;
@@ -6791,7 +6822,7 @@ expand_expr (exp, target, tmode, modifier)
                emit_block_move (target, op0,
                                 GEN_INT ((bitsize + BITS_PER_UNIT - 1)
                                          / BITS_PER_UNIT),
-                                1);
+                                BITS_PER_UNIT);
                
                return target;
              }
@@ -7060,7 +7091,8 @@ expand_expr (exp, target, tmode, modifier)
                               * BITS_PER_UNIT),
                              GET_MODE_BITSIZE (mode)),
                         0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
-                        VOIDmode, 0, 1, int_size_in_bytes (type), 0);
+                        VOIDmode, 0, BITS_PER_UNIT,
+                        int_size_in_bytes (type), 0);
          else
            abort ();
 
@@ -8276,7 +8308,7 @@ expand_expr (exp, target, tmode, modifier)
 
       if (GET_CODE (op0) == REG
          && ! REG_USERVAR_P (op0))
-       mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)) / BITS_PER_UNIT);
+       mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
 
       /* If we might have had a temp slot, add an equivalent address
         for it.  */
@@ -8698,7 +8730,7 @@ expand_expr_unaligned (exp, palign)
        if (mode1 == VOIDmode
            || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
            || (SLOW_UNALIGNED_ACCESS (mode1, alignment)
-               && (TYPE_ALIGN (type) > alignment * BITS_PER_UNIT
+               && (TYPE_ALIGN (type) > alignment
                    || bitpos % TYPE_ALIGN (type) != 0)))
          {
            enum machine_mode ext_mode = mode_for_size (bitsize, MODE_INT, 1);
@@ -9045,7 +9077,8 @@ preexpand_calls (exp)
       /* Do nothing if already expanded.  */
       if (CALL_EXPR_RTL (exp) != 0
          /* Do nothing if the call returns a variable-sized object.  */
-         || TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST
+         || (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))
@@ -9125,7 +9158,10 @@ clear_pending_stack_adjust ()
       && EXIT_IGNORE_STACK
       && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
       && ! flag_inline_functions)
-    pending_stack_adjust = 0;
+    {
+      stack_pointer_delta -= pending_stack_adjust,
+      pending_stack_adjust = 0;
+    }
 #endif
 }
 
@@ -9339,9 +9375,8 @@ do_jump (exp, if_false_label, if_true_label)
 
        /* Get description of this reference.  We don't actually care
           about the underlying object here.  */
-       get_inner_reference (exp, &bitsize, &bitpos, &offset,
-                            &mode, &unsignedp, &volatilep,
-                            &alignment);
+       get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
+                            &unsignedp, &volatilep, &alignment);
 
        type = type_for_size (bitsize, unsignedp);
        if (! SLOW_BYTE_ACCESS
@@ -10026,7 +10061,7 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
   do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
                           ((mode == BLKmode)
                            ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
-                          MIN (align0, align1) / BITS_PER_UNIT,
+                          MIN (align0, align1),
                           if_false_label, if_true_label);
 }
 \f