This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
stack_pointer_delta patch updated
- To: egcs-patches at egcs dot cygnus dot com, rth at cygnus dot com
- Subject: stack_pointer_delta patch updated
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Thu, 30 Mar 2000 13:35:41 +0200
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. */