Commit f8a097cd by Jan Hubicka Committed by Jan Hubicka

calls.c (expand_call): Avoid unnecesary precalculation and outgoing parameters…

calls.c (expand_call): Avoid unnecesary precalculation and outgoing parameters space guarding for...

	* calls.c (expand_call): Avoid unnecesary precalculation
	and outgoing parameters space guarding for sibling calls.
	(store_one_arg): Likewise.

From-SVN: r33280
parent 48d9ade5
Thu Apr 20 14:19:18 MET DST 2000 Jan Hubicka <jh@suse.cz>
* calls.c (expand_call): Avoid unnecesary precalculation
and outgoing parameters space guarding for sibling calls.
(store_one_arg): Likewise.
Thu Apr 20 08:01:07 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> Thu Apr 20 08:01:07 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* toplev.c (enum dump_file_index, dump_file): Add DFI_sibling. * toplev.c (enum dump_file_index, dump_file): Add DFI_sibling.
......
...@@ -2467,11 +2467,11 @@ expand_call (exp, target, ignore) ...@@ -2467,11 +2467,11 @@ expand_call (exp, target, ignore)
|| reg_mentioned_p (virtual_outgoing_args_rtx, || reg_mentioned_p (virtual_outgoing_args_rtx,
structure_value_addr)) structure_value_addr))
&& (args_size.var && (args_size.var
|| (!ACCUMULATE_OUTGOING_ARGS && args_size.constant) || (!ACCUMULATE_OUTGOING_ARGS && args_size.constant)))
))
structure_value_addr = copy_to_reg (structure_value_addr); structure_value_addr = copy_to_reg (structure_value_addr);
/* Precompute any arguments as needed. */ /* Precompute any arguments as needed. */
if (pass)
precompute_arguments (flags, num_actuals, args); precompute_arguments (flags, num_actuals, args);
/* Now we are about to start emitting insns that can be deleted /* Now we are about to start emitting insns that can be deleted
...@@ -2480,11 +2480,14 @@ expand_call (exp, target, ignore) ...@@ -2480,11 +2480,14 @@ expand_call (exp, target, ignore)
start_sequence (); start_sequence ();
old_stack_allocated = stack_pointer_delta - pending_stack_adjust; 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, /* If we have no actual push instructions, or shouldn't use them,
make space for all args right now. */ make space for all args right now. */
if (args_size.var != 0) else if (args_size.var != 0)
{ {
if (old_stack_level == 0) if (old_stack_level == 0)
{ {
...@@ -2519,24 +2522,24 @@ expand_call (exp, target, ignore) ...@@ -2519,24 +2522,24 @@ expand_call (exp, target, ignore)
{ {
if (ACCUMULATE_OUTGOING_ARGS) if (ACCUMULATE_OUTGOING_ARGS)
{ {
/* Since the stack pointer will never be pushed, it is possible /* Since the stack pointer will never be pushed, it is
for the evaluation of a parm to clobber something we have possible for the evaluation of a parm to clobber
already written to the stack. Since most function calls on something we have already written to the stack.
RISC machines do not use the stack, this is uncommon, but Since most function calls on RISC machines do not use
must work correctly. the stack, this is uncommon, but must work correctly.
Therefore, we save any area of the stack that was already Therefore, we save any area of the stack that was already
written and that we are using. Here we set up to do this by written and that we are using. Here we set up to do this
making a new stack usage map from the old one. The actual by making a new stack usage map from the old one. The
save will be done by store_one_arg. actual save will be done by store_one_arg.
Another approach might be to try to reorder the argument Another approach might be to try to reorder the argument
evaluations to avoid this conflicting stack usage. */ evaluations to avoid this conflicting stack usage. */
#ifndef OUTGOING_REG_PARM_STACK_SPACE #ifndef OUTGOING_REG_PARM_STACK_SPACE
/* Since we will be writing into the entire argument area, the /* Since we will be writing into the entire argument area,
map must be allocated for its entire size, not just the part the map must be allocated for its entire size, not just
that is the responsibility of the caller. */ the part that is the responsibility of the caller. */
needed += reg_parm_stack_space; needed += reg_parm_stack_space;
#endif #endif
...@@ -2547,7 +2550,8 @@ expand_call (exp, target, ignore) ...@@ -2547,7 +2550,8 @@ expand_call (exp, target, ignore)
highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use, highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
needed); needed);
#endif #endif
stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use); stack_usage_map
= (char *) alloca (highest_outgoing_arg_in_use);
if (initial_highest_arg_in_use) if (initial_highest_arg_in_use)
bcopy (initial_stack_usage_map, stack_usage_map, bcopy (initial_stack_usage_map, stack_usage_map,
...@@ -2559,9 +2563,9 @@ expand_call (exp, target, ignore) ...@@ -2559,9 +2563,9 @@ expand_call (exp, target, ignore)
- initial_highest_arg_in_use)); - initial_highest_arg_in_use));
needed = 0; needed = 0;
/* The address of the outgoing argument list must not be copied /* The address of the outgoing argument list must not be
to a register here, because argblock would be left pointing copied to a register here, because argblock would be left
to the wrong place after the call to pointing to the wrong place after the call to
allocate_dynamic_stack_space below. */ allocate_dynamic_stack_space below. */
argblock = virtual_outgoing_args_rtx; argblock = virtual_outgoing_args_rtx;
...@@ -2590,31 +2594,19 @@ expand_call (exp, target, ignore) ...@@ -2590,31 +2594,19 @@ expand_call (exp, target, ignore)
else else
argblock = push_block (GEN_INT (needed), 0, 0); argblock = push_block (GEN_INT (needed), 0, 0);
/* We only really need to call `copy_to_reg' in the case where /* We only really need to call `copy_to_reg' in the case
push insns are going to be used to pass ARGBLOCK to a function where push insns are going to be used to pass ARGBLOCK
call in ARGS. In that case, the stack pointer changes value to a function call in ARGS. In that case, the stack
from the allocation point to the call point, and hence pointer changes value from the allocation point to the
the value of VIRTUAL_OUTGOING_ARGS_RTX changes as well. call point, and hence the value of
But might as well always do it. */ VIRTUAL_OUTGOING_ARGS_RTX changes as well. But might
as well always do it. */
argblock = copy_to_reg (argblock); argblock = copy_to_reg (argblock);
}
}
}
/* The argument block when performing a sibling call is the /* The save/restore code in store_one_arg handles all
incoming argument block. */ cases except one:
if (pass == 0) a constructor call (including a C function returning
{ a BLKmode struct) to initialize an argument. */
rtx temp = plus_constant (arg_pointer_rtx,
FIRST_PARM_OFFSET (current_function_decl));
argblock = force_reg (Pmode, force_operand (temp, NULL_RTX));
}
if (ACCUMULATE_OUTGOING_ARGS)
{
/* The save/restore code in store_one_arg handles all cases except one:
a constructor call (including a C function returning a BLKmode struct)
to initialize an argument. */
if (stack_arg_under_construction) if (stack_arg_under_construction)
{ {
#ifndef OUTGOING_REG_PARM_STACK_SPACE #ifndef OUTGOING_REG_PARM_STACK_SPACE
...@@ -2648,6 +2640,8 @@ expand_call (exp, target, ignore) ...@@ -2648,6 +2640,8 @@ expand_call (exp, target, ignore)
break; break;
} }
} }
}
}
compute_argument_addresses (args, argblock, num_actuals); compute_argument_addresses (args, argblock, num_actuals);
...@@ -2709,7 +2703,7 @@ expand_call (exp, target, ignore) ...@@ -2709,7 +2703,7 @@ expand_call (exp, target, ignore)
#ifdef REG_PARM_STACK_SPACE #ifdef REG_PARM_STACK_SPACE
/* Save the fixed argument area if it's part of the caller's frame and /* Save the fixed argument area if it's part of the caller's frame and
is clobbered by argument setup for this call. */ is clobbered by argument setup for this call. */
if (ACCUMULATE_OUTGOING_ARGS) if (ACCUMULATE_OUTGOING_ARGS && pass)
save_area = save_fixed_argument_area (reg_parm_stack_space, argblock, save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
&low_to_save, &high_to_save); &low_to_save, &high_to_save);
#endif #endif
...@@ -2722,7 +2716,7 @@ expand_call (exp, target, ignore) ...@@ -2722,7 +2716,7 @@ expand_call (exp, target, ignore)
for (i = 0; i < num_actuals; i++) for (i = 0; i < num_actuals; i++)
if (args[i].reg == 0 || args[i].pass_on_stack) if (args[i].reg == 0 || args[i].pass_on_stack)
store_one_arg (&args[i], argblock, flags & ECF_MAY_BE_ALLOCA, store_one_arg (&args[i], argblock, flags,
args_size.var != 0, reg_parm_stack_space); args_size.var != 0, reg_parm_stack_space);
/* If we have a parm that is passed in registers but not in memory /* If we have a parm that is passed in registers but not in memory
...@@ -2737,7 +2731,7 @@ expand_call (exp, target, ignore) ...@@ -2737,7 +2731,7 @@ expand_call (exp, target, ignore)
if (reg_parm_seen) if (reg_parm_seen)
for (i = 0; i < num_actuals; i++) for (i = 0; i < num_actuals; i++)
if (args[i].partial != 0 && ! args[i].pass_on_stack) if (args[i].partial != 0 && ! args[i].pass_on_stack)
store_one_arg (&args[i], argblock, flags & ECF_MAY_BE_ALLOCA, store_one_arg (&args[i], argblock, flags,
args_size.var != 0, reg_parm_stack_space); args_size.var != 0, reg_parm_stack_space);
#ifdef PREFERRED_STACK_BOUNDARY #ifdef PREFERRED_STACK_BOUNDARY
...@@ -3037,14 +3031,13 @@ expand_call (exp, target, ignore) ...@@ -3037,14 +3031,13 @@ expand_call (exp, target, ignore)
stack_usage_map = initial_stack_usage_map; stack_usage_map = initial_stack_usage_map;
sibcall_failure = 1; sibcall_failure = 1;
} }
else if (ACCUMULATE_OUTGOING_ARGS) else if (ACCUMULATE_OUTGOING_ARGS && pass)
{ {
#ifdef REG_PARM_STACK_SPACE #ifdef REG_PARM_STACK_SPACE
if (save_area) if (save_area)
{ {
restore_fixed_argument_area (save_area, argblock, restore_fixed_argument_area (save_area, argblock,
high_to_save, low_to_save); high_to_save, low_to_save);
sibcall_failure = 1;
} }
#endif #endif
...@@ -3065,7 +3058,6 @@ expand_call (exp, target, ignore) ...@@ -3065,7 +3058,6 @@ expand_call (exp, target, ignore)
validize_mem (args[i].save_area), validize_mem (args[i].save_area),
GEN_INT (args[i].size.constant), GEN_INT (args[i].size.constant),
PARM_BOUNDARY); PARM_BOUNDARY);
sibcall_failure = 1;
} }
highest_outgoing_arg_in_use = initial_highest_arg_in_use; highest_outgoing_arg_in_use = initial_highest_arg_in_use;
...@@ -3595,8 +3587,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) ...@@ -3595,8 +3587,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
{ {
if (ACCUMULATE_OUTGOING_ARGS) if (ACCUMULATE_OUTGOING_ARGS)
{ {
/* If this is being stored into a pre-allocated, fixed-size, stack /* If this is being stored into a pre-allocated, fixed-size,
area, save any previous data at that location. */ stack area, save any previous data at that location. */
#ifdef ARGS_GROW_DOWNWARD #ifdef ARGS_GROW_DOWNWARD
/* stack_slot is negative, but we want to index stack_usage_map /* stack_slot is negative, but we want to index stack_usage_map
...@@ -3610,16 +3602,18 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) ...@@ -3610,16 +3602,18 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
for (i = lower_bound; i < upper_bound; i++) for (i = lower_bound; i < upper_bound; i++)
if (stack_usage_map[i] if (stack_usage_map[i]
/* Don't store things in the fixed argument area at this point; /* Don't store things in the fixed argument area at this
it has already been saved. */ point; it has already been saved. */
&& i > reg_parm_stack_space) && i > reg_parm_stack_space)
break; break;
if (i != upper_bound) if (i != upper_bound)
{ {
/* We need to make a save area. See what mode we can make it. */ /* We need to make a save area. See what mode we can make
it. */
enum machine_mode save_mode enum machine_mode save_mode
= mode_for_size (argvec[argnum].size.constant * BITS_PER_UNIT, = mode_for_size (argvec[argnum].size.constant
* BITS_PER_UNIT,
MODE_INT, 1); MODE_INT, 1);
rtx stack_area rtx stack_area
= gen_rtx_MEM = gen_rtx_MEM
...@@ -3975,11 +3969,11 @@ target_for_arg (type, size, args_addr, offset) ...@@ -3975,11 +3969,11 @@ target_for_arg (type, size, args_addr, offset)
FNDECL is the declaration of the function we are calling. */ FNDECL is the declaration of the function we are calling. */
static void static void
store_one_arg (arg, argblock, may_be_alloca, variable_size, store_one_arg (arg, argblock, flags, variable_size,
reg_parm_stack_space) reg_parm_stack_space)
struct arg_data *arg; struct arg_data *arg;
rtx argblock; rtx argblock;
int may_be_alloca; int flags;
int variable_size ATTRIBUTE_UNUSED; int variable_size ATTRIBUTE_UNUSED;
int reg_parm_stack_space; int reg_parm_stack_space;
{ {
...@@ -3996,7 +3990,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, ...@@ -3996,7 +3990,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size,
this argument. */ this argument. */
push_temp_slots (); push_temp_slots ();
if (ACCUMULATE_OUTGOING_ARGS) if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL))
{ {
/* If this is being stored into a pre-allocated, fixed-size, stack area, /* If this is being stored into a pre-allocated, fixed-size, stack area,
save any previous data at that location. */ save any previous data at that location. */
...@@ -4124,7 +4118,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size, ...@@ -4124,7 +4118,7 @@ store_one_arg (arg, argblock, may_be_alloca, variable_size,
/* Don't allow anything left on stack from computation /* Don't allow anything left on stack from computation
of argument to alloca. */ of argument to alloca. */
if (may_be_alloca) if (flags & ECF_MAY_BE_ALLOCA)
do_pending_stack_adjust (); do_pending_stack_adjust ();
if (arg->value == arg->stack) if (arg->value == arg->stack)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment