Commit 37017f4d by Richard Sandiford Committed by Richard Sandiford

mips.h (STARTING_FRAME_OFFSET): Remove rtl profiling code.

gcc/
	* config/mips/mips.h (STARTING_FRAME_OFFSET): Remove rtl
	profiling code.
	* config/mips/mips.c (mips_frame_info): Give num_gp and num_fp type
	"unsigned int" rather than "int" and put them with the other
	register-related fields.  Put expanded comments above fields
	rather than to their right.
	(mips16e_mask_registers): Replace the GP_REG_SIZE_PTR argument
	with a NUM_REGS_PTR argument.
	(mips16e_save_restore_pattern_p): Update accordingly.
	(compute_frame_size): Clarify frame diagram.  Rewrite.

From-SVN: r129456
parent 41030557
2007-10-18 Richard Sandiford <rsandifo@nildram.co.uk> 2007-10-18 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.h (STARTING_FRAME_OFFSET): Remove rtl
profiling code.
* config/mips/mips.c (mips_frame_info): Give num_gp and num_fp type
"unsigned int" rather than "int" and put them with the other
register-related fields. Put expanded comments above fields
rather than to their right.
(mips16e_mask_registers): Replace the GP_REG_SIZE_PTR argument
with a NUM_REGS_PTR argument.
(mips16e_save_restore_pattern_p): Update accordingly.
(compute_frame_size): Clarify frame diagram. Rewrite.
2007-10-18 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips-ftypes.def: New file. * config/mips/mips-ftypes.def: New file.
* config/mips/mips.c (MIPS_FTYPE_NAME1, MIPS_FTYPE_NAME2) * config/mips/mips.c (MIPS_FTYPE_NAME1, MIPS_FTYPE_NAME2)
(MIPS_FTYPE_NAME3, MIPS_FTYPE_NAME4): New macros. (MIPS_FTYPE_NAME3, MIPS_FTYPE_NAME4): New macros.
...@@ -239,21 +239,44 @@ static const char *const mips_fp_conditions[] = { ...@@ -239,21 +239,44 @@ static const char *const mips_fp_conditions[] = {
struct mips_frame_info GTY(()) struct mips_frame_info GTY(())
{ {
HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ /* The size of the frame in bytes. */
HOST_WIDE_INT var_size; /* # bytes that variables take up */ HOST_WIDE_INT total_size;
HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */
HOST_WIDE_INT cprestore_size; /* # bytes that the .cprestore slot takes up */ /* The number of bytes allocated to variables. */
HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */ HOST_WIDE_INT var_size;
HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */
unsigned int mask; /* mask of saved gp registers */ /* The number of bytes allocated to outgoing function arguments. */
unsigned int fmask; /* mask of saved fp registers */ HOST_WIDE_INT args_size;
HOST_WIDE_INT gp_save_offset; /* offset from vfp to store gp registers */
HOST_WIDE_INT fp_save_offset; /* offset from vfp to store fp registers */ /* The number of bytes allocated to the .cprestore slot, or 0 if there
HOST_WIDE_INT gp_sp_offset; /* offset from new sp to store gp registers */ is no such slot. */
HOST_WIDE_INT fp_sp_offset; /* offset from new sp to store fp registers */ HOST_WIDE_INT cprestore_size;
bool initialized; /* true if frame size already calculated */
int num_gp; /* number of gp registers saved */ /* The size in bytes of the GPR and FPR save areas. */
int num_fp; /* number of fp registers saved */ HOST_WIDE_INT gp_reg_size;
HOST_WIDE_INT fp_reg_size;
/* Bit X is set if the function saves or restores GPR X. */
unsigned int mask;
/* Likewise FPR X. */
unsigned int fmask;
/* The number of GPRs and FPRs saved. */
unsigned int num_gp;
unsigned int num_fp;
/* The offset of the topmost GPR and FPR save slots from the top of
the frame, or zero if no such slots are needed. */
HOST_WIDE_INT gp_save_offset;
HOST_WIDE_INT fp_save_offset;
/* Likewise, but giving offsets from the bottom of the frame. */
HOST_WIDE_INT gp_sp_offset;
HOST_WIDE_INT fp_sp_offset;
/* True if this structure has been initialized after reload. */
bool initialized;
}; };
struct machine_function GTY(()) { struct machine_function GTY(()) {
...@@ -7249,14 +7272,14 @@ mips16e_find_first_register (unsigned int mask, const unsigned char *regs, ...@@ -7249,14 +7272,14 @@ mips16e_find_first_register (unsigned int mask, const unsigned char *regs,
return i; return i;
} }
/* *MASK_PTR is a mask of general purpose registers and *GP_REG_SIZE_PTR /* *MASK_PTR is a mask of general-purpose registers and *NUM_REGS_PTR
is the number of bytes that they occupy. If *MASK_PTR contains REGS[X] is the number of set bits. If *MASK_PTR contains REGS[X] for some X
for some X in [0, SIZE), adjust *MASK_PTR and *GP_REG_SIZE_PTR so that in [0, SIZE), adjust *MASK_PTR and *NUM_REGS_PTR so that the same
the same is true for all indexes (X, SIZE). */ is true for all indexes (X, SIZE). */
static void static void
mips16e_mask_registers (unsigned int *mask_ptr, const unsigned char *regs, mips16e_mask_registers (unsigned int *mask_ptr, const unsigned char *regs,
unsigned int size, HOST_WIDE_INT *gp_reg_size_ptr) unsigned int size, unsigned int *num_regs_ptr)
{ {
unsigned int i; unsigned int i;
...@@ -7264,7 +7287,7 @@ mips16e_mask_registers (unsigned int *mask_ptr, const unsigned char *regs, ...@@ -7264,7 +7287,7 @@ mips16e_mask_registers (unsigned int *mask_ptr, const unsigned char *regs,
for (i++; i < size; i++) for (i++; i < size; i++)
if (!BITSET_P (*mask_ptr, regs[i])) if (!BITSET_P (*mask_ptr, regs[i]))
{ {
*gp_reg_size_ptr += GET_MODE_SIZE (gpr_mode); *num_regs_ptr += 1;
*mask_ptr |= 1 << regs[i]; *mask_ptr |= 1 << regs[i];
} }
} }
...@@ -7507,8 +7530,8 @@ bool ...@@ -7507,8 +7530,8 @@ bool
mips16e_save_restore_pattern_p (rtx pattern, HOST_WIDE_INT adjust, mips16e_save_restore_pattern_p (rtx pattern, HOST_WIDE_INT adjust,
struct mips16e_save_restore_info *info) struct mips16e_save_restore_info *info)
{ {
unsigned int i, nargs, mask; unsigned int i, nargs, mask, extra;
HOST_WIDE_INT top_offset, save_offset, offset, extra; HOST_WIDE_INT top_offset, save_offset, offset;
rtx set, reg, mem, base; rtx set, reg, mem, base;
int n; int n;
...@@ -7816,116 +7839,117 @@ mips_save_reg_p (unsigned int regno) ...@@ -7816,116 +7839,117 @@ mips_save_reg_p (unsigned int regno)
MIPS stack frames look like: MIPS stack frames look like:
Before call After call +-------------------------------+
high +-----------------------+ +-----------------------+ | |
mem. | | | | | incoming stack arguments |
| caller's temps. | | caller's temps. | | |
| | | | +-------------------------------+
+-----------------------+ +-----------------------+ | |
| | | | | caller-allocated save area |
| arguments on stack. | | arguments on stack. | A | for register arguments |
| | | | | |
+-----------------------+ +-----------------------+ +-------------------------------+ <-- incoming stack pointer
| 4 words to save | | 4 words to save | | |
| arguments passed | | arguments passed | | callee-allocated save area |
| in registers, even | | in registers, even | B | for arguments that are |
| if not passed. | | if not passed. | | split between registers and |
SP->+-----------------------+ VFP->+-----------------------+ | the stack |
(VFP = SP+fp_sp_offset) | |\ | |
| fp register save | | fp_reg_size +-------------------------------+ <-- arg_pointer_rtx
| |/ | |
SP+gp_sp_offset->+-----------------------+ C | callee-allocated save area |
/| |\ | for register varargs |
| | gp register save | | gp_reg_size | |
gp_reg_rounded | | |/ +-------------------------------+ <-- frame_pointer_rtx + fp_sp_offset
| +-----------------------+ | | + UNITS_PER_HWFPVALUE
\| alignment padding | | FPR save area |
+-----------------------+ | |
| |\ +-------------------------------+ <-- frame_pointer_rtx + gp_sp_offset
| | + UNITS_PER_WORD
| GPR save area |
| |
+-------------------------------+
| | \
| local variables | | var_size | local variables | | var_size
| |/ | | /
+-----------------------+ +-------------------------------+
| | \
| $gp save area | | cprestore_size
| | /
P +-------------------------------+ <-- hard_frame_pointer_rtx for
| | MIPS16 code
| outgoing stack arguments |
| |
+-------------------------------+
| | | |
| alloca allocations | | caller-allocated save area |
| for register arguments |
| | | |
+-----------------------+ +-------------------------------+ <-- stack_pointer_rtx
/| | frame_pointer_rtx
cprestore_size | | GP save for V.4 abi | hard_frame_pointer_rtx for
\| | non-MIPS16 code.
+-----------------------+
| |\ At least two of A, B and C will be empty.
| arguments on stack | |
| | | Dynamic stack allocations such as alloca insert data at point P.
+-----------------------+ | They decrease stack_pointer_rtx but leave frame_pointer_rtx and
| 4 words to save | | args_size hard_frame_pointer_rtx unchanged. */
| arguments passed | |
| in registers, even | |
| if not passed. | |
low | (TARGET_OLDABI only) |/
memory SP->+-----------------------+
*/
HOST_WIDE_INT HOST_WIDE_INT
compute_frame_size (HOST_WIDE_INT size) compute_frame_size (HOST_WIDE_INT size)
{ {
unsigned int regno; struct mips_frame_info *frame;
HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ HOST_WIDE_INT offset;
HOST_WIDE_INT var_size; /* # bytes that variables take up */ unsigned int regno, i;
HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */
HOST_WIDE_INT cprestore_size; /* # bytes that the cprestore slot takes up */
HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding */
HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */
HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */
unsigned int mask; /* mask of saved gp registers */
unsigned int fmask; /* mask of saved fp registers */
cfun->machine->global_pointer = mips_global_pointer ();
gp_reg_size = 0; frame = &cfun->machine->frame;
fp_reg_size = 0; memset (frame, 0, sizeof (*frame));
mask = 0;
fmask = 0;
var_size = MIPS_STACK_ALIGN (size);
args_size = current_function_outgoing_args_size;
cprestore_size = MIPS_STACK_ALIGN (STARTING_FRAME_OFFSET) - args_size;
/* The space set aside by STARTING_FRAME_OFFSET isn't needed in leaf cfun->machine->global_pointer = mips_global_pointer ();
functions. If the function has local variables, we're committed
to allocating it anyway. Otherwise reclaim it here. */
if (var_size == 0 && current_function_is_leaf)
cprestore_size = args_size = 0;
/* The first STARTING_FRAME_OFFSET bytes contain the outgoing argument
area and the $gp save slot. This area isn't needed in leaf functions,
but if the target-independent frame size is nonzero, we're committed
to allocating it anyway. */
if (size == 0 && current_function_is_leaf)
{
/* The MIPS 3.0 linker does not like functions that dynamically /* The MIPS 3.0 linker does not like functions that dynamically
allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
looks like we are trying to create a second frame pointer to the looks like we are trying to create a second frame pointer to the
function, so allocate some stack space to make it happy. */ function, so allocate some stack space to make it happy. */
if (current_function_calls_alloca)
frame->args_size = REG_PARM_STACK_SPACE (cfun->decl);
else
frame->args_size = 0;
frame->cprestore_size = 0;
}
else
{
frame->args_size = current_function_outgoing_args_size;
frame->cprestore_size = STARTING_FRAME_OFFSET - frame->args_size;
}
offset = frame->args_size + frame->cprestore_size;
if (args_size == 0 && current_function_calls_alloca) /* Move above the local variables. */
args_size = 4 * UNITS_PER_WORD; frame->var_size = MIPS_STACK_ALIGN (size);
offset += frame->var_size;
total_size = var_size + args_size + cprestore_size;
/* Calculate space needed for gp registers. */ /* Find out which GPRs we need to save. */
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (mips_save_reg_p (regno)) if (mips_save_reg_p (regno))
{ {
gp_reg_size += GET_MODE_SIZE (gpr_mode); frame->num_gp++;
mask |= 1 << (regno - GP_REG_FIRST); frame->mask |= 1 << (regno - GP_REG_FIRST);
} }
/* We need to restore these for the handler. */ /* If this function calls eh_return, we must also save and restore the
EH data registers. */
if (current_function_calls_eh_return) if (current_function_calls_eh_return)
for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
{ {
unsigned int i; frame->num_gp++;
for (i = 0; ; ++i) frame->mask |= 1 << (EH_RETURN_DATA_REGNO (i) - GP_REG_FIRST);
{
regno = EH_RETURN_DATA_REGNO (i);
if (regno == INVALID_REGNUM)
break;
gp_reg_size += GET_MODE_SIZE (gpr_mode);
mask |= 1 << (regno - GP_REG_FIRST);
}
} }
/* The MIPS16e SAVE and RESTORE instructions have two ranges of registers: /* The MIPS16e SAVE and RESTORE instructions have two ranges of registers:
...@@ -7933,86 +7957,53 @@ compute_frame_size (HOST_WIDE_INT size) ...@@ -7933,86 +7957,53 @@ compute_frame_size (HOST_WIDE_INT size)
save all later registers too. */ save all later registers too. */
if (GENERATE_MIPS16E_SAVE_RESTORE) if (GENERATE_MIPS16E_SAVE_RESTORE)
{ {
mips16e_mask_registers (&mask, mips16e_s2_s8_regs, mips16e_mask_registers (&frame->mask, mips16e_s2_s8_regs,
ARRAY_SIZE (mips16e_s2_s8_regs), &gp_reg_size); ARRAY_SIZE (mips16e_s2_s8_regs), &frame->num_gp);
mips16e_mask_registers (&mask, mips16e_a0_a3_regs, mips16e_mask_registers (&frame->mask, mips16e_a0_a3_regs,
ARRAY_SIZE (mips16e_a0_a3_regs), &gp_reg_size); ARRAY_SIZE (mips16e_a0_a3_regs), &frame->num_gp);
} }
/* This loop must iterate over the same space as its companion in /* Move above the GPR save area. */
mips_for_each_saved_reg. */ if (frame->num_gp > 0)
if (TARGET_HARD_FLOAT)
for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1);
regno >= FP_REG_FIRST;
regno -= MAX_FPRS_PER_FMT)
if (mips_save_reg_p (regno))
{ {
fp_reg_size += MAX_FPRS_PER_FMT * UNITS_PER_FPREG; frame->gp_reg_size = frame->num_gp * UNITS_PER_WORD;
fmask |= ((1 << MAX_FPRS_PER_FMT) - 1) << (regno - FP_REG_FIRST); offset += MIPS_STACK_ALIGN (frame->gp_reg_size);
frame->gp_sp_offset = offset - UNITS_PER_WORD;
} }
gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size); /* Find out which FPRs we need to save. This loop must iterate over
total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size); the same space as its companion in mips_for_each_saved_reg. */
if (TARGET_HARD_FLOAT)
/* Add in the space required for saving incoming register arguments. */ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += MAX_FPRS_PER_FMT)
total_size += current_function_pretend_args_size; if (mips_save_reg_p (regno))
total_size += MIPS_STACK_ALIGN (cfun->machine->varargs_size);
/* Save other computed information. */
cfun->machine->frame.total_size = total_size;
cfun->machine->frame.var_size = var_size;
cfun->machine->frame.args_size = args_size;
cfun->machine->frame.cprestore_size = cprestore_size;
cfun->machine->frame.gp_reg_size = gp_reg_size;
cfun->machine->frame.fp_reg_size = fp_reg_size;
cfun->machine->frame.mask = mask;
cfun->machine->frame.fmask = fmask;
cfun->machine->frame.initialized = reload_completed;
cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
cfun->machine->frame.num_fp = (fp_reg_size
/ (MAX_FPRS_PER_FMT * UNITS_PER_FPREG));
if (mask)
{ {
HOST_WIDE_INT offset; frame->num_fp += MAX_FPRS_PER_FMT;
frame->fmask |= ~(~0 << MAX_FPRS_PER_FMT) << (regno - FP_REG_FIRST);
if (GENERATE_MIPS16E_SAVE_RESTORE)
/* MIPS16e SAVE and RESTORE instructions require the GP save area
to be aligned at the high end with any padding at the low end.
It is only safe to use this calculation for o32, where we never
have pretend arguments, and where any varargs will be saved in
the caller-allocated area rather than at the top of the frame. */
offset = (total_size - GET_MODE_SIZE (gpr_mode));
else
offset = (args_size + cprestore_size + var_size
+ gp_reg_size - GET_MODE_SIZE (gpr_mode));
cfun->machine->frame.gp_sp_offset = offset;
cfun->machine->frame.gp_save_offset = offset - total_size;
} }
else
/* Move above the FPR save area. */
if (frame->num_fp > 0)
{ {
cfun->machine->frame.gp_sp_offset = 0; frame->fp_reg_size = frame->num_fp * UNITS_PER_FPREG;
cfun->machine->frame.gp_save_offset = 0; offset += MIPS_STACK_ALIGN (frame->fp_reg_size);
frame->fp_sp_offset = offset - UNITS_PER_HWFPVALUE;
} }
if (fmask) /* Move above the callee-allocated varargs save area. */
{ offset += MIPS_STACK_ALIGN (cfun->machine->varargs_size);
HOST_WIDE_INT offset;
offset = (args_size + cprestore_size + var_size /* Move above the callee-allocated area for pretend stack arguments. */
+ gp_reg_rounded + fp_reg_size offset += current_function_pretend_args_size;
- MAX_FPRS_PER_FMT * UNITS_PER_FPREG); frame->total_size = offset;
cfun->machine->frame.fp_sp_offset = offset;
cfun->machine->frame.fp_save_offset = offset - total_size; /* Work out the offsets of the save areas from the top of the frame. */
} if (frame->gp_sp_offset > 0)
else frame->gp_save_offset = frame->gp_sp_offset - offset;
{ if (frame->fp_sp_offset > 0)
cfun->machine->frame.fp_sp_offset = 0; frame->fp_save_offset = frame->fp_sp_offset - offset;
cfun->machine->frame.fp_save_offset = 0;
}
/* Ok, we're done. */ frame->initialized = reload_completed;
return total_size; return frame->total_size;
} }
/* Return the style of GP load sequence that is being used for the /* Return the style of GP load sequence that is being used for the
......
...@@ -1885,21 +1885,10 @@ enum reg_class ...@@ -1885,21 +1885,10 @@ enum reg_class
#define STACK_GROWS_DOWNWARD #define STACK_GROWS_DOWNWARD
/* The offset of the first local variable from the beginning of the frame. /* The offset of the first local variable from the beginning of the frame.
See compute_frame_size for details about the frame layout. See compute_frame_size for details about the frame layout. */
??? If flag_profile_values is true, and we are generating 32-bit code, then
we assume that we will need 16 bytes of argument space. This is because
the value profiling code may emit calls to cmpdi2 in leaf functions.
Without this hack, the local variables will start at sp+8 and the gp save
area will be at sp+16, and thus they will overlap. compute_frame_size is
OK because it uses STARTING_FRAME_OFFSET to compute cprestore_size, which
will end up as 24 instead of 8. This won't be needed if profiling code is
inserted before virtual register instantiation. */
#define STARTING_FRAME_OFFSET \ #define STARTING_FRAME_OFFSET \
((flag_profile_values && ! TARGET_64BIT \ (current_function_outgoing_args_size \
? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \
: current_function_outgoing_args_size) \
+ (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)) + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
#define RETURN_ADDR_RTX mips_return_addr #define RETURN_ADDR_RTX mips_return_addr
......
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