OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / function.c
index fe7f61b..fc8be4c 100644 (file)
@@ -61,6 +61,10 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "tm_p.h"
 
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
+
 #ifndef TRAMPOLINE_ALIGNMENT
 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
 #endif
@@ -107,6 +111,11 @@ Boston, MA 02111-1307, USA.  */
    compiler passes. */
 int current_function_is_leaf;
 
+/* Nonzero if function being compiled doesn't contain any instructions
+   that can throw an exception.  This is set prior to final.  */
+
+int current_function_nothrow;
+
 /* Nonzero if function being compiled doesn't modify the stack pointer
    (ignoring the prologue and epilogue).  This is only valid after
    life_analysis has run. */
@@ -147,8 +156,12 @@ struct function *cfun = 0;
 struct function *all_functions = 0;
 
 /* These arrays record the INSN_UIDs of the prologue and epilogue insns.  */
-static int *prologue;
-static int *epilogue;
+static varray_type prologue;
+static varray_type epilogue;
+
+/* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
+   in this function.  */
+static varray_type sibcall_epilogue;
 \f
 /* In order to evaluate some expressions, such as function calls returning
    structures in memory, we need to temporarily allocate stack locations.
@@ -191,7 +204,7 @@ struct temp_slot
      imposed on the memory.  For example, if the stack slot is the
      call frame for an inline functioned, we have no idea what alias
      sets will be assigned to various pieces of the call frame.  */
-  int alias_set;
+  HOST_WIDE_INT alias_set;
   /* The value of `sequence_rtl_expr' when this temporary is allocated.  */
   tree rtl_expr;
   /* Non-zero if this temporary is currently in use.  */
@@ -238,7 +251,8 @@ static rtx assign_stack_temp_for_type PARAMS ((enum machine_mode,
 static struct temp_slot *find_temp_slot_from_address  PARAMS ((rtx));
 static void put_reg_into_stack PARAMS ((struct function *, rtx, tree,
                                         enum machine_mode, enum machine_mode,
-                                        int, int, int, struct hash_table *));
+                                        int, unsigned int, int,
+                                        struct hash_table *));
 static void fixup_var_refs     PARAMS ((rtx, enum machine_mode, int, 
                                         struct hash_table *));
 static struct fixup_replacement
@@ -253,7 +267,7 @@ static rtx fixup_stack_1    PARAMS ((rtx, rtx));
 static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
 static void instantiate_decls  PARAMS ((tree, int));
 static void instantiate_decls_1        PARAMS ((tree, int));
-static void instantiate_decl   PARAMS ((rtx, int, int));
+static void instantiate_decl   PARAMS ((rtx, HOST_WIDE_INT, int));
 static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
 static void delete_handlers    PARAMS ((void));
 static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
@@ -262,19 +276,18 @@ static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
 static void pad_below          PARAMS ((struct args_size *, enum machine_mode,
                                         tree));
 #endif
-#ifdef ARGS_GROW_DOWNWARD
-static tree round_down         PARAMS ((tree, int));
-#endif
 static rtx round_trampoline_addr PARAMS ((rtx));
+static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
+static void reorder_blocks_1   PARAMS ((rtx, tree, varray_type *));
 static tree blocks_nreverse    PARAMS ((tree));
 static int all_blocks          PARAMS ((tree, tree *));
 static tree *get_block_vector   PARAMS ((tree, int *));
 /* We always define `record_insns' even if its not used so that we
    can always export `prologue_epilogue_contains'.  */
-static int *record_insns       PARAMS ((rtx)) ATTRIBUTE_UNUSED;
-static int contains            PARAMS ((rtx, int *));
+static void record_insns       PARAMS ((rtx, varray_type *)) ATTRIBUTE_UNUSED;
+static int contains            PARAMS ((rtx, varray_type));
 #ifdef HAVE_return
-static void emit_return_into_block PARAMS ((basic_block));
+static void emit_return_into_block PARAMS ((basic_block, rtx));
 #endif
 static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *));
 static boolean purge_addressof_1 PARAMS ((rtx *, rtx, int, int, 
@@ -293,7 +306,6 @@ static void mark_function_chain PARAMS ((void *));
 static void prepare_function_start PARAMS ((void));
 static void do_clobber_return_reg PARAMS ((rtx, void *));
 static void do_use_return_reg PARAMS ((rtx, void *));
-static void preserve_rtl_expr_temp PARAMS ((struct temp_slot *));
 \f
 /* Pointer to chain of `struct function' for containing functions.  */
 struct function *outer_function_chain;
@@ -430,6 +442,9 @@ void
 free_after_compilation (f)
      struct function *f;
 {
+  struct temp_slot *ts;
+  struct temp_slot *next;
+
   free_eh_status (f);
   free_expr_status (f);
   free_emit_status (f);
@@ -441,6 +456,13 @@ free_after_compilation (f)
   if (f->x_parm_reg_stack_loc)
     free (f->x_parm_reg_stack_loc);
 
+  for (ts = f->x_temp_slots; ts; ts = next)
+    {
+      next = ts->next;
+      free (ts);
+    }
+  f->x_temp_slots = NULL;
+
   f->arg_offset_rtx = NULL;
   f->return_rtx = NULL;
   f->internal_arg_pointer = NULL;
@@ -461,7 +483,6 @@ free_after_compilation (f)
   f->x_parm_birth_insn = NULL;
   f->x_last_parm_insn = NULL;
   f->x_parm_reg_stack_loc = NULL;
-  f->x_temp_slots = NULL;
   f->fixup_var_refs_queue = NULL;
   f->original_arg_vector = NULL;
   f->original_decl_initial = NULL;
@@ -604,6 +625,7 @@ assign_stack_local_1 (mode, size, align, function)
 
 /* Wrapper around assign_stack_local_1;  assign a local stack slot for the
    current function.  */
+
 rtx
 assign_stack_local (mode, size, align)
      enum machine_mode mode;
@@ -638,7 +660,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
      tree type;
 {
   int align;
-  int alias_set;
+  HOST_WIDE_INT alias_set;
   struct temp_slot *p, *best_p = 0;
 
   /* If SIZE is -1 it means that somebody tried to allocate a temporary
@@ -660,6 +682,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
 
   if (! type)
     type = type_for_mode (mode, 0);
+
   if (type)
     align = LOCAL_ALIGNMENT (type, align);
 
@@ -669,7 +692,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
   for (p = temp_slots; p; p = p->next)
     if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
        && ! p->in_use
-       && (!flag_strict_aliasing
+       && (! flag_strict_aliasing
            || (alias_set && p->alias_set == alias_set))
        && (best_p == 0 || best_p->size > p->size
            || (best_p->size == p->size && best_p->align > p->align)))
@@ -688,18 +711,14 @@ assign_stack_temp_for_type (mode, size, keep, type)
       /* If there are enough aligned bytes left over, make them into a new
         temp_slot so that the extra bytes don't get wasted.  Do this only
         for BLKmode slots, so that we can be sure of the alignment.  */
-      if (GET_MODE (best_p->slot) == BLKmode
-         /* We can't split slots if -fstrict-aliasing because the
-            information about the alias set for the new slot will be
-            lost.  */
-         && !flag_strict_aliasing)
+      if (GET_MODE (best_p->slot) == BLKmode)
        {
          int alignment = best_p->align / BITS_PER_UNIT;
          HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
 
          if (best_p->size - rounded_size >= alignment)
            {
-             p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
+             p = (struct temp_slot *) xmalloc (sizeof (struct temp_slot));
              p->in_use = p->addr_taken = 0;
              p->size = best_p->size - rounded_size;
              p->base_offset = best_p->base_offset + rounded_size;
@@ -710,6 +729,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
              p->align = best_p->align;
              p->address = 0;
              p->rtl_expr = 0;
+             p->alias_set = best_p->alias_set;
              p->next = temp_slots;
              temp_slots = p;
 
@@ -729,7 +749,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
     {
       HOST_WIDE_INT frame_offset_old = frame_offset;
 
-      p = (struct temp_slot *) oballoc (sizeof (struct temp_slot));
+      p = (struct temp_slot *) xmalloc (sizeof (struct temp_slot));
 
       /* We are passing an explicit alignment request to assign_stack_local.
         One side effect of that is assign_stack_local will not round SIZE
@@ -800,7 +820,11 @@ assign_stack_temp_for_type (mode, size, keep, type)
   RTX_UNCHANGING_P (p->slot) = 0;
   MEM_IN_STRUCT_P (p->slot) = 0;
   MEM_SCALAR_P (p->slot) = 0;
-  MEM_ALIAS_SET (p->slot) = 0;
+  MEM_ALIAS_SET (p->slot) = alias_set;
+
+  if (type != 0)
+    MEM_SET_IN_STRUCT_P (p->slot, AGGREGATE_TYPE_P (type));
+
   return p->slot;
 }
 
@@ -851,11 +875,10 @@ assign_temp (type, keep, memory_required, dont_promote)
         instead.  This is the case for Chill variable-sized strings.  */
       if (size == -1 && TREE_CODE (type) == ARRAY_TYPE
          && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE
-         && TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST)
-       size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
+         && host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
+       size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
 
       tmp = assign_stack_temp_for_type (mode, size, keep, type);
-      MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type));
       return tmp;
     }
 
@@ -920,7 +943,10 @@ combine_temp_slots ()
              }
            /* Either delete Q or advance past it.  */
            if (delete_q)
-             prev_q->next = q->next;
+             {
+               prev_q->next = q->next;
+               free (q);
+             }
            else
              prev_q = q;
          }
@@ -1130,36 +1156,6 @@ preserve_temp_slots (x)
       p->level--;
 }
 
-/* Preserve the temporary slot given by P (originally created during
-   the building of an RTL_EXPR) at least as long as things in our
-   current scope.  */
-
-static void
-preserve_rtl_expr_temp (p)
-     struct temp_slot *p;
-{
-  /* Set the slot level to that of the currently prevailing scope.  */
-  p->level = MIN (p->level, temp_slot_level);
-  /* This slot is no longer associated with the RTL_EXPR from which it
-     originated.  */
-  p->rtl_expr = NULL_TREE;
-}
-
-/* Preserve the temporary slots created during the building of the
-   RTL_EXPR given by T at least as long as things in our current
-   scope.  */
-
-void
-preserve_rtl_expr_temps (t)
-     tree t;
-{
-  struct temp_slot *p;
-
-  for (p = temp_slots; p; p = p->next)
-    if (p->in_use && p->rtl_expr == t)
-      preserve_rtl_expr_temp (p);
-}
-
 /* X is the result of an RTL_EXPR.  If it is a temporary slot associated
    with that RTL_EXPR, promote it into a temporary slot at the present
    level so it will not be freed when we free slots made in the
@@ -1179,8 +1175,11 @@ preserve_rtl_expr_result (x)
   /* If we can find a match, move it to our level unless it is already at
      an upper level.  */
   p = find_temp_slot_from_address (XEXP (x, 0));
-  if (p)
-    preserve_rtl_expr_temp (p);
+  if (p != 0)
+    {
+      p->level = MIN (p->level, temp_slot_level);
+      p->rtl_expr = 0;
+    }
 
   return;
 }
@@ -1215,7 +1214,16 @@ free_temps_for_rtl_expr (t)
 
   for (p = temp_slots; p; p = p->next)
     if (p->rtl_expr == t)
-      p->in_use = 0;
+      {
+       /* If this slot is below the current TEMP_SLOT_LEVEL, then it
+          needs to be preserved.  This can happen if a temporary in
+          the RTL_EXPR was addressed; preserve_temp_slots will move
+          the temporary into a higher level.   */
+       if (temp_slot_level <= p->level)
+         p->in_use = 0;
+       else
+         p->rtl_expr = NULL_TREE;
+      }
 
   combine_temp_slots ();
 }
@@ -1324,6 +1332,9 @@ put_var_into_stack (decl)
   struct function *function = 0;
   tree context;
   int can_use_addressof;
+  int volatilep = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
+  int usedp = (TREE_USED (decl)
+              || (TREE_CODE (decl) != SAVE_EXPR && DECL_INITIAL (decl) != 0));
 
   context = decl_function_context (decl);
 
@@ -1351,7 +1362,7 @@ put_var_into_stack (decl)
 
   /* If this is a variable-size object with a pseudo to address it,
      put that pseudo into the stack, if the var is nonlocal.  */
-  if (DECL_NONLOCAL (decl)
+  if (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl)
       && GET_CODE (reg) == MEM
       && GET_CODE (XEXP (reg, 0)) == REG
       && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
@@ -1386,43 +1397,31 @@ put_var_into_stack (decl)
       if (can_use_addressof)
        gen_mem_addressof (reg, decl);
       else
-       put_reg_into_stack (function, reg, TREE_TYPE (decl),
-                           promoted_mode, decl_mode,
-                           TREE_SIDE_EFFECTS (decl), 0,
-                           TREE_USED (decl) || DECL_INITIAL (decl) != 0,
-                           0);
+       put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode,
+                           decl_mode, volatilep, 0, usedp, 0);
     }
   else if (GET_CODE (reg) == CONCAT)
     {
       /* A CONCAT contains two pseudos; put them both in the stack.
         We do it so they end up consecutive.  */
       enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
-      tree part_type = TREE_TYPE (TREE_TYPE (decl));
+      tree part_type = type_for_mode (part_mode, 0);
 #ifdef FRAME_GROWS_DOWNWARD
       /* Since part 0 should have a lower address, do it second.  */
       put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
-                         part_mode, TREE_SIDE_EFFECTS (decl), 0,
-                         TREE_USED (decl) || DECL_INITIAL (decl) != 0,
-                         0);
+                         part_mode, volatilep, 0, usedp, 0);
       put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
-                         part_mode, TREE_SIDE_EFFECTS (decl), 0,
-                         TREE_USED (decl) || DECL_INITIAL (decl) != 0,
-                         0);
+                         part_mode, volatilep, 0, usedp, 0);
 #else
       put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
-                         part_mode, TREE_SIDE_EFFECTS (decl), 0,
-                         TREE_USED (decl) || DECL_INITIAL (decl) != 0,
-                         0);
+                         part_mode, volatilep, 0, usedp, 0);
       put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
-                         part_mode, TREE_SIDE_EFFECTS (decl), 0,
-                         TREE_USED (decl) || DECL_INITIAL (decl) != 0,
-                         0);
+                         part_mode, volatilep, 0, usedp, 0);
 #endif
 
       /* Change the CONCAT into a combined MEM for both parts.  */
       PUT_CODE (reg, MEM);
-      MEM_VOLATILE_P (reg) = MEM_VOLATILE_P (XEXP (reg, 0));
-      MEM_ALIAS_SET (reg) = get_alias_set (decl);
+      set_mem_attributes (reg, decl, 1);
 
       /* The two parts are in memory order already.
         Use the lower parts address as ours.  */
@@ -1458,19 +1457,20 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
      tree type;
      enum machine_mode promoted_mode, decl_mode;
      int volatile_p;
-     int original_regno;
+     unsigned int original_regno;
      int used_p;
      struct hash_table *ht;
 {
   struct function *func = function ? function : cfun;
   rtx new = 0;
-  int regno = original_regno;
+  unsigned int regno = original_regno;
 
   if (regno == 0)
     regno = REGNO (reg);
 
   if (regno < func->x_max_parm_reg)
     new = func->x_parm_reg_stack_loc[regno];
+
   if (new == 0)
     new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
 
@@ -1520,6 +1520,7 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
   rtx first_insn = get_insns ();
   struct sequence_stack *stack = seq_stack;
   tree rtl_exps = rtl_expr_chain;
+  rtx insn;
 
   /* Must scan all insns for stack-refs that exceed the limit.  */
   fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, 
@@ -1554,10 +1555,35 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht)
     }
 
   /* Scan the catch clauses for exception handling too.  */
-  push_to_sequence (catch_clauses);
+  push_to_full_sequence (catch_clauses, catch_clauses_last);
   fixup_var_refs_insns (var, promoted_mode, unsignedp, catch_clauses,
                        0, 0);
