This is the mail archive of the gcc-patches@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]

stack_pointer_delta patch updated


Hi
My stack pointer delta needed some updating after the ACCUMULATE_ARGS changes.
Also I was able to give it much better testing the before, since I was able to do
all 3 modes of bootstraps on ia32 and tested it on PPC at SuSE.
It seems to work reliably and especially for -mno-push-args is necessary in order
to get sane code for PREFERRED_STACK_BOUNDARY.

I've also measured speedups in Spec95 benchmarks, so it looks like frame is aligned
more often than previously. I plan to hack prologues code to verify alignment
at runtime soon.

Honza

Wed Mar 22 16:05:38 MET 2000  Jan Hubicka  <jh@suse.cz>

	* builtins.c  (expand_builtin_apply):  Pass proper parameters to
	allocate_dynamic_stack_space.
	* calls.c (emit_call_1):  Do not adjust stack pointer for SIB,
	update stack_pointer_delta; do not update arg_size_so_far.
	(compute_argument_block_size): Use stack_delta instead of
	stack_pointer_pending and arg_size_so_far.
	(expand_call): Add sanity checking for stack_pointer_delta;
	save and restore stack_pointer_delta for SIB, use
	stack_pointer_delta for alignment; do not update arg_space_so_far.
	(emit_library_call_value): Use stack_pointer_delta for alignment.
	(store_one_arg): Do not update arg_space_so_far.
	* explow.c (adjust_stack, anti_adjust_stack): Update
	stack_pointer_delta.
	(allocate_dynamic_stack_space): Add sanity checking for
	stack_pointer_delta.
	* expr.c (init_expr, clear_pending_stack_adjust): Clear
	stack_pointer_delta.
	(emit_push_insn): Update stack_pointer_delta.
	* function.h (struct expr_status): Add x_stack_pointer_delta;
	remove x_arg_space_so_far.
	(arg_space_so_far): Remove.
	(stack_pointer_delta): New macro.

