This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Problem with stack-adjustment code


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 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]