-  end_sequence ();
+  end_full_sequence (&catch_clauses, &catch_clauses_last);
+
+  /* Scan sequences saved in CALL_PLACEHOLDERS too.  */
+  for (insn = first_insn; insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == CALL_INSN
+         && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
+       {
+         int i;
+
+         /* Look at the Normal call, sibling call and tail recursion
+            sequences attached to the CALL_PLACEHOLDER.  */
+         for (i = 0; i < 3; i++)
+           {
+             rtx seq = XEXP (PATTERN (insn), i);
+             if (seq)
+               {
+                 push_to_sequence (seq);
+                 fixup_var_refs_insns (var, promoted_mode, unsignedp,
+                                       seq, 0, 0);
+                 XEXP (PATTERN (insn), i) = get_insns ();
+                 end_sequence ();
+               }
+           }
+       }
+    }
 }
 \f
 /* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
@@ -2009,7 +2035,6 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
 
                  newmem = gen_rtx_MEM (wanted_mode,
                                        plus_constant (XEXP (tem, 0), offset));
-                 RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
                  MEM_COPY_ATTRIBUTES (newmem, tem);
 
                  /* Make the change and see if the insn remains valid.  */
@@ -2201,7 +2226,6 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
                    newmem = gen_rtx_MEM (wanted_mode,
                                          plus_constant (XEXP (tem, 0),
                                                         offset));
-                   RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);
                    MEM_COPY_ATTRIBUTES (newmem, tem);
 
                    /* Make the change and see if the insn remains valid.  */
@@ -2717,7 +2741,6 @@ static int cfa_offset;
 
 #ifndef STACK_DYNAMIC_OFFSET
 
-#ifdef ACCUMULATE_OUTGOING_ARGS
 /* The bottom of the stack points to the actual arguments.  If
    REG_PARM_STACK_SPACE is defined, this includes the space for the register
    parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,
@@ -2728,23 +2751,21 @@ static int cfa_offset;
 
 #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
 #define STACK_DYNAMIC_OFFSET(FNDECL)   \
-(current_function_outgoing_args_size   \
- + REG_PARM_STACK_SPACE (FNDECL) + (STACK_POINTER_OFFSET))
+((ACCUMULATE_OUTGOING_ARGS                                                   \
+  ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
+ + (STACK_POINTER_OFFSET))                                                   \
 
 #else
 #define STACK_DYNAMIC_OFFSET(FNDECL)   \
-(current_function_outgoing_args_size + (STACK_POINTER_OFFSET))
-#endif
-
-#else
-#define STACK_DYNAMIC_OFFSET(FNDECL) STACK_POINTER_OFFSET
+((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0)        \
+ + (STACK_POINTER_OFFSET))
 #endif
 #endif
 
-/* On a few machines, the CFA coincides with the arg pointer.  */
+/* On most machines, the CFA coincides with the first incoming parm.  */
 
 #ifndef ARG_POINTER_CFA_OFFSET
-#define ARG_POINTER_CFA_OFFSET 0
+#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
 #endif
 
 
@@ -2782,7 +2803,6 @@ gen_mem_addressof (reg, decl)
 
 /* If DECL has an RTL that is an ADDRESSOF rtx, put it into the stack.  */
 
-#if 0
 void
 flush_addressof (decl)
      tree decl;
@@ -2794,7 +2814,6 @@ flush_addressof (decl)
       && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
     put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
 }
-#endif
 
 /* Force the register pointed to by R, an ADDRESSOF rtx, into the stack.  */
 
@@ -2810,9 +2829,14 @@ put_addressof_into_stack (r, ht)
     abort ();
 
   put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
-                     DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
+                     GET_MODE (reg),
+                     (TREE_CODE (decl) != SAVE_EXPR
+                      && TREE_THIS_VOLATILE (decl)),
                      ADDRESSOF_REGNO (r),
-                     TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht);
+                     (TREE_USED (decl)
+                      || (TREE_CODE (decl) != SAVE_EXPR
+                          && DECL_INITIAL (decl) != 0)),
+                     ht);
 }
 
 /* List of replacements made below in purge_addressof_1 when creating
@@ -2896,7 +2920,6 @@ purge_addressof_1 (loc, insn, force, store, ht)
        {
          sub2 = gen_rtx_MEM (GET_MODE (x), copy_rtx (XEXP (sub, 0)));
          MEM_COPY_ATTRIBUTES (sub2, sub);
-         RTX_UNCHANGING_P (sub2) = RTX_UNCHANGING_P (sub);
          sub = sub2;
        }
       else if (GET_CODE (sub) == REG
@@ -3007,7 +3030,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
                  start_sequence ();
                  store_bit_field (sub, size_x, 0, GET_MODE (x),
                                   val, GET_MODE_SIZE (GET_MODE (sub)),
-                                  GET_MODE_SIZE (GET_MODE (sub)));
+                                  GET_MODE_ALIGNMENT (GET_MODE (sub)));
 
                  /* Make sure to unshare any shared rtl that store_bit_field
                     might have created.  */
@@ -3254,7 +3277,7 @@ purge_addressof (insns)
   /* When we actually purge ADDRESSOFs, we turn REGs into MEMs.  That
      requires a fixup pass over the instruction stream to correct
      INSNs that depended on the REG being a REG, and not a MEM.  But,
-     these fixup passes are slow.  Furthermore, more MEMs are not
+     these fixup passes are slow.  Furthermore, most MEMs are not
      mentioned in very many instructions.  So, we speed up the process
      by pre-calculating which REGs occur in which INSNs; that allows
      us to perform the fixup passes much more quickly.  */
@@ -3298,6 +3321,20 @@ purge_addressof (insns)
   hash_table_free (&ht);
   purge_bitfield_addressof_replacements = 0;
   purge_addressof_replacements = 0;
+
+  /* REGs are shared.  purge_addressof will destructively replace a REG
+     with a MEM, which creates shared MEMs.
+
+     Unfortunately, the children of put_reg_into_stack assume that MEMs
+     referring to the same stack slot are shared (fixup_var_refs and
+     the associated hash table code).
+
+     So, we have to do another unsharing pass after we have flushed any
+     REGs that had their address taken into the stack.
+
+     It may be worth tracking whether or not we converted any REGs into
+     MEMs to avoid this overhead when it is not needed.  */
+  unshare_all_rtl_again (get_insns ());
 }
 \f
 /* Pass through the INSNS of function FNDECL and convert virtual register
@@ -3309,14 +3346,14 @@ instantiate_virtual_regs (fndecl, insns)
      rtx insns;
 {
   rtx insn;
-  int i;
+  unsigned int i;
 
   /* Compute the offsets to use for this function.  */
   in_arg_offset = FIRST_PARM_OFFSET (fndecl);
   var_offset = STARTING_FRAME_OFFSET;
   dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
   out_arg_offset = STACK_POINTER_OFFSET;
-  cfa_offset = ARG_POINTER_CFA_OFFSET;
+  cfa_offset = ARG_POINTER_CFA_OFFSET (fndecl);
 
   /* Scan all variables and parameters of this function.  For each that is
      in memory, instantiate all virtual registers if the result is a valid
@@ -3427,7 +3464,7 @@ instantiate_decls_1 (let, valid_only)
 static void
 instantiate_decl (x, size, valid_only)
      rtx x;
-     int size;
+     HOST_WIDE_INT size;
      int valid_only;
 {
   enum machine_mode mode;
@@ -3457,21 +3494,23 @@ instantiate_decl (x, size, valid_only)
 
   instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
 
-  if (valid_only)
+  if (valid_only && size >= 0)
     {
+      unsigned HOST_WIDE_INT decl_size = size;
+
       /* Now verify that the resulting address is valid for every integer or
         floating-point mode up to and including SIZE bytes long.  We do this
         since the object might be accessed in any mode and frame addresses
         are shared.  */
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-          mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+          mode != VOIDmode && GET_MODE_SIZE (mode) <= decl_size;
           mode = GET_MODE_WIDER_MODE (mode))
        if (! memory_address_p (mode, addr))
          return;
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-          mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+          mode != VOIDmode && GET_MODE_SIZE (mode) <= decl_size;
           mode = GET_MODE_WIDER_MODE (mode))
        if (! memory_address_p (mode, addr))
          return;
