OSDN Git Service

2003-03-10 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
[pf3gnuchains/gcc-fork.git] / gcc / calls.c
index e911dda..cab6571 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "sbitmap.h"
 #include "langhooks.h"
 #include "target.h"
+#include "cgraph.h"
 
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
@@ -197,6 +198,7 @@ static int check_sibcall_argument_overlap   PARAMS ((rtx, struct arg_data *,
 
 static int combine_pending_stack_adjustment_and_call
                                                 PARAMS ((int, struct args_size *, int));
+static tree fix_unsafe_tree            PARAMS ((tree));
 
 #ifdef REG_PARM_STACK_SPACE
 static rtx save_fixed_argument_area    PARAMS ((int, rtx, int *, int *));
@@ -797,8 +799,14 @@ flags_from_decl_or_type (exp)
   /* ??? We can't set IS_MALLOC for function types?  */
   if (DECL_P (exp))
     {
+      struct cgraph_rtl_info *i = cgraph_rtl_info (exp);
       type = TREE_TYPE (exp);
 
+      if (i && i->pure_function)
+       flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
+      if (i && i->const_function)
+       flags |= ECF_CONST | ECF_LIBCALL_BLOCK;
+
       /* The function exp may have the `malloc' attribute.  */
       if (DECL_P (exp) && DECL_IS_MALLOC (exp))
        flags |= ECF_MALLOC;
@@ -911,66 +919,68 @@ save_fixed_argument_area (reg_parm_stack_space, argblock,
      int *low_to_save;
      int *high_to_save;
 {
-  int i;
-  rtx save_area = NULL_RTX;
+  int low;
+  int high;
 
-  /* Compute the boundary of the that needs to be saved, if any.  */
+  /* Compute the boundary of the area that needs to be saved, if any.  */
+  high = reg_parm_stack_space;
 #ifdef ARGS_GROW_DOWNWARD
-  for (i = 0; i < reg_parm_stack_space + 1; i++)
-#else
-  for (i = 0; i < reg_parm_stack_space; i++)
+  high += 1;
 #endif
-    {
-      if (i >= highest_outgoing_arg_in_use
-         || stack_usage_map[i] == 0)
-       continue;
+  if (high > highest_outgoing_arg_in_use)
+    high = highest_outgoing_arg_in_use;
 
-      if (*low_to_save == -1)
-       *low_to_save = i;
+  for (low = 0; low < high; low++)
+    if (stack_usage_map[low] != 0)
+      {
+       int num_to_save;
+       enum machine_mode save_mode;
+       int delta;
+       rtx stack_area;
+       rtx save_area;
 
-      *high_to_save = i;
-    }
+       while (stack_usage_map[--high] == 0)
+         ;
 
-  if (*low_to_save >= 0)
-    {
-      int num_to_save = *high_to_save - *low_to_save + 1;
-      enum machine_mode save_mode
-       = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-      rtx stack_area;
+       *low_to_save = low;
+       *high_to_save = high;
+
+       num_to_save = high - low + 1;
+       save_mode = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
 
-      /* If we don't have the required alignment, must do this in BLKmode.  */
-      if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
-                               BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
-       save_mode = BLKmode;
+       /* If we don't have the required alignment, must do this
+          in BLKmode.  */
+       if ((low & (MIN (GET_MODE_SIZE (save_mode),
+                        BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
+         save_mode = BLKmode;
 
 #ifdef ARGS_GROW_DOWNWARD
-      stack_area
-       = gen_rtx_MEM (save_mode,
-                      memory_address (save_mode,
-                                      plus_constant (argblock,
-                                                     - *high_to_save)));
+       delta = -high;
 #else
-      stack_area = gen_rtx_MEM (save_mode,
-                               memory_address (save_mode,
-                                               plus_constant (argblock,
-                                                              *low_to_save)));
+       delta = low;
 #endif
+       stack_area = gen_rtx_MEM (save_mode,
+                                 memory_address (save_mode,
+                                                 plus_constant (argblock,
+                                                                delta)));
 
-      set_mem_align (stack_area, PARM_BOUNDARY);
-      if (save_mode == BLKmode)
-       {
-         save_area = assign_stack_temp (BLKmode, num_to_save, 0);
-         emit_block_move (validize_mem (save_area), stack_area,
-                          GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
-       }
-      else
-       {
-         save_area = gen_reg_rtx (save_mode);
-         emit_move_insn (save_area, stack_area);
-       }
-    }
+       set_mem_align (stack_area, PARM_BOUNDARY);
+       if (save_mode == BLKmode)
+         {
+           save_area = assign_stack_temp (BLKmode, num_to_save, 0);
+           emit_block_move (validize_mem (save_area), stack_area,
+                            GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
+         }
+       else
+         {
+           save_area = gen_reg_rtx (save_mode);
+           emit_move_insn (save_area, stack_area);
+         }
+
+       return save_area;
+      }
 
-  return save_area;
+  return NULL_RTX;
 }
 
 static void
@@ -981,19 +991,18 @@ restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
      int low_to_save;
 {
   enum machine_mode save_mode = GET_MODE (save_area);
+  int delta;
+  rtx stack_area;
+
 #ifdef ARGS_GROW_DOWNWARD
-  rtx stack_area
-    = gen_rtx_MEM (save_mode,
-                  memory_address (save_mode,
-                                  plus_constant (argblock,
-                                                 - high_to_save)));
+  delta = -high_to_save;
 #else
-  rtx stack_area
-    = gen_rtx_MEM (save_mode,
-                  memory_address (save_mode,
-                                  plus_constant (argblock,
-                                                 low_to_save)));
+  delta = low_to_save;
 #endif
+  stack_area = gen_rtx_MEM (save_mode,
+                           memory_address (save_mode,
+                                           plus_constant (argblock, delta)));
+  set_mem_align (stack_area, PARM_BOUNDARY);
 
   if (save_mode != BLKmode)
     emit_move_insn (stack_area, save_area);
@@ -1632,6 +1641,7 @@ compute_argument_addresses (args, argblock, num_actuals)
 
          addr = plus_constant (addr, arg_offset);
          args[i].stack = gen_rtx_MEM (args[i].mode, addr);
+         set_mem_align (args[i].stack, PARM_BOUNDARY);
          set_mem_attributes (args[i].stack,
                              TREE_TYPE (args[i].tree_value), 1);
 
@@ -1642,6 +1652,7 @@ compute_argument_addresses (args, argblock, num_actuals)
 
          addr = plus_constant (addr, arg_offset);
          args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
+         set_mem_align (args[i].stack_slot, PARM_BOUNDARY);
          set_mem_attributes (args[i].stack_slot,
                              TREE_TYPE (args[i].tree_value), 1);
 
@@ -1661,12 +1672,12 @@ compute_argument_addresses (args, argblock, num_actuals)
    FNDECL is the tree node for the target function.  For an indirect call
    FNDECL will be NULL_TREE.
 
-   EXP is the CALL_EXPR for this call.  */
+   ADDR is the operand 0 of CALL_EXPR for this call.  */
 
 static rtx
-rtx_for_function_call (fndecl, exp)
+rtx_for_function_call (fndecl, addr)
      tree fndecl;
-     tree exp;
+     tree addr;
 {
   rtx funexp;
 
@@ -1688,7 +1699,7 @@ rtx_for_function_call (fndecl, exp)
     /* Generate an rtx (probably a pseudo-register) for the address.  */
     {
       push_temp_slots ();
-      funexp = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+      funexp = expand_expr (addr, NULL_RTX, VOIDmode, 0);
       pop_temp_slots ();       /* FUNEXP can't be BLKmode.  */
       emit_queue ();
     }
@@ -1832,9 +1843,11 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
             the stack before executing the inlined function if it
             makes any calls.  */
 
-         for (i = reg_parm_stack_space - 1; i >= 0; i--)
-           if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0)
-             break;
+         i = reg_parm_stack_space;
+         if (i > highest_outgoing_arg_in_use)
+           i = highest_outgoing_arg_in_use;
+         while (--i >= 0 && stack_usage_map[i] == 0)
+           ;
 
          if (stack_arg_under_construction || i >= 0)
            {
@@ -2193,8 +2206,8 @@ expand_call (exp, target, ignore)
   int is_integrable = 0;
 #ifdef REG_PARM_STACK_SPACE
   /* Define the boundary of the register parm stack space that needs to be
-     save, if any.  */
-  int low_to_save = -1, high_to_save;
+     saved, if any.  */
+  int low_to_save, high_to_save;
   rtx save_area = 0;           /* Place that it is saved */
 #endif
 
@@ -2208,6 +2221,7 @@ expand_call (exp, target, ignore)
   int old_stack_allocated;
   rtx call_fusage;
   tree p = TREE_OPERAND (exp, 0);
+  tree addr = TREE_OPERAND (exp, 0);
   int i;
   /* The alignment of the stack, in bits.  */
   HOST_WIDE_INT preferred_stack_boundary;
@@ -2337,9 +2351,15 @@ expand_call (exp, target, ignore)
 
   /* Figure out the amount to which the stack should be aligned.  */
   preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
+  if (fndecl)
+    {
+      struct cgraph_rtl_info *i = cgraph_rtl_info (fndecl);
+      if (i && i->preferred_incoming_stack_boundary)
+       preferred_stack_boundary = i->preferred_incoming_stack_boundary;
+    }
 
   /* Operand 0 is a pointer-to-function; get the type of the function.  */
-  funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
+  funtype = TREE_TYPE (addr);
   if (! POINTER_TYPE_P (funtype))
     abort ();
   funtype = TREE_TYPE (funtype);
@@ -2414,7 +2434,7 @@ expand_call (exp, target, ignore)
      calling convention than normal calls.  The last argument in
      INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call
      or not.  */
-  INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0));
+  INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, fndecl);
 
   /* Make a vector to hold all the information about each arg.  */
   args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
@@ -2476,8 +2496,8 @@ expand_call (exp, target, ignore)
 
   /* Tail recursion fails, when we are not dealing with recursive calls.  */
   if (!try_tail_recursion
-      || TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
-      || TREE_OPERAND (TREE_OPERAND (exp, 0), 0) != current_function_decl)
+      || TREE_CODE (addr) != ADDR_EXPR
+      || TREE_OPERAND (addr, 0) != current_function_decl)
     try_tail_recursion = 0;
 
   /*  Rest of purposes for tail call optimizations to fail.  */
@@ -2499,7 +2519,7 @@ expand_call (exp, target, ignore)
       /* Functions that do not return exactly once may not be sibcall
          optimized.  */
       || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP | ECF_NORETURN))
-      || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
+      || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
       /* If this function requires more stack slots than the current
         function, we cannot change it into a sibling call.  */
       || args_size.constant > current_function_args_size
@@ -2552,9 +2572,9 @@ expand_call (exp, target, ignore)
          if (try_tail_recursion)
            actparms = tree_cons (NULL_TREE, args[i].tree_value, actparms);
        }
-      /* Do the same for the function address if it is an expression. */
+      /* Do the same for the function address if it is an expression.  */
       if (!fndecl)
-        TREE_OPERAND (exp, 0) = fix_unsafe_tree (TREE_OPERAND (exp, 0));
+        addr = fix_unsafe_tree (addr);
       /* Expanding one of those dangerous arguments could have added
         cleanups, but otherwise give it a whirl.  */
       if (any_pending_cleanups (1))
@@ -2623,6 +2643,8 @@ expand_call (exp, target, ignore)
   if (cfun->preferred_stack_boundary < preferred_stack_boundary
       && fndecl != current_function_decl)
     cfun->preferred_stack_boundary = preferred_stack_boundary;
+  if (fndecl == current_function_decl)
+    cfun->recursive_call_emit = true;
 
   preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
 
@@ -2631,7 +2653,7 @@ expand_call (exp, target, ignore)
   /* We want to make two insn chains; one for a sibling call, the other
      for a normal call.  We will select one of the two chains after
      initial RTL generation is complete.  */
-  for (pass = 0; pass < 2; pass++)
+  for (pass = try_tail_call ? 0 : 1; pass < 2; pass++)
     {
       int sibcall_failure = 0;
       /* We want to emit any pending stack adjustments before the tail
@@ -2645,9 +2667,6 @@ expand_call (exp, target, ignore)
 
       if (pass == 0)
        {
-         if (! try_tail_call)
-           continue;
-
          /* Emit any queued insns now; otherwise they would end up in
              only one of the alternates.  */
          emit_queue ();
@@ -2948,7 +2967,7 @@ expand_call (exp, target, ignore)
         be deferred during the evaluation of the arguments.  */
       NO_DEFER_POP;
 
-      funexp = rtx_for_function_call (fndecl, exp);
+      funexp = rtx_for_function_call (fndecl, addr);
 
       /* Figure out the register where the value, if any, will come back.  */
       valreg = 0;
@@ -3319,10 +3338,8 @@ expand_call (exp, target, ignore)
        {
 #ifdef REG_PARM_STACK_SPACE
          if (save_area)
-           {
-             restore_fixed_argument_area (save_area, argblock,
-                                          high_to_save, low_to_save);
-           }
+           restore_fixed_argument_area (save_area, argblock,
+                                        high_to_save, low_to_save);
 #endif
 
          /* If we saved any argument areas, restore them.  */
@@ -3510,7 +3527,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
 #ifdef REG_PARM_STACK_SPACE
   /* Define the boundary of the register parm stack space that needs to be
      save, if any.  */
-  int low_to_save = -1, high_to_save = 0;
+  int low_to_save, high_to_save;
   rtx save_area = 0;            /* Place that it is saved.  */
 #endif
 
@@ -3730,12 +3747,12 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
            {
              tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
 
-             slot = gen_rtx_MEM (mode,
-                                 expand_expr (build1 (ADDR_EXPR,
-                                                      build_pointer_type
-                                                      (type),
-                                                      make_tree (type, val)),
-                                              NULL_RTX, VOIDmode, 0));
+             slot
+               = gen_rtx_MEM (mode,
+                              expand_expr (build1 (ADDR_EXPR,
+                                                   build_pointer_type (type),
+                                                   make_tree (type, val)),
+                                           NULL_RTX, VOIDmode, 0));
            }
 
          call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
@@ -3891,62 +3908,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
     {
       /* The argument list is the property of the called routine and it
         may clobber it.  If the fixed area has been used for previous
-        parameters, we must save and restore it.
-
-        Here we compute the boundary of the that needs to be saved, if any.  */
-
-#ifdef ARGS_GROW_DOWNWARD
-      for (count = 0; count < reg_parm_stack_space + 1; count++)
-#else
-      for (count = 0; count < reg_parm_stack_space; count++)
-#endif
-       {
-         if (count >= highest_outgoing_arg_in_use
-             || stack_usage_map[count] == 0)
-           continue;
-
-         if (low_to_save == -1)
-           low_to_save = count;
-
-         high_to_save = count;
-       }
-
-      if (low_to_save >= 0)
-       {
-         int num_to_save = high_to_save - low_to_save + 1;
-         enum machine_mode save_mode
-           = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-         rtx stack_area;
-
-         /* If we don't have the required alignment, must do this in BLKmode.  */
-         if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
-                                  BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
-           save_mode = BLKmode;
-
-#ifdef ARGS_GROW_DOWNWARD
-         stack_area = gen_rtx_MEM (save_mode,
-                                   memory_address (save_mode,
-                                                   plus_constant (argblock,
-                                                                  -high_to_save)));
-#else
-         stack_area = gen_rtx_MEM (save_mode,
-                                   memory_address (save_mode,
-                                                   plus_constant (argblock,
-                                                                  low_to_save)));
-#endif
-         if (save_mode == BLKmode)
-           {
-             save_area = assign_stack_temp (BLKmode, num_to_save, 0);
-             set_mem_align (save_area, PARM_BOUNDARY);
-             emit_block_move (save_area, stack_area, GEN_INT (num_to_save),
-                              BLOCK_OP_CALL_PARM);
-           }
-         else
-           {
-             save_area = gen_reg_rtx (save_mode);
-             emit_move_insn (save_area, stack_area);
-           }
-       }
+        parameters, we must save and restore it.  */
+      save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
+                                           &low_to_save, &high_to_save);
     }
 #endif
 
@@ -3979,14 +3943,15 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
              upper_bound = lower_bound + argvec[argnum].size.constant;
 #endif
 
-             for (i = lower_bound; i < upper_bound; i++)
-               if (stack_usage_map[i]
-                   /* Don't store things in the fixed argument area at this
-                      point; it has already been saved.  */
-                   && i > reg_parm_stack_space)
-                 break;
+             i = lower_bound;
+             /* Don't worry about things in the fixed argument area;
+                it has already been saved.  */
+             if (i < reg_parm_stack_space)
+               i = reg_parm_stack_space;
+             while (i < upper_bound && stack_usage_map[i] == 0)
+               i++;
 
-             if (i != upper_bound)
+             if (i < upper_bound)
                {
                  /* We need to make a save area.  See what mode we can make
                     it.  */
@@ -4136,7 +4101,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
     {
       rtx insns;
 
-      if (valreg == 0 || GET_CODE (valreg) == PARALLEL)
+      if (valreg == 0)
        {
          insns = get_insns ();
          end_sequence ();
@@ -4145,9 +4110,18 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
       else
        {
          rtx note = 0;
-         rtx temp = gen_reg_rtx (GET_MODE (valreg));
+         rtx temp;
          int i;
 
+         if (GET_CODE (valreg) == PARALLEL)
+           {
+             temp = gen_reg_rtx (outmode);
+             emit_group_store (temp, valreg, outmode);
+             valreg = temp;
+           }
+
+         temp = gen_reg_rtx (GET_MODE (valreg));
+
          /* Construct an "equal form" for the value which mentions all the
             arguments in order as well as the function name.  */
          for (i = 0; i < nargs; i++)
@@ -4181,6 +4155,12 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
          if (value != mem_value)
            emit_move_insn (value, mem_value);
        }
+      else if (GET_CODE (valreg) == PARALLEL)
+       {
+         if (value == 0)
+           value = gen_reg_rtx (outmode);
+         emit_group_store (value, valreg, outmode);
+       }
       else if (value != 0)
        emit_move_insn (value, valreg);
       else
@@ -4191,29 +4171,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
     {
 #ifdef REG_PARM_STACK_SPACE
       if (save_area)
-       {
-         enum machine_mode save_mode = GET_MODE (save_area);
-#ifdef ARGS_GROW_DOWNWARD
-         rtx stack_area
-           = gen_rtx_MEM (save_mode,
-                          memory_address (save_mode,
-                                          plus_constant (argblock,
-                                                         - high_to_save)));
-#else
-         rtx stack_area
-           = gen_rtx_MEM (save_mode,
-                          memory_address (save_mode,
-                                          plus_constant (argblock, low_to_save)));
-#endif
-
-         set_mem_align (stack_area, PARM_BOUNDARY);
-         if (save_mode != BLKmode)
-           emit_move_insn (stack_area, save_area);
-         else
-           emit_block_move (stack_area, save_area,
-                            GEN_INT (high_to_save - low_to_save + 1),
-                            BLOCK_OP_CALL_PARM);
-       }
+       restore_fixed_argument_area (save_area, argblock,
+                                    high_to_save, low_to_save);
 #endif
 
       /* If we saved any argument areas, restore them.  */
@@ -4363,14 +4322,15 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
          upper_bound = lower_bound + arg->size.constant;
 #endif
 
-         for (i = lower_bound; i < upper_bound; i++)
-           if (stack_usage_map[i]
-               /* Don't store things in the fixed argument area at this point;
-                  it has already been saved.  */
-               && i > reg_parm_stack_space)
-             break;
+         i = lower_bound;
+         /* Don't worry about things in the fixed argument area;
+            it has already been saved.  */
+         if (i < reg_parm_stack_space)
+           i = reg_parm_stack_space;
+         while (i < upper_bound && stack_usage_map[i] == 0)
+           i++;
 
-         if (i != upper_bound)
+         if (i < upper_bound)
            {
              /* We need to make a save area.  See what mode we can make it.  */
              enum machine_mode save_mode
@@ -4399,13 +4359,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
                }
            }
        }
-      /* Now that we have saved any slots that will be overwritten by this
-        store, mark all slots this store will use.  We must do this before
-        we actually expand the argument since the expansion itself may
-        trigger library calls which might need to use the same stack slot.  */
-      if (argblock && ! variable_size && arg->stack)
-       for (i = lower_bound; i < upper_bound; i++)
-         stack_usage_map[i] = 1;
     }
 
   /* If this isn't going to be placed on both the stack and in registers,
@@ -4458,7 +4411,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
                                (partial
                                 || TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
                                ? NULL_RTX : arg->stack,
-                               VOIDmode, 0);
+                               VOIDmode, EXPAND_STACK_PARM);
 
       /* If we are promoting object (or for any other reason) the mode
         doesn't agree, convert the mode.  */
@@ -4601,37 +4554,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
            }
        }
 
-      /* Special handling is required if part of the parameter lies in the
-        register parameter area.  The argument may be copied into the stack
-        slot using memcpy(), but the original contents of the register
-        parameter area will be restored after the memcpy() call.
-
-        To ensure that the part that lies in the register parameter area
-        is copied correctly, we emit a separate push for that part.  This
-        push should be small enough to avoid a call to memcpy().  */
-#ifndef STACK_PARMS_IN_REG_PARM_AREA
-      if (arg->reg && arg->pass_on_stack)
-#else
-      if (1)
-#endif
-       {
-         if (arg->offset.constant < reg_parm_stack_space && arg->offset.var)
-           error ("variable offset is passed partially in stack and in reg");
-         else if (arg->offset.constant < reg_parm_stack_space && arg->size.var)
-           error ("variable size is passed partially in stack and in reg");
-         else if (arg->offset.constant < reg_parm_stack_space 
-             && ((arg->offset.constant + arg->size.constant) 
-                  > reg_parm_stack_space))
-          {
-           rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
-           emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
-                           parm_align, partial, reg, excess, argblock,
-                           ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
-                           ARGS_SIZE_RTX (arg->alignment_pad));
-         }
-       }
-       
-
       emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
                      parm_align, partial, reg, excess, argblock,
                      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
@@ -4649,6 +4571,12 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
        arg->value = arg->stack_slot;
     }
 
+  /* Mark all slots this store used.  */
+  if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
+      && argblock && ! variable_size && arg->stack)
+    for (i = lower_bound; i < upper_bound; i++)
+      stack_usage_map[i] = 1;
+
   /* Once we have pushed something, pops can't safely
      be deferred during the rest of the arguments.  */
   NO_DEFER_POP;
@@ -4667,7 +4595,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
   return sibcall_failure;
 }
 
-
 /* Nonzero if we do not know how to pass TYPE solely in registers.
    We cannot do so in the following cases:
 
@@ -4690,7 +4617,7 @@ default_must_pass_in_stack (mode, type)
      tree type;
 {
   if (!type)
-    return true;
+    return false;
 
   /* If the type has variable size...  */
   if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)