Index: egcs/gcc//builtins.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/builtins.c,v
retrieving revision 1.42
diff -c -3 -p -r1.42 builtins.c
*** builtins.c	2000/03/30 00:03:14	1.42
--- builtins.c	2000/03/30 11:26:13
*************** expand_builtin_apply (function, argument
*** 870,877 ****
    /* Create a block where the return registers can be saved.  */
    result = assign_stack_local (BLKmode, apply_result_size (), -1);
  
-   /* ??? The argsize value should be adjusted here.  */
- 
    /* Fetch the arg pointer from the ARGUMENTS block.  */
    incoming_args = gen_reg_rtx (Pmode);
    emit_move_insn (incoming_args,
--- 870,875 ----
*************** expand_builtin_apply (function, argument
*** 900,906 ****
       haven't figured out how the calling convention macros effect this,
       but it's likely that the source and/or destination addresses in
       the block copy will need updating in machine specific ways.  */
!   dest = allocate_dynamic_stack_space (argsize, 0, 0);
    emit_block_move (gen_rtx_MEM (BLKmode, dest),
  		   gen_rtx_MEM (BLKmode, incoming_args),
  		   argsize,
--- 898,904 ----
       haven't figured out how the calling convention macros effect this,
       but it's likely that the source and/or destination addresses in
       the block copy will need updating in machine specific ways.  */
!   dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
    emit_block_move (gen_rtx_MEM (BLKmode, dest),
  		   gen_rtx_MEM (BLKmode, incoming_args),
  		   argsize,
Index: egcs/gcc//calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.109
diff -c -3 -p -r1.109 calls.c
*** calls.c	2000/03/29 22:46:03	1.109
--- calls.c	2000/03/30 11:26:13
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 577,582 ****
--- 577,583 ----
  			       CALL_INSN_FUNCTION_USAGE (call_insn));
        rounded_stack_size -= n_popped;
        rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
+       stack_pointer_delta -= n_popped;
      }
  
    if (!ACCUMULATE_OUTGOING_ARGS)
*************** emit_call_1 (funexp, fndecl, funtype, st
*** 588,597 ****
  	 If returning from the subroutine does pop the args, indicate that the
  	 stack pointer will be changed.  */
  
-       /* The space for the args is no longer waiting for the call; either it
- 	 was popped by the call, or it'll be popped below.  */
-       arg_space_so_far -= rounded_stack_size - n_popped;
- 
        if (rounded_stack_size != 0)
  	{
  	  if (flag_defer_pop && inhibit_defer_pop == 0
--- 589,594 ----
*************** compute_argument_block_size (reg_parm_st
*** 1308,1314 ****
  #ifdef PREFERRED_STACK_BOUNDARY
        preferred_stack_boundary /= BITS_PER_UNIT;
        if (preferred_stack_boundary > 1)
! 	args_size->var = round_up (args_size->var, preferred_stack_boundary);
  #endif
  
        if (reg_parm_stack_space > 0)
--- 1305,1318 ----
  #ifdef PREFERRED_STACK_BOUNDARY
        preferred_stack_boundary /= BITS_PER_UNIT;
        if (preferred_stack_boundary > 1)
! 	{
! 	  /* We don't handle this case yet.  To handle it correctly we have
! 	     to add the delta, round and substract the delta.  
! 	     Currently no machine description requires this support.  */
! 	  if (stack_pointer_delta & (preferred_stack_boundary - 1))
! 	    abort();
! 	  args_size->var = round_up (args_size->var, preferred_stack_boundary);
! 	}
  #endif
  
        if (reg_parm_stack_space > 0)
*************** compute_argument_block_size (reg_parm_st
*** 1333,1345 ****
        if (preferred_stack_boundary < 1)
  	preferred_stack_boundary = 1;
        args_size->constant = (((args_size->constant
! 			       + arg_space_so_far
! 			       + pending_stack_adjust
  			       + preferred_stack_boundary - 1)
  			      / preferred_stack_boundary
  			      * preferred_stack_boundary)
! 			     - arg_space_so_far
! 			     - pending_stack_adjust);
  #endif
  
        args_size->constant = MAX (args_size->constant,
--- 1337,1347 ----
        if (preferred_stack_boundary < 1)
  	preferred_stack_boundary = 1;
        args_size->constant = (((args_size->constant
! 			       + stack_pointer_delta
  			       + preferred_stack_boundary - 1)
  			      / preferred_stack_boundary
  			      * preferred_stack_boundary)
! 			     - stack_pointer_delta);
  #endif
  
        args_size->constant = MAX (args_size->constant,
*************** expand_call (exp, target, ignore)
*** 1819,1824 ****
--- 1821,1827 ----
    rtx old_stack_level = 0;
    int old_pending_adj = 0;
    int old_inhibit_defer_pop = inhibit_defer_pop;
+   int old_stack_allocated;
    rtx call_fusage;
    register tree p;
    register int i;
*************** expand_call (exp, target, ignore)
*** 2124,2129 ****
--- 2127,2133 ----
  	 recursion call can be ignored if we indeed use the tail recursion
  	 call expansion.  */
        int save_pending_stack_adjust = pending_stack_adjust;
+       int save_stack_pointer_delta = stack_pointer_delta;
  
        /* Use a new sequence to hold any RTL we generate.  We do not even
  	 know if we will use this RTL yet.  The final decision can not be
*************** expand_call (exp, target, ignore)
*** 2141,2146 ****
--- 2145,2151 ----
        /* Restore the original pending stack adjustment for the sibling and
  	 normal call cases below.  */
        pending_stack_adjust = save_pending_stack_adjust;
+       stack_pointer_delta = save_stack_pointer_delta;
      }
  
    function_call_count++;
*************** expand_call (exp, target, ignore)
*** 2186,2191 ****
--- 2191,2197 ----
  	 recursion call can be ignored if we indeed use the tail recursion
  	 call expansion.  */
        int save_pending_stack_adjust;
+       int save_stack_pointer_delta;
        rtx insns;
        rtx before_call, next_arg_reg;
  
*************** expand_call (exp, target, ignore)
*** 2223,2228 ****
--- 2229,2235 ----
  	  /* State variables we need to save and restore between
  	     iterations.  */
  	  save_pending_stack_adjust = pending_stack_adjust;
+ 	  save_stack_pointer_delta = stack_pointer_delta;
  	}
  
        /* Other state variables that we must reinitialize each time
*************** expand_call (exp, target, ignore)
*** 2417,2422 ****
--- 2424,2431 ----
        if (is_const || is_malloc)
  	start_sequence ();
  
+       old_stack_allocated =  stack_pointer_delta - pending_stack_adjust;
+ 
        /* If we have no actual push instructions, or shouldn't use them,
  	 make space for all args right now.  */
  
*************** expand_call (exp, target, ignore)
*** 2598,2619 ****
  	  if (pending_stack_adjust && ! is_const
  	      && ! inhibit_defer_pop)
  	    {
  	      args_size.constant = (unadjusted_args_size
  				    + ((pending_stack_adjust
  					+ args_size.constant
- 					+ arg_space_so_far
  					- unadjusted_args_size)
  				       % (preferred_stack_boundary
  					  / BITS_PER_UNIT)));
! 	      pending_stack_adjust -= (args_size.constant
! 				       - unadjusted_args_size);
! 	      do_pending_stack_adjust ();
  	    }
  	  else if (argblock == 0)
  	    anti_adjust_stack (GEN_INT (args_size.constant
  					- unadjusted_args_size));
- 	  arg_space_so_far += args_size.constant - unadjusted_args_size;
- 
  	  /* Now that the stack is properly aligned, pops can't safely
  	     be deferred during the evaluation of the arguments.  */
  	  NO_DEFER_POP;
--- 2607,2627 ----
  	  if (pending_stack_adjust && ! is_const
  	      && ! inhibit_defer_pop)
  	    {
+ 	      int adjust;
  	      args_size.constant = (unadjusted_args_size
  				    + ((pending_stack_adjust
  					+ args_size.constant
  					- unadjusted_args_size)
  				       % (preferred_stack_boundary
  					  / BITS_PER_UNIT)));
! 	      adjust = (pending_stack_adjust - args_size.constant
! 		        + unadjusted_args_size);
! 	      adjust_stack (GEN_INT (adjust));
! 	      pending_stack_adjust = 0;
  	    }
  	  else if (argblock == 0)
  	    anti_adjust_stack (GEN_INT (args_size.constant
  					- unadjusted_args_size));
  	  /* Now that the stack is properly aligned, pops can't safely
  	     be deferred during the evaluation of the arguments.  */
  	  NO_DEFER_POP;
*************** expand_call (exp, target, ignore)
*** 2680,2686 ****
  #ifdef PREFERRED_STACK_BOUNDARY
        /* If we pushed args in forward order, perform stack alignment
  	 after pushing the last arg.  */
-       /* ??? Fix for arg_space_so_far.  */
        if (!PUSH_ARGS_REVERSED && argblock == 0)
  	anti_adjust_stack (GEN_INT (args_size.constant
  				    - unadjusted_args_size));
--- 2688,2693 ----
*************** expand_call (exp, target, ignore)
*** 2752,2757 ****
--- 2759,2769 ----
  		    | (nothrow ? ECF_NOTHROW : 0)
  		    | (pass == 0 ? ECF_SIBCALL : 0)));
  
+       /* Verify that we've deallocated all the stack we used.  */
+       if (pass
+           && old_stack_allocated != stack_pointer_delta - pending_stack_adjust)
+ 	abort();
+ 
        /* If call is cse'able, make appropriate pair of reg-notes around it.
  	 Test valreg so we don't crash; may safely ignore `const'
  	 if return type is void.  Disable for PARALLEL return values, because
*************** expand_call (exp, target, ignore)
*** 3033,3042 ****
  	     zero out the sequence.  */
  	  if (sibcall_failure)
  	    tail_call_insns = NULL_RTX;
- 
  	  /* Restore the pending stack adjustment now that we have
  	     finished generating the sibling call sequence.  */
  	  pending_stack_adjust = save_pending_stack_adjust;
  	}
        else
  	normal_call_insns = insns;
--- 3045,3055 ----
  	     zero out the sequence.  */
  	  if (sibcall_failure)
  	    tail_call_insns = NULL_RTX;
  	  /* Restore the pending stack adjustment now that we have
  	     finished generating the sibling call sequence.  */
+ 
  	  pending_stack_adjust = save_pending_stack_adjust;
+ 	  stack_pointer_delta = save_stack_pointer_delta;
  	}
        else
  	normal_call_insns = insns;
*************** emit_library_call_value_1 (retval, orgfu
*** 3335,3342 ****
  
    original_args_size = args_size;
  #ifdef PREFERRED_STACK_BOUNDARY
!   args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
! 			 / STACK_BYTES) * STACK_BYTES);
  #endif
  
    args_size.constant = MAX (args_size.constant,
--- 3348,3359 ----
  
    original_args_size = args_size;
  #ifdef PREFERRED_STACK_BOUNDARY
!   args_size.constant = (((args_size.constant
! 			  + stack_pointer_delta
! 			  + STACK_BYTES - 1)
! 			  / STACK_BYTES
! 			  * STACK_BYTES)
! 			 - stack_pointer_delta);
  #endif
  
    args_size.constant = MAX (args_size.constant,
*************** store_one_arg (arg, argblock, may_be_all
*** 4051,4058 ****
  		      partial, reg, used - size, argblock,
  		      ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
  		      ARGS_SIZE_RTX (arg->alignment_pad));
- 
-       arg_space_so_far += used;
      }
    else
      {
--- 4068,4073 ----
*************** store_one_arg (arg, argblock, may_be_all
*** 4080,4086 ****
  	  excess = (arg->size.constant - int_size_in_bytes (TREE_TYPE (pval))
  		    + partial * UNITS_PER_WORD);
  	  size_rtx = expr_size (pval);
- 	  arg_space_so_far += excess + INTVAL (size_rtx);
  	}
  
        emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
--- 4095,4100 ----
Index: egcs/gcc//explow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/explow.c,v
retrieving revision 1.43
diff -c -3 -p -r1.43 explow.c
*** explow.c	2000/03/25 18:34:01	1.43
--- explow.c	2000/03/30 11:26:15
*************** adjust_stack (adjust)
*** 852,857 ****
--- 852,862 ----
    if (adjust == const0_rtx)
      return;
  
+   /* We expect all variable sized adjustments to be multiple of
+      PREFERRED_STACK_BOUNDARY.  */
+   if (GET_CODE (adjust) == CONST_INT)
+     stack_pointer_delta -= INTVAL (adjust);
+ 
    temp = expand_binop (Pmode,
  #ifdef STACK_GROWS_DOWNWARD
  		       add_optab,
*************** anti_adjust_stack (adjust)
*** 878,883 ****
--- 883,893 ----
    if (adjust == const0_rtx)
      return;
  
+   /* We expect all variable sized adjustments to be multiple of
+      PREFERRED_STACK_BOUNDARY.  */
+   if (GET_CODE (adjust) == CONST_INT)
+     stack_pointer_delta += INTVAL (adjust);
+ 
    temp = expand_binop (Pmode,
  #ifdef STACK_GROWS_DOWNWARD
  		       sub_optab,
*************** allocate_dynamic_stack_space (size, targ
*** 1294,1299 ****
--- 1304,1316 ----
  #endif
  
    do_pending_stack_adjust ();
+ 
+  /* We ought to be called always on the toplevel and stack ought to be aligned
+     propertly.  */
+ #ifdef PREFERRED_STACK_BOUNDARY
+   if (stack_pointer_delta % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT))
+     abort ();
+ #endif
  
    /* If needed, check that we have the required amount of stack.  Take into
       account what has already been checked.  */
Index: egcs/gcc//expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.223
diff -c -3 -p -r1.223 expr.c
*** expr.c	2000/03/29 13:10:41	1.223
--- expr.c	2000/03/30 11:26:17
*************** init_expr ()
*** 306,312 ****
  
    pending_chain = 0;
    pending_stack_adjust = 0;
!   arg_space_so_far = 0;
    inhibit_defer_pop = 0;
    saveregs_value = 0;
    apply_args_value = 0;
--- 306,312 ----
  
    pending_chain = 0;
    pending_stack_adjust = 0;
!   stack_pointer_delta = 0;
    inhibit_defer_pop = 0;
    saveregs_value = 0;
    apply_args_value = 0;
*************** emit_push_insn (x, mode, type, size, ali
*** 3012,3017 ****
--- 3012,3018 ----
  	      && where_pad != none && where_pad != stack_direction)
  	    anti_adjust_stack (GEN_INT (extra));
  
+ 	  stack_pointer_delta += INTVAL (size) - used;
  	  move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
  			  INTVAL (size) - used, align);
  
*************** emit_push_insn (x, mode, type, size, ali
*** 3252,3258 ****
  
  #ifdef PUSH_ROUNDING
        if (args_addr == 0 && PUSH_ARGS)
! 	addr = gen_push_operand ();
        else
  #endif
  	{
--- 3253,3262 ----
  
  #ifdef PUSH_ROUNDING
        if (args_addr == 0 && PUSH_ARGS)
! 	{
! 	  addr = gen_push_operand ();
! 	  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
! 	}
        else
  #endif
  	{
*************** clear_pending_stack_adjust ()
*** 9149,9155 ****
        && EXIT_IGNORE_STACK
        && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
        && ! flag_inline_functions)
!     pending_stack_adjust = 0;
  #endif
  }
  
--- 9153,9162 ----
        && EXIT_IGNORE_STACK
        && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
        && ! flag_inline_functions)
!     {
!       stack_pointer_delta -= pending_stack_adjust,
!       pending_stack_adjust = 0;
!     }
  #endif
  }
  
Index: egcs/gcc//function.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.h,v
retrieving revision 1.52
diff -c -3 -p -r1.52 function.h
*** function.h	2000/03/25 18:34:02	1.52
--- function.h	2000/03/30 11:26:17
*************** struct expr_status
*** 130,139 ****
       These are the arguments to function calls that have already returned.  */
    int x_pending_stack_adjust;
  
-   /* Number of units that we should eventually pop off the stack.
-      These are the arguments to function calls that have not happened yet.  */
-   int x_arg_space_so_far;
- 
    /* Under some ABIs, it is the caller's responsibility to pop arguments
       pushed for function calls.  A naive implementation would simply pop
       the arguments immediately after each call.  However, if several
--- 130,135 ----
*************** struct expr_status
*** 151,156 ****
--- 147,158 ----
       NO_DEFER_POP and OK_DEFER_POP.  */
    int x_inhibit_defer_pop;
  
+   /* If PREFERRED_STACK_BOUNDARY and PUSH_ROUNDING are defined, the stack
+      boundary can be momentairly unaligned while pushing the arguments.
+      Record the delta since last aligned boundary here in order to get
+      stack alignment in the nested function calls working right.  */
+   int x_stack_pointer_delta;
+ 
    /* Nonzero means __builtin_saveregs has already been done in this function.
       The value is the pseudoreg containing the value __builtin_saveregs
       returned.  */
*************** struct expr_status
*** 167,178 ****
  };
  
  #define pending_stack_adjust (cfun->expr->x_pending_stack_adjust)
- #define arg_space_so_far (cfun->expr->x_arg_space_so_far)
  #define inhibit_defer_pop (cfun->expr->x_inhibit_defer_pop)
  #define saveregs_value (cfun->expr->x_saveregs_value)
  #define apply_args_value (cfun->expr->x_apply_args_value)
  #define forced_labels (cfun->expr->x_forced_labels)
  #define pending_chain (cfun->expr->x_pending_chain)
  
  /* This structure can save all the important global and static variables
     describing the status of the current function.  */
--- 169,180 ----
  };
  
  #define pending_stack_adjust (cfun->expr->x_pending_stack_adjust)
  #define inhibit_defer_pop (cfun->expr->x_inhibit_defer_pop)
  #define saveregs_value (cfun->expr->x_saveregs_value)
  #define apply_args_value (cfun->expr->x_apply_args_value)
  #define forced_labels (cfun->expr->x_forced_labels)
  #define pending_chain (cfun->expr->x_pending_chain)
+ #define stack_pointer_delta (cfun->expr->x_stack_pointer_delta)
  
  /* This structure can save all the important global and static variables
     describing the status of the current function.  */

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