@@ -3994,12 +4033,11 @@ aggregate_value_p (exp)
 {
   int i, regno, nregs;
   rtx reg;
-  tree type;
-  if (TREE_CODE_CLASS (TREE_CODE (exp)) == 't')
-    type = exp;
-  else
-    type = TREE_TYPE (exp);
 
+  tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
+
+  if (TREE_CODE (type) == VOID_TYPE)
+    return 0;
   if (RETURN_IN_MEMORY (type))
     return 1;
   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
@@ -4124,7 +4162,6 @@ assign_parms (fndecl)
 
   for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
     {
-      int aggregate = AGGREGATE_TYPE_P (TREE_TYPE (parm));
       struct args_size stack_offset;
       struct args_size arg_size;
       int passed_pointer = 0;
@@ -4177,7 +4214,8 @@ assign_parms (fndecl)
         type of the first field for the tests below.  We have already
         verified that the modes are the same.  */
       if (DECL_TRANSPARENT_UNION (parm)
-         || TYPE_TRANSPARENT_UNION (passed_type))
+         || (TREE_CODE (passed_type) == UNION_TYPE
+             && TYPE_TRANSPARENT_UNION (passed_type)))
        passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
 
       /* See if this arg was passed by invisible reference.  It is if
@@ -4281,12 +4319,7 @@ assign_parms (fndecl)
                                                  internal_arg_pointer,
                                                  offset_rtx));
 
-       /* If this is a memory ref that contains aggregate components,
-          mark it as such for cse and loop optimize.  Likewise if it
-          is readonly.  */
-       MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
-       RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
-       MEM_ALIAS_SET (stack_parm) = get_alias_set (parm);
+       set_mem_attributes (stack_parm, parm, 1);
       }
 
       /* If this parameter was passed both in registers and in the stack,
@@ -4320,8 +4353,8 @@ assign_parms (fndecl)
              if (GET_CODE (entry_parm) == PARALLEL)
                emit_group_store (validize_mem (stack_parm), entry_parm,
                                  int_size_in_bytes (TREE_TYPE (parm)),
-                                 (TYPE_ALIGN (TREE_TYPE (parm))
-                                  / BITS_PER_UNIT));
+                                 TYPE_ALIGN (TREE_TYPE (parm)));
+                                 
              else
                move_block_from_reg (REGNO (entry_parm),
                                     validize_mem (stack_parm), nregs,
@@ -4391,38 +4424,6 @@ assign_parms (fndecl)
          && nominal_mode != BLKmode && nominal_mode != passed_mode)
        stack_parm = 0;
 
-#if 0
-      /* Now adjust STACK_PARM to the mode and precise location
-        where this parameter should live during execution,
-        if we discover that it must live in the stack during execution.
-        To make debuggers happier on big-endian machines, we store
-        the value in the last bytes of the space available.  */
-
-      if (nominal_mode != BLKmode && nominal_mode != passed_mode
-         && stack_parm != 0)
-       {
-         rtx offset_rtx;
-
-         if (BYTES_BIG_ENDIAN
-             && GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
-           stack_offset.constant += (GET_MODE_SIZE (passed_mode)
-                                     - GET_MODE_SIZE (nominal_mode));
-
-         offset_rtx = ARGS_SIZE_RTX (stack_offset);
-         if (offset_rtx == const0_rtx)
-           stack_parm = gen_rtx_MEM (nominal_mode, internal_arg_pointer);
-         else
-           stack_parm = gen_rtx_MEM (nominal_mode,
-                                     gen_rtx_PLUS (Pmode,
-                                                   internal_arg_pointer,
-                                                   offset_rtx));
-
-         /* If this is a memory ref that contains aggregate components,
-            mark it as such for cse and loop optimize.  */
-         MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
-       }
-#endif /* 0 */
-
       /* ENTRY_PARM is an RTX for the parameter as it arrives,
         in the mode in which it arrives.
         STACK_PARM is an RTX for a stack slot where the parameter can live
@@ -4462,25 +4463,18 @@ assign_parms (fndecl)
                  stack_parm
                    = assign_stack_local (GET_MODE (entry_parm),
                                          size_stored, 0);
-
-                 /* If this is a memory ref that contains aggregate
-                    components, mark it as such for cse and loop optimize.  */
-                 MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
+                 set_mem_attributes (stack_parm, parm, 1);
                }
 
              else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
                abort ();
 
-             if (TREE_READONLY (parm))
-               RTX_UNCHANGING_P (stack_parm) = 1;
-
              /* Handle calls that pass values in multiple non-contiguous
                 locations.  The Irix 6 ABI has examples of this.  */
              if (GET_CODE (entry_parm) == PARALLEL)
                emit_group_store (validize_mem (stack_parm), entry_parm,
                                  int_size_in_bytes (TREE_TYPE (parm)),
-                                 (TYPE_ALIGN (TREE_TYPE (parm))
-                                  / BITS_PER_UNIT));
+                                 TYPE_ALIGN (TREE_TYPE (parm)));
              else
                move_block_from_reg (REGNO (entry_parm),
                                     validize_mem (stack_parm),
@@ -4507,7 +4501,7 @@ assign_parms (fndecl)
             may need to do it in a wider mode.  */
 
          register rtx parmreg;
-         int regno, regnoi = 0, regnor = 0;
+         unsigned int regno, regnoi = 0, regnor = 0;
 
          unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
 
@@ -4523,7 +4517,7 @@ assign_parms (fndecl)
            {
              DECL_RTL (parm)
                = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
-             MEM_SET_IN_STRUCT_P (DECL_RTL (parm), aggregate);
+             set_mem_attributes (DECL_RTL (parm), parm, 1);
            }
          else
            DECL_RTL (parm) = parmreg;
@@ -4619,7 +4613,7 @@ assign_parms (fndecl)
 
              push_to_sequence (conversion_insns);
 
-             if (TYPE_SIZE (type) == 0
+             if (!COMPLETE_TYPE_P (type)
                  || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                /* This is a variable sized object.  */
                copy = gen_rtx_MEM (BLKmode,
@@ -4629,8 +4623,7 @@ assign_parms (fndecl)
              else
                copy = assign_stack_temp (TYPE_MODE (type),
                                          int_size_in_bytes (type), 1);
-             MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
-             RTX_UNCHANGING_P (copy) = TREE_READONLY (parm);
+             set_mem_attributes (copy, parm, 1);
 
              store_expr (parm, copy, 0);
              emit_move_insn (parmreg, XEXP (copy, 0));
@@ -4745,8 +4738,8 @@ assign_parms (fndecl)
          /* For pointer data type, suggest pointer register.  */
          if (POINTER_TYPE_P (TREE_TYPE (parm)))
            mark_reg_pointer (parmreg,
-                             (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm)))
-                              / BITS_PER_UNIT));
+                             TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
+
        }
       else
        {
@@ -4781,9 +4774,7 @@ assign_parms (fndecl)
                  stack_parm
                    = assign_stack_local (GET_MODE (entry_parm),
                                          GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
-                 /* If this is a memory ref that contains aggregate components,
-                    mark it as such for cse and loop optimize.  */
-                 MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
+                 set_mem_attributes (stack_parm, parm, 1);
                }
 
              if (promoted_mode != nominal_mode)
@@ -4820,19 +4811,12 @@ assign_parms (fndecl)
       if (parm == function_result_decl)
        {
          tree result = DECL_RESULT (fndecl);
-         tree restype = TREE_TYPE (result);
 
          DECL_RTL (result)
            = gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm));
 
-         MEM_SET_IN_STRUCT_P (DECL_RTL (result), 
-                              AGGREGATE_TYPE_P (restype));
+         set_mem_attributes (DECL_RTL (result), result, 1);
        }
-
-      if (TREE_THIS_VOLATILE (parm))
-       MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
-      if (TREE_READONLY (parm))
-       RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
     }
 
   /* Output all parameter conversion instructions (possibly including calls)
@@ -4901,7 +4885,7 @@ assign_parms (fndecl)
 
 rtx
 promoted_input_arg (regno, pmode, punsignedp)
-     int regno;
+     unsigned int regno;
      enum machine_mode *pmode;
      int *punsignedp;
 {
@@ -5355,7 +5339,9 @@ fix_lexical_addr (addr, var)
       addr = fix_lexical_addr (XEXP (fp->x_arg_pointer_save_area, 0), var);
       addr = memory_address (Pmode, addr);
 
-      base = copy_to_reg (gen_rtx_MEM (Pmode, addr));
+      base = gen_rtx_MEM (Pmode, addr);
+      MEM_ALIAS_SET (base) = get_frame_alias_set ();
+      base = copy_to_reg (base);
 #else
       displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
       base = lookup_static_chain (var);
@@ -5489,11 +5475,6 @@ round_trampoline_addr (tramp)
   return tramp;
 }
 \f
-/* The functions identify_blocks and reorder_blocks provide a way to
-   reorder the tree of BLOCK nodes, for optimizers that reshuffle or
-   duplicate portions of the RTL code.  Call identify_blocks before
-   changing the RTL, and call reorder_blocks after.  */
-
 /* Put all this function's BLOCK nodes including those that are chained
    onto the first block into a vector, and return it.
    Also store in each NOTE for the beginning or end of a block
@@ -5502,16 +5483,12 @@ round_trampoline_addr (tramp)
    and INSNS, the insn chain of the function.  */
 
 void
