This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Problem with stack-adjustment code
- To: Mark Mitchell <mark at codesourcery dot com>
- Subject: Re: Problem with stack-adjustment code
- From: Richard Henderson <rth at cygnus dot com>
- Date: Fri, 28 Apr 2000 11:03:04 -0700
- Cc: law at cygnus dot com, jh at suse dot cz, gcc-bugs at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- References: <20000426160339D.mitchell@codesourcery.com> <Pine.LNX.4.10.10004271152500.20645-100000@u-pl2.ms.mff.cuni.cz> <20000427095839H.mitchell@codesourcery.com>
On Thu, Apr 27, 2000 at 09:58:39AM -0700, Mark Mitchell wrote:
> By the time I got your message, I already had this patch put together.
> Since it fixes my test case, survived a i686-pc-linux-gnu
> bootstrap/test and makes sense to me, I checked it in. However, you
> or Richard may well conclude I blew it.
I think you're largely right. Moreover, combining your new code
with one of Jan's recent patches yields something that seems right
to me for the structure return cases too (compile/20000420-2.c).
r~
PS: Just realized I didn't update the commentary. I'll do that
before I actually check it in.
* calls.c (combine_pending_stack_adjustment_and_call): Return the
adjustment; don't do the stack adjust.
(expand_call): Call compute_argument_block_size right before
allocating the block; update comment; don't do alignment sanity
checking for sibling call; use args_size instead of
unadjusted_args_size before args_size is adjusted. Use
combine_pending_stack_adjustment_and_call to compute stack adjust
for must_preallocate case.
* expr.c (push_block): Remove shadow `temp' in inner scope.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.126
diff -c -p -d -r1.126 calls.c
*** calls.c 2000/04/27 16:44:23 1.126
--- calls.c 2000/04/28 17:53:50
*************** static int special_function_p PARAMS (
*** 210,216 ****
static int flags_from_decl_or_type PARAMS ((tree));
static rtx try_to_integrate PARAMS ((tree, tree, rtx,
int, tree, rtx));
! static void combine_pending_stack_adjustment_and_call
PARAMS ((int, struct args_size *, int));
#ifdef REG_PARM_STACK_SPACE
--- 210,216 ----
static int flags_from_decl_or_type PARAMS ((tree));
static rtx try_to_integrate PARAMS ((tree, tree, rtx,
int, tree, rtx));
! static int combine_pending_stack_adjustment_and_call
PARAMS ((int, struct args_size *, int));
#ifdef REG_PARM_STACK_SPACE
*************** try_to_integrate (fndecl, actparms, targ
*** 1866,1872 ****
ARGS_SIZE->CONSTANT is set to the number of bytes that should be
popped after the call. */
! static void
combine_pending_stack_adjustment_and_call (unadjusted_args_size,
args_size,
preferred_unit_stack_boundary)
--- 1866,1872 ----
ARGS_SIZE->CONSTANT is set to the number of bytes that should be
popped after the call. */
! static int
combine_pending_stack_adjustment_and_call (unadjusted_args_size,
args_size,
preferred_unit_stack_boundary)
*************** combine_pending_stack_adjustment_and_cal
*** 1910,1918 ****
args_size->constant
= pending_stack_adjust - adjustment + unadjusted_args_size;
! /* Push the right number of bytes. */
! pending_stack_adjust = adjustment;
! do_pending_stack_adjust ();
}
/* Generate all the code for a function call
--- 1910,1916 ----
args_size->constant
= pending_stack_adjust - adjustment + unadjusted_args_size;
! return adjustment;
}
/* Generate all the code for a function call
*************** expand_call (exp, target, ignore)
*** 2504,2522 ****
sibcall_failure = 1;
}
- /* Compute the actual size of the argument block required. The variable
- and constant sizes must be combined, the size may have to be rounded,
- and there may be a minimum required size. When generating a sibcall
- pattern, do not round up, since we'll be re-using whatever space our
- caller provided. */
- unadjusted_args_size
- = compute_argument_block_size (reg_parm_stack_space, &args_size,
- (pass == 0 ? 0
- : preferred_stack_boundary));
-
/* If the callee pops its own arguments, then it must pop exactly
the same number of arguments as the current function. */
! if (RETURN_POPS_ARGS (fndecl, funtype, unadjusted_args_size)
!= RETURN_POPS_ARGS (current_function_decl,
TREE_TYPE (current_function_decl),
current_function_args_size))
--- 2502,2510 ----
sibcall_failure = 1;
}
/* If the callee pops its own arguments, then it must pop exactly
the same number of arguments as the current function. */
! if (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
!= RETURN_POPS_ARGS (current_function_decl,
TREE_TYPE (current_function_decl),
current_function_args_size))
*************** expand_call (exp, target, ignore)
*** 2548,2561 ****
if (flags & (ECF_CONST | ECF_PURE | ECF_MALLOC))
start_sequence ();
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
/* The argument block when performing a sibling call is the
incoming argument block. */
if (pass == 0)
argblock = virtual_incoming_args_rtx;
/* If we have no actual push instructions, or shouldn't use them,
make space for all args right now. */
-
else if (args_size.var != 0)
{
if (old_stack_level == 0)
--- 2536,2560 ----
if (flags & (ECF_CONST | ECF_PURE | ECF_MALLOC))
start_sequence ();
+ /* Compute the actual size of the argument block required. The variable
+ and constant sizes must be combined, the size may have to be rounded,
+ and there may be a minimum required size. When generating a sibcall
+ pattern, do not round up, since we'll be re-using whatever space our
+ caller provided. */
+ unadjusted_args_size
+ = compute_argument_block_size (reg_parm_stack_space, &args_size,
+ (pass == 0 ? 0
+ : preferred_stack_boundary));
+
old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
+
/* The argument block when performing a sibling call is the
incoming argument block. */
if (pass == 0)
argblock = virtual_incoming_args_rtx;
+
/* If we have no actual push instructions, or shouldn't use them,
make space for all args right now. */
else if (args_size.var != 0)
{
if (old_stack_level == 0)
*************** expand_call (exp, target, ignore)
*** 2643,2663 ****
{
if (inhibit_defer_pop == 0)
{
! /* Try to reuse some or all of the pending_stack_adjust
! to get this space. Maybe we can avoid any pushing. */
! if (needed > pending_stack_adjust)
! {
! needed -= pending_stack_adjust;
! pending_stack_adjust = 0;
! }
! else
{
! pending_stack_adjust -= needed;
needed = 0;
}
}
! /* Special case this because overhead of `push_block' in this
! case is non-trivial. */
if (needed == 0)
argblock = virtual_outgoing_args_rtx;
else
--- 2642,2666 ----
{
if (inhibit_defer_pop == 0)
{
! needed
! = (combine_pending_stack_adjustment_and_call
! (unadjusted_args_size,
! &args_size,
! preferred_unit_stack_boundary));
! needed = unadjusted_args_size - needed;
!
! if (needed < 0)
{
! pending_stack_adjust = -needed;
! do_pending_stack_adjust ();
needed = 0;
}
+ else
+ pending_stack_adjust = 0;
}
!
! /* Special case this because overhead of `push_block' in
! this case is non-trivial. */
if (needed == 0)
argblock = virtual_outgoing_args_rtx;
else
*************** expand_call (exp, target, ignore)
*** 2725,2734 ****
if (pending_stack_adjust
&& ! (flags & (ECF_CONST | ECF_PURE))
&& ! inhibit_defer_pop)
! combine_pending_stack_adjustment_and_call
! (unadjusted_args_size,
! &args_size,
! preferred_unit_stack_boundary);
else if (argblock == 0)
anti_adjust_stack (GEN_INT (args_size.constant
- unadjusted_args_size));
--- 2728,2741 ----
if (pending_stack_adjust
&& ! (flags & (ECF_CONST | ECF_PURE))
&& ! inhibit_defer_pop)
! {
! pending_stack_adjust
! = (combine_pending_stack_adjustment_and_call
! (unadjusted_args_size,
! &args_size,
! preferred_unit_stack_boundary));
! do_pending_stack_adjust ();
! }
else if (argblock == 0)
anti_adjust_stack (GEN_INT (args_size.constant
- unadjusted_args_size));
*************** expand_call (exp, target, ignore)
*** 2862,2869 ****
now! */
#ifdef PREFERRED_STACK_BOUNDARY
! /* Stack must to be properly aligned now. */
! if (stack_pointer_delta & (preferred_stack_boundary / BITS_PER_UNIT - 1))
abort();
#endif
--- 2869,2878 ----
now! */
#ifdef PREFERRED_STACK_BOUNDARY
! /* Stack must be properly aligned now. */
! if (pass
! && (stack_pointer_delta
! & (preferred_stack_boundary / BITS_PER_UNIT - 1)))
abort();
#endif
*************** emit_library_call_value_1 (retval, orgfu
*** 3767,3773 ****
? hard_libcall_value (outmode) : NULL_RTX);
#ifdef PREFERRED_STACK_BOUNDARY
! /* Stack must to be properly aligned now. */
if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1))
abort();
#endif
--- 3776,3782 ----
? hard_libcall_value (outmode) : NULL_RTX);
#ifdef PREFERRED_STACK_BOUNDARY
! /* Stack must be properly aligned now. */
if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1))
abort();
#endif
Index: expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.232
diff -c -p -d -r1.232 expr.c
*** expr.c 2000/04/27 14:13:48 1.232
--- expr.c 2000/04/28 17:53:51
*************** push_block (size, extra, below)
*** 2840,2846 ****
anti_adjust_stack (size);
else
{
! rtx temp = copy_to_mode_reg (Pmode, size);
if (extra != 0)
temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
temp, 0, OPTAB_LIB_WIDEN);
--- 2840,2846 ----
anti_adjust_stack (size);
else
{
! temp = copy_to_mode_reg (Pmode, size);
if (extra != 0)
temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
temp, 0, OPTAB_LIB_WIDEN);
*************** push_block (size, extra, below)
*** 2857,2863 ****
if (1)
#endif
{
-
/* Return the lowest stack address when STACK or ARGS grow downward and
we are not aaccumulating outgoing arguments (the c4x port uses such
conventions). */
--- 2857,2862 ----