-identify_blocks (block, insns)
-     tree block;
-     rtx insns;
+identify_blocks ()
 {
   int n_blocks;
-  tree *block_vector;
+  tree *block_vector, *last_block_vector;
   tree *block_stack;
-  int depth = 0;
-  int current_block_number = 1;
-  rtx insn;
+  tree block = DECL_INITIAL (current_function_decl);
 
   if (block == 0)
     return;
@@ -5521,96 +5498,165 @@ identify_blocks (block, insns)
   block_vector = get_block_vector (block, &n_blocks);
   block_stack = (tree *) xmalloc (n_blocks * sizeof (tree));
 
-  for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == NOTE)
-      {
-       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
-         {
-           tree b;
-
-           /* If there are more block notes than BLOCKs, something
-              is badly wrong.  */
-           if (current_block_number == n_blocks)
-             abort ();
-
-           b = block_vector[current_block_number++];
-           NOTE_BLOCK (insn) = b;
-           block_stack[depth++] = b;
-         }
-       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
-         {
-           if (depth == 0)
-             /* There are more NOTE_INSN_BLOCK_ENDs that
-                NOTE_INSN_BLOCK_BEGs.  Something is badly wrong.  */
-             abort ();
+  last_block_vector = identify_blocks_1 (get_insns (), 
+                                        block_vector + 1,
+                                        block_vector + n_blocks, 
+                                        block_stack);
 
-           NOTE_BLOCK (insn) = block_stack[--depth];
-         }
-      }
+  /* If we didn't use all of the subblocks, we've misplaced block notes.  */
+  /* ??? This appears to happen all the time.  Latent bugs elsewhere?  */
+  if (0 && last_block_vector != block_vector + n_blocks)
+    abort ();
 
   free (block_vector);
   free (block_stack);
 }
 
-/* Given a revised instruction chain, rebuild the tree structure of
-   BLOCK nodes to correspond to the new order of RTL.  The new block
-   tree is inserted below TOP_BLOCK.  Returns the current top-level
-   block.  */
+/* Subroutine of identify_blocks.  Do the block substitution on the
+   insn chain beginning with INSNS.  Recurse for CALL_PLACEHOLDER chains.
 
-tree
-reorder_blocks (block, insns)
-     tree block;
+   BLOCK_STACK is pushed and popped for each BLOCK_BEGIN/BLOCK_END pair.
+   BLOCK_VECTOR is incremented for each block seen.  */
+
+static tree *
+identify_blocks_1 (insns, block_vector, end_block_vector, orig_block_stack)
      rtx insns;
+     tree *block_vector;
+     tree *end_block_vector;
+     tree *orig_block_stack;
 {
-  tree current_block = block;
   rtx insn;
+  tree *block_stack = orig_block_stack;
+
+  for (insn = insns; insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == NOTE)
+       {
+         if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+           {
+             tree b;
+
+             /* If there are more block notes than BLOCKs, something
+                is badly wrong.  */
+             if (block_vector == end_block_vector)
+               abort ();
+
+             b = *block_vector++;
+             NOTE_BLOCK (insn) = b;
+             *block_stack++ = b;
+           }
+         else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+           {
+             /* If there are more NOTE_INSN_BLOCK_ENDs than
+                NOTE_INSN_BLOCK_BEGs, something is badly wrong.  */
+             if (block_stack == orig_block_stack)
+               abort ();
+
+             NOTE_BLOCK (insn) = *--block_stack;
+           }
+        }
+      else if (GET_CODE (insn) == CALL_INSN
+              && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
+       {
+         rtx cp = PATTERN (insn);
+
+         block_vector = identify_blocks_1 (XEXP (cp, 0), block_vector, 
+                                           end_block_vector, block_stack);
+         if (XEXP (cp, 1))
+           block_vector = identify_blocks_1 (XEXP (cp, 1), block_vector,
+                                             end_block_vector, block_stack);
+         if (XEXP (cp, 2))
+           block_vector = identify_blocks_1 (XEXP (cp, 2), block_vector,
+                                             end_block_vector, block_stack);
+       }
+    }
+
+  /* If there are more NOTE_INSN_BLOCK_BEGINs than NOTE_INSN_BLOCK_ENDs,
+     something is badly wrong.  */
+  if (block_stack != orig_block_stack)
+    abort ();
+
+  return block_vector;
+}
+
+/* Identify BLOCKs referenced by more than one
+   NOTE_INSN_BLOCK_{BEG,END}, and create duplicate blocks. */
+
+void
+reorder_blocks ()
+{
+  tree block = DECL_INITIAL (current_function_decl);
   varray_type block_stack;
 
   if (block == NULL_TREE)
-    return NULL_TREE;
+    return;
 
   VARRAY_TREE_INIT (block_stack, 10, "block_stack");
 
-  /* Prune the old trees away, so that it doesn't get in the way.  */
-  BLOCK_SUBBLOCKS (current_block) = 0;
-  BLOCK_CHAIN (current_block) = 0;
+  /* Prune the old trees away, so that they don't get in the way.  */
+  BLOCK_SUBBLOCKS (block) = NULL_TREE;
+  BLOCK_CHAIN (block) = NULL_TREE;
 
-  for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == NOTE)
-      {
-       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
-         {
-           tree block = NOTE_BLOCK (insn);
-           /* If we have seen this block before, copy it.  */
-           if (TREE_ASM_WRITTEN (block))
-             {
-               block = copy_node (block);
-               NOTE_BLOCK (insn) = block;
-             }
-           BLOCK_SUBBLOCKS (block) = 0;
-           TREE_ASM_WRITTEN (block) = 1;
-           BLOCK_SUPERCONTEXT (block) = current_block; 
-           BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
-           BLOCK_SUBBLOCKS (current_block) = block;
-           current_block = block;
-           VARRAY_PUSH_TREE (block_stack, block);
-         }
-       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
-         {
-           NOTE_BLOCK (insn) = VARRAY_TOP_TREE (block_stack);
-           VARRAY_POP (block_stack);
-           BLOCK_SUBBLOCKS (current_block)
-             = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
-           current_block = BLOCK_SUPERCONTEXT (current_block);
-         }
-      }
+  reorder_blocks_1 (get_insns (), block, &block_stack);
 
-  BLOCK_SUBBLOCKS (current_block)
-    = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
+  BLOCK_SUBBLOCKS (block)
+    = blocks_nreverse (BLOCK_SUBBLOCKS (block));
 
   VARRAY_FREE (block_stack);
+}
 
-  return current_block;
+/* Helper function for reorder_blocks.  Process the insn chain beginning
+   at INSNS.  Recurse for CALL_PLACEHOLDER insns.  */
+
+static void
+reorder_blocks_1 (insns, current_block, p_block_stack)
+     rtx insns;
+     tree current_block;
+     varray_type *p_block_stack;
+{
+  rtx insn;
+
+  for (insn = insns; insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == NOTE)
+       {
+         if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+           {
+             tree block = NOTE_BLOCK (insn);
+             /* If we have seen this block before, copy it.  */
+             if (TREE_ASM_WRITTEN (block))
+               {
+                 block = copy_node (block);
+                 NOTE_BLOCK (insn) = block;
+               }
+             BLOCK_SUBBLOCKS (block) = 0;
+             TREE_ASM_WRITTEN (block) = 1;
+             BLOCK_SUPERCONTEXT (block) = current_block; 
+             BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
+             BLOCK_SUBBLOCKS (current_block) = block;
+             current_block = block;
+             VARRAY_PUSH_TREE (*p_block_stack, block);
+           }
+         else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+           {
+             NOTE_BLOCK (insn) = VARRAY_TOP_TREE (*p_block_stack);
+             VARRAY_POP (*p_block_stack);
+             BLOCK_SUBBLOCKS (current_block)
+               = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
+             current_block = BLOCK_SUPERCONTEXT (current_block);
+           }
+       }
+      else if (GET_CODE (insn) == CALL_INSN
+              && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
+       {
+         rtx cp = PATTERN (insn);
+         reorder_blocks_1 (XEXP (cp, 0), current_block, p_block_stack);
+         if (XEXP (cp, 1))
+           reorder_blocks_1 (XEXP (cp, 1), current_block, p_block_stack);
+         if (XEXP (cp, 2))
+           reorder_blocks_1 (XEXP (cp, 2), current_block, p_block_stack);
+       }
+    }
 }
 
 /* Reverse the order of elements in the chain T of blocks,
@@ -5765,9 +5811,12 @@ prepare_function_start ()
   cfun->original_decl_initial = 0;
   cfun->original_arg_vector = 0;  
 
-  cfun->stack_alignment_needed = 0;
 #ifdef STACK_BOUNDARY
+  cfun->stack_alignment_needed = STACK_BOUNDARY;
   cfun->preferred_stack_boundary = STACK_BOUNDARY;
+#else
+  cfun->stack_alignment_needed = 0;
+  cfun->preferred_stack_boundary = 0;
 #endif
 
   /* Set if a call to setjmp is seen.  */
@@ -5779,6 +5828,7 @@ prepare_function_start ()
   current_function_calls_alloca = 0;
   current_function_contains_functions = 0;
   current_function_is_leaf = 0;
+  current_function_nothrow = 0;
   current_function_sp_is_unchanging = 0;
   current_function_uses_only_leaf_regs = 0;
   current_function_has_computed_jump = 0;
@@ -5853,7 +5903,7 @@ init_dummy_function_start ()
 void
 init_function_start (subr, filename, line)
      tree subr;
-     char *filename;
+     const char *filename;
      int line;
 {
   prepare_function_start ();
@@ -5910,8 +5960,11 @@ void
 init_function_for_compilation ()
 {
   reg_renumber = 0;
+
   /* No prologue/epilogue insns yet.  */
-  prologue = epilogue = 0;
+  VARRAY_GROW (prologue, 0);
+  VARRAY_GROW (epilogue, 0);
+  VARRAY_GROW (sibcall_epilogue, 0);
 }
 
 /* Indicate that the current function uses extra args
@@ -6039,10 +6092,8 @@ expand_function_start (subr, parms_have_cleanups)
        {
          DECL_RTL (DECL_RESULT (subr))
            = gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address);
-         MEM_SET_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)),
-                              AGGREGATE_TYPE_P (TREE_TYPE
-                                                (DECL_RESULT
-                                                 (subr))));
+         set_mem_attributes (DECL_RTL (DECL_RESULT (subr)),
+                             DECL_RESULT (subr), 1);
        }
     }
   else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
@@ -6069,13 +6120,8 @@ expand_function_start (subr, parms_have_cleanups)
   else
     /* Scalar, returned in a register.  */
     {
-#ifdef FUNCTION_OUTGOING_VALUE
-      DECL_RTL (DECL_RESULT (subr))
-       = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
-#else
       DECL_RTL (DECL_RESULT (subr))
-       = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (subr)), subr);
-#endif
+       = hard_function_value (TREE_TYPE (DECL_RESULT (subr)), subr, 1);
 
       /* Mark this reg as the function's return value.  */
       if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
@@ -6142,9 +6188,9 @@ expand_function_start (subr, parms_have_cleanups)
 #ifdef FRAME_GROWS_DOWNWARD
          last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
 #endif
-         last_ptr = copy_to_reg (gen_rtx_MEM (Pmode,
-                                              memory_address (Pmode,
-                                                              last_ptr)));
+         last_ptr = gen_rtx_MEM (Pmode, memory_address (Pmode, last_ptr));
+         MEM_ALIAS_SET (last_ptr) = get_frame_alias_set ();
+         last_ptr = copy_to_reg (last_ptr);
 
          /* If we are not optimizing, ensure that we know that this
             piece of context is live over the entire function.  */
@@ -6214,14 +6260,25 @@ diddle_return_value (doit, arg)
      void *arg;
 {
   rtx outgoing = current_function_return_rtx;
+  int pcc;
 
   if (! outgoing)
     return;
 
-  if (GET_CODE (outgoing) == REG
-      && REGNO (outgoing) >= FIRST_PSEUDO_REGISTER)
+  pcc = (current_function_returns_struct
+         || current_function_returns_pcc_struct);
+
+  if ((GET_CODE (outgoing) == REG
+       && REGNO (outgoing) >= FIRST_PSEUDO_REGISTER)
+      || pcc)
     {
       tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+
+      /* A PCC-style return returns a pointer to the memory in which
+        the structure is stored.  */
+      if (pcc)
+       type = build_pointer_type (type);
+
 #ifdef FUNCTION_OUTGOING_VALUE
       outgoing = FUNCTION_OUTGOING_VALUE (type, current_function_decl);
 #else
@@ -6232,6 +6289,7 @@ diddle_return_value (doit, arg)
       if (GET_MODE (outgoing) == BLKmode)
        PUT_MODE (outgoing,
                  GET_MODE (DECL_RTL (DECL_RESULT (current_function_decl))));
+      REG_FUNCTION_VALUE_P (outgoing) = 1;
     }
 
   if (GET_CODE (outgoing) == REG)
@@ -6286,7 +6344,7 @@ use_return_register ()
 
 void
 expand_function_end (filename, line, end_bindings)
-     char *filename;
+     const char *filename;
      int line;
      int end_bindings;
 {
@@ -6356,7 +6414,7 @@ expand_function_end (filename, line, end_bindings)
       blktramp = change_address (initial_trampoline, BLKmode, tramp);
       emit_block_move (blktramp, initial_trampoline,
                       GEN_INT (TRAMPOLINE_SIZE),
-                      TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
+                      TRAMPOLINE_ALIGNMENT);
 #endif
       INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
       seq = get_insns ();
@@ -6387,7 +6445,11 @@ expand_function_end (filename, line, end_bindings)
     }
 
   /* Warn about unused parms if extra warnings were specified.  */
-  if (warn_unused && extra_warnings)
+  /* Either ``-W -Wunused'' or ``-Wunused-parameter'' enables this
+     warning.  WARN_UNUSED_PARAMETER is negative when set by
+     -Wunused. */
+  if (warn_unused_parameter > 0
+      || (warn_unused_parameter < 0 && extra_warnings))
     {
       tree decl;
 
@@ -6425,7 +6487,7 @@ expand_function_end (filename, line, end_bindings)
      already exists a copy of this note somewhere above.  This line number
      note is still needed for debugging though, so we can't delete it.  */
   if (flag_test_coverage)
-    emit_note (NULL_PTR, NOTE_REPEATED_LINE_NUMBER);
+    emit_note (NULL_PTR, NOTE_INSN_REPEATED_LINE_NUMBER);
 
   /* Output a linenumber for the end of the function.
      SDB depends on this.  */
@@ -6463,7 +6525,7 @@ expand_function_end (filename, line, end_bindings)
 
     /* If there are any catch_clauses remaining, output them now.  */
     emit_insns (catch_clauses);
-    catch_clauses = NULL_RTX;
+    catch_clauses = catch_clauses_last = NULL_RTX;
     /* If the above emitted any code, may sure we jump around it.  */
     if (last != get_last_insn ())
       {
@@ -6596,30 +6658,32 @@ expand_function_end (filename, line, end_bindings)
   expand_fixups (get_insns ());
 }
 \f
-/* Create an array that records the INSN_UIDs of INSNS (either a sequence
-   or a single insn).  */
+/* Extend a vector that records the INSN_UIDs of INSNS (either a
+   sequence or a single insn).  */
 
-static int *
-record_insns (insns)
+static void
+record_insns (insns, vecp)
      rtx insns;
+     varray_type *vecp;
 {
-  int *vec;
-
   if (GET_CODE (insns) == SEQUENCE)
     {
       int len = XVECLEN (insns, 0);
-      vec = (int *) oballoc ((len + 1) * sizeof (int));
-      vec[len] = 0;
+      int i = VARRAY_SIZE (*vecp);
+
+      VARRAY_GROW (*vecp, i + len);
       while (--len >= 0)
-       vec[len] = INSN_UID (XVECEXP (insns, 0, len));
+       {
+         VARRAY_INT (*vecp, i) = INSN_UID (XVECEXP (insns, 0, len));
+         ++i;
+       }
     }
   else
     {
-      vec = (int *) oballoc (2 * sizeof (int));
-      vec[0] = INSN_UID (insns);
-      vec[1] = 0;
+      int i = VARRAY_SIZE (*vecp);
+      VARRAY_GROW (*vecp, i + 1);
+      VARRAY_INT (*vecp, i) = INSN_UID (insns);
     }
-  return vec;
 }
 
 /* Determine how many INSN_UIDs in VEC are part of INSN.  */
@@ -6627,7 +6691,7 @@ record_insns (insns)
 static int
 contains (insn, vec)
      rtx insn;
-     int *vec;
+     varray_type vec;
 {
   register int i, j;
 
@@ -6636,15 +6700,15 @@ contains (insn, vec)
     {
       int count = 0;
       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
-       for (j = 0; vec[j]; j++)
-         if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j])
+       for (j = VARRAY_SIZE (vec) - 1; j >= 0; --j)
+         if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == VARRAY_INT (vec, j))
            count++;
       return count;
     }
   else
     {
-      for (j = 0; vec[j]; j++)
-       if (INSN_UID (insn) == vec[j])
+      for (j = VARRAY_SIZE (vec) - 1; j >= 0; --j)
+       if (INSN_UID (insn) == VARRAY_INT (vec, j))
          return 1;
     }
   return 0;
@@ -6654,31 +6718,45 @@ int
 prologue_epilogue_contains (insn)
      rtx insn;
 {
-  if (prologue && contains (insn, prologue))
+  if (contains (insn, prologue))
     return 1;
-  if (epilogue && contains (insn, epilogue))
+  if (contains (insn, epilogue))
     return 1;
   return 0;
 }
 
+int
+sibcall_epilogue_contains (insn)
+      rtx insn;
+{
+  if (sibcall_epilogue)
+    return contains (insn, sibcall_epilogue);
+  return 0;
+}
+
 #ifdef HAVE_return
 /* Insert gen_return at the end of block BB.  This also means updating
    block_for_insn appropriately.  */
 
 static void
-emit_return_into_block (bb)
+emit_return_into_block (bb, line_note)
      basic_block bb;
+     rtx line_note;
 {
   rtx p, end;
 
-  end = emit_jump_insn_after (gen_return (), bb->end);
   p = NEXT_INSN (bb->end); 
+  end = emit_jump_insn_after (gen_return (), bb->end);
+  if (line_note)
+    emit_line_note_after (NOTE_SOURCE_FILE (line_note),
+                         NOTE_LINE_NUMBER (line_note), bb->end);
+
   while (1)
     {
       set_block_for_insn (p, bb);
-      if (p == end)
+      if (p == bb->end)
        break;
-      p = NEXT_INSN (p);
+      p = PREV_INSN (p);
     }
   bb->end = end;
 }
@@ -6692,15 +6770,19 @@ void
 thread_prologue_and_epilogue_insns (f)
      rtx f ATTRIBUTE_UNUSED;
 {
-  int insertted = 0;
+  int inserted = 0;
   edge e;
   rtx seq;
+#ifdef HAVE_prologue
+  rtx prologue_end = NULL_RTX;
+#endif
+#if defined (HAVE_epilogue) || defined(HAVE_return)
+  rtx epilogue_end = NULL_RTX;
+#endif
 
 #ifdef HAVE_prologue
   if (HAVE_prologue)
     {
-      rtx insn;
-
       start_sequence ();
       seq = gen_prologue();
       emit_insn (seq);
@@ -6708,27 +6790,8 @@ thread_prologue_and_epilogue_insns (f)
       /* Retain a map of the prologue insns.  */
       if (GET_CODE (seq) != SEQUENCE)
        seq = get_insns ();
-      prologue = record_insns (seq);
-      emit_note (NULL, NOTE_INSN_PROLOGUE_END);
-
-      /* GDB handles `break f' by setting a breakpoint on the first
-        line note *after* the prologue.  That means that we should
-        insert a line note here; otherwise, if the next line note
-        comes part way into the next block, GDB will skip all the way
-        to that point.  */
-      insn = next_nonnote_insn (f);
-      while (insn)
-       {
-         if (GET_CODE (insn) == NOTE 
-             && NOTE_LINE_NUMBER (insn) >= 0)
-           {
-             emit_line_note_force (NOTE_SOURCE_FILE (insn),
-                                   NOTE_LINE_NUMBER (insn));
-             break;
-           }
-
-         insn = PREV_INSN (insn);
-       }
+      record_insns (seq, &prologue);
+      prologue_end = emit_note (NULL, NOTE_INSN_PROLOGUE_END);
 
       seq = gen_sequence ();
       end_sequence ();
@@ -6742,7 +6805,7 @@ thread_prologue_and_epilogue_insns (f)
            abort ();
 
          insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
-         insertted = 1;
+         inserted = 1;
        }
       else
        emit_insn_after (seq, f);
@@ -6788,6 +6851,19 @@ thread_prologue_and_epilogue_insns (f)
 
       if (last->head == label && GET_CODE (label) == CODE_LABEL)
        {
+          rtx epilogue_line_note = NULL_RTX;
+
+         /* Locate the line number associated with the closing brace,
+            if we can find one.  */
+         for (seq = get_last_insn ();
+              seq && ! active_insn_p (seq);
+              seq = PREV_INSN (seq))
+           if (GET_CODE (seq) == NOTE && NOTE_LINE_NUMBER (seq) > 0)
+             {
+               epilogue_line_note = seq;
+               break;
+             }
+
          for (e = last->pred; e ; e = e_next)
            {
              basic_block bb = e->src;
@@ -6805,7 +6881,7 @@ thread_prologue_and_epilogue_insns (f)
                 with a simple return instruction.  */
              if (simplejump_p (jump))
                {
-                 emit_return_into_block (bb);
+                 emit_return_into_block (bb, epilogue_line_note);
                  flow_delete_insn (jump);
                }
 
@@ -6837,29 +6913,17 @@ thread_prologue_and_epilogue_insns (f)
                continue;
 
              /* Fix up the CFG for the successful change we just made.  */
-             remove_edge (e);
-             make_edge (NULL, bb, EXIT_BLOCK_PTR, 0);
+             redirect_edge_succ (e, EXIT_BLOCK_PTR);
            }
 
          /* Emit a return insn for the exit fallthru block.  Whether
             this is still reachable will be determined later.  */
 
          emit_barrier_after (last->end);
-         emit_return_into_block (last);
+         emit_return_into_block (last, epilogue_line_note);
+         epilogue_end = last->end;
+          goto epilogue_done;
        }
-      else 
-       {
-         /* The exit block wasn't empty.  We have to use insert_insn_on_edge,
-            as it may be the exit block can go elsewhere as well
-            as exiting.  */
-         start_sequence ();
-         emit_jump_insn (gen_return ());
-         seq = gen_sequence ();
-         end_sequence ();
-         insert_insn_on_edge (seq, e);
-         insertted = 1;
-       }
-      goto epilogue_done;
     }
 #endif
 #ifdef HAVE_epilogue
@@ -6877,7 +6941,7 @@ thread_prologue_and_epilogue_insns (f)
        goto epilogue_done;
 
       start_sequence ();
-      emit_note (NULL, NOTE_INSN_EPILOGUE_BEG);
+      epilogue_end = emit_note (NULL, NOTE_INSN_EPILOGUE_BEG);
 
       seq = gen_epilogue ();
       emit_jump_insn (seq);
@@ -6885,19 +6949,117 @@ thread_prologue_and_epilogue_insns (f)
       /* Retain a map of the epilogue insns.  */
       if (GET_CODE (seq) != SEQUENCE)
        seq = get_insns ();
-      epilogue = record_insns (seq);
+      record_insns (seq, &epilogue);
 
       seq = gen_sequence ();
       end_sequence();
 
       insert_insn_on_edge (seq, e);
-      insertted = 1;
+      inserted = 1;
     }
 #endif
 epilogue_done:
 
-  if (insertted)
+  if (inserted)
     commit_edge_insertions ();
+
+#ifdef HAVE_sibcall_epilogue
+  /* Emit sibling epilogues before any sibling call sites.  */
+  for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+    {
+      basic_block bb = e->src;
+      rtx insn = bb->end;
+      rtx i;
+      rtx newinsn;
+
+      if (GET_CODE (insn) != CALL_INSN
+         || ! SIBLING_CALL_P (insn))
+       continue;
+
+      start_sequence ();
+      seq = gen_sibcall_epilogue ();
+      end_sequence ();
+
+      i = PREV_INSN (insn);
+      newinsn = emit_insn_before (seq, insn);
+
+      /* Update the UID to basic block map.  */
+      for (i = NEXT_INSN (i); i != insn; i = NEXT_INSN (i))
+       set_block_for_insn (i, bb);
+
+      /* Retain a map of the epilogue insns.  Used in life analysis to
+        avoid getting rid of sibcall epilogue insns.  */
+      record_insns (GET_CODE (seq) == SEQUENCE
+                   ? seq : newinsn, &sibcall_epilogue);
+    }
+#endif
+
+#ifdef HAVE_prologue
+  if (prologue_end)
+    {
+      rtx insn, prev;
+
+      /* GDB handles `break f' by setting a breakpoint on the first
+        line note after the prologue.  Which means (1) that if
+        there are line number notes before where we inserted the
+        prologue we should move them, and (2) we should generate a
+        note before the end of the first basic block, if there isn't
+        one already there.  */
+
+      for (insn = prologue_end; insn ; insn = prev)
+       {
+         prev = PREV_INSN (insn);
+         if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+           {
+             /* Note that we cannot reorder the first insn in the
+                chain, since rest_of_compilation relies on that
+                remaining constant.  */
+             if (prev == NULL)
+               break;
+             reorder_insns (insn, insn, prologue_end);
+           }
+       }
+
+      /* Find the last line number note in the first block.  */
+      for (insn = BASIC_BLOCK (0)->end;
+          insn != prologue_end;
+          insn = PREV_INSN (insn))
+       if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+         break;
+
+      /* If we didn't find one, make a copy of the first line number
+        we run across.  */
+      if (! insn)
+       {
+         for (insn = next_active_insn (prologue_end);
+              insn;
+              insn = PREV_INSN (insn))
+           if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+             {
+               emit_line_note_after (NOTE_SOURCE_FILE (insn),
+                                     NOTE_LINE_NUMBER (insn),
+                                     prologue_end);
+               break;
+             }
+       }
+    }
+#endif
+#ifdef HAVE_epilogue
+  if (epilogue_end)
+    {
+      rtx insn, next;
+
+      /* Similarly, move any line notes that appear after the epilogue.
+         There is no need, however, to be quite so anal about the existance
+        of such a note.  */
+      for (insn = epilogue_end; insn ; insn = next)
+       {
+         next = NEXT_INSN (insn);
+         if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
+           reorder_insns (insn, insn, PREV_INSN (epilogue_end));
+       }
+    }
+#endif
 }
 
 /* Reposition the prologue-end and epilogue-begin notes after instruction
@@ -6908,90 +7070,82 @@ reposition_prologue_and_epilogue_notes (f)
      rtx f ATTRIBUTE_UNUSED;
 {
 #if defined (HAVE_prologue) || defined (HAVE_epilogue)
-  /* Reposition the prologue and epilogue notes.  */
-  if (n_basic_blocks)
+  int len;
+
+  if ((len = VARRAY_SIZE (prologue)) > 0)
     {
-      int len;
+      register rtx insn, note = 0;
 
-      if (prologue)
+      /* Scan from the beginning until we reach the last prologue insn.
+        We apparently can't depend on basic_block_{head,end} after
+        reorg has run.  */
+      for (insn = f; len && insn; insn = NEXT_INSN (insn))
        {
-         register rtx insn, note = 0;
-
-         /* Scan from the beginning until we reach the last prologue insn.
-            We apparently can't depend on basic_block_{head,end} after
-            reorg has run.  */
-         for (len = 0; prologue[len]; len++)
-           ;
-         for (insn = f; len && insn; insn = NEXT_INSN (insn))
+         if (GET_CODE (insn) == NOTE)
            {
-             if (GET_CODE (insn) == NOTE)
+             if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
+               note = insn;
+           }
+         else if ((len -= contains (insn, prologue)) == 0)
+           {
+             rtx next;
+             /* Find the prologue-end note if we haven't already, and
+                move it to just after the last prologue insn.  */
+             if (note == 0)
                {
-                 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
-                   note = insn;
+                 for (note = insn; (note = NEXT_INSN (note));)
+                   if (GET_CODE (note) == NOTE
+                       && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
+                     break;
                }
-             else if ((len -= contains (insn, prologue)) == 0)
-               {
-                 rtx next;
-                 /* Find the prologue-end note if we haven't already, and
-                    move it to just after the last prologue insn.  */
-                 if (note == 0)
-                   {
-                     for (note = insn; (note = NEXT_INSN (note));)
-                       if (GET_CODE (note) == NOTE
-                           && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
-                         break;
-                   }
 
-                 next = NEXT_INSN (note);
+             next = NEXT_INSN (note);
 
-                 /* Whether or not we can depend on BLOCK_HEAD, 
-                    attempt to keep it up-to-date.  */
-                 if (BLOCK_HEAD (0) == note)
-                   BLOCK_HEAD (0) = next;
+             /* Whether or not we can depend on BLOCK_HEAD, 
+                attempt to keep it up-to-date.  */
+             if (BLOCK_HEAD (0) == note)
+               BLOCK_HEAD (0) = next;
 
-                 remove_insn (note);
-                 add_insn_after (note, insn);
-               }
+             remove_insn (note);
+             add_insn_after (note, insn);
            }
        }
+    }
+
+  if ((len = VARRAY_SIZE (epilogue)) > 0)
+    {
+      register rtx insn, note = 0;
 
-      if (epilogue)
+      /* Scan from the end until we reach the first epilogue insn.
+        We apparently can't depend on basic_block_{head,end} after
+        reorg has run.  */
+      for (insn = get_last_insn (); len && insn; insn = PREV_INSN (insn))
        {
-         register rtx insn, note = 0;
-
-         /* Scan from the end until we reach the first epilogue insn.
-            We apparently can't depend on basic_block_{head,end} after
-            reorg has run.  */
-         for (len = 0; epilogue[len]; len++)
-           ;
-         for (insn = get_last_insn (); len && insn; insn = PREV_INSN (insn))
+         if (GET_CODE (insn) == NOTE)
+           {
+             if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
+               note = insn;
+           }
+         else if ((len -= contains (insn, epilogue)) == 0)
            {
-             if (GET_CODE (insn) == NOTE)
+             /* Find the epilogue-begin note if we haven't already, and
+                move it to just before the first epilogue insn.  */
+             if (note == 0)
                {
-                 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
-                   note = insn;
+                 for (note = insn; (note = PREV_INSN (note));)
+                   if (GET_CODE (note) == NOTE
+                       && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
+                     break;
                }
-             else if ((len -= contains (insn, epilogue)) == 0)
-               {
-                 /* Find the epilogue-begin note if we haven't already, and
-                    move it to just before the first epilogue insn.  */
-                 if (note == 0)
-                   {
-                     for (note = insn; (note = PREV_INSN (note));)
-                       if (GET_CODE (note) == NOTE
-                           && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
-                         break;
-                   }
 
-                 /* Whether or not we can depend on BLOCK_HEAD, 
-                    attempt to keep it up-to-date.  */
-                 if (n_basic_blocks
-                     && BLOCK_HEAD (n_basic_blocks-1) == insn)
-                   BLOCK_HEAD (n_basic_blocks-1) = note;
+             /* Whether or not we can depend on BLOCK_HEAD, 
+                attempt to keep it up-to-date.  */
+             if (n_basic_blocks
+                 && BLOCK_HEAD (n_basic_blocks-1) == insn)
+               BLOCK_HEAD (n_basic_blocks-1) = note;
 
-                 remove_insn (note);
-                 add_insn_before (note, insn);
-               }
+             remove_insn (note);
+             add_insn_before (note, insn);
            }
        }
     }
@@ -7105,4 +7259,8 @@ init_function_once ()
 {
   ggc_add_root (&all_functions, 1, sizeof all_functions,
                mark_function_chain);
+
+  VARRAY_INT_INIT (prologue, 0, "prologue");
+  VARRAY_INT_INIT (epilogue, 0, "epilogue");
+  VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue");
 }