From 37017f4dd64886a2c6164d1c2d01cf4bb72238b6 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 18 Oct 2007 19:26:20 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 13 ++ gcc/config/mips/mips.c | 365 ++++++++++++++++++++--------------------- gcc/config/mips/mips.h | 15 +- 3 files changed, 193 insertions(+), 200 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b76c4cef46b..c372a59db8d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2007-10-18 Richard Sandiford + + * 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 * config/mips/mips-ftypes.def: New file. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 77bd08ebcf4..f25305bd618 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -239,21 +239,44 @@ static const char *const mips_fp_conditions[] = { struct mips_frame_info GTY(()) { - HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ - HOST_WIDE_INT var_size; /* # bytes that variables take up */ - 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_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 */ - 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 */ - HOST_WIDE_INT gp_sp_offset; /* offset from new sp to store gp registers */ - HOST_WIDE_INT fp_sp_offset; /* offset from new sp to store fp registers */ - bool initialized; /* true if frame size already calculated */ - int num_gp; /* number of gp registers saved */ - int num_fp; /* number of fp registers saved */ + /* The size of the frame in bytes. */ + HOST_WIDE_INT total_size; + + /* The number of bytes allocated to variables. */ + HOST_WIDE_INT var_size; + + /* The number of bytes allocated to outgoing function arguments. */ + HOST_WIDE_INT args_size; + + /* The number of bytes allocated to the .cprestore slot, or 0 if there + is no such slot. */ + HOST_WIDE_INT cprestore_size; + + /* The size in bytes of the GPR and FPR save areas. */ + 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(()) { @@ -7249,14 +7272,14 @@ mips16e_find_first_register (unsigned int mask, const unsigned char *regs, return i; } -/* *MASK_PTR is a mask of general purpose registers and *GP_REG_SIZE_PTR - is the number of bytes that they occupy. If *MASK_PTR contains REGS[X] - for some X in [0, SIZE), adjust *MASK_PTR and *GP_REG_SIZE_PTR so that - the same is true for all indexes (X, SIZE). */ +/* *MASK_PTR is a mask of general-purpose registers and *NUM_REGS_PTR + is the number of set bits. If *MASK_PTR contains REGS[X] for some X + in [0, SIZE), adjust *MASK_PTR and *NUM_REGS_PTR so that the same + is true for all indexes (X, SIZE). */ static void 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; @@ -7264,7 +7287,7 @@ mips16e_mask_registers (unsigned int *mask_ptr, const unsigned char *regs, for (i++; i < size; 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]; } } @@ -7507,8 +7530,8 @@ bool mips16e_save_restore_pattern_p (rtx pattern, HOST_WIDE_INT adjust, struct mips16e_save_restore_info *info) { - unsigned int i, nargs, mask; - HOST_WIDE_INT top_offset, save_offset, offset, extra; + unsigned int i, nargs, mask, extra; + HOST_WIDE_INT top_offset, save_offset, offset; rtx set, reg, mem, base; int n; @@ -7816,203 +7839,171 @@ mips_save_reg_p (unsigned int regno) MIPS stack frames look like: - Before call After call - high +-----------------------+ +-----------------------+ - mem. | | | | - | caller's temps. | | caller's temps. | - | | | | - +-----------------------+ +-----------------------+ - | | | | - | arguments on stack. | | arguments on stack. | - | | | | - +-----------------------+ +-----------------------+ - | 4 words to save | | 4 words to save | - | arguments passed | | arguments passed | - | in registers, even | | in registers, even | - | if not passed. | | if not passed. | - SP->+-----------------------+ VFP->+-----------------------+ - (VFP = SP+fp_sp_offset) | |\ - | fp register save | | fp_reg_size - | |/ - SP+gp_sp_offset->+-----------------------+ - /| |\ - | | gp register save | | gp_reg_size - gp_reg_rounded | | |/ - | +-----------------------+ - \| alignment padding | - +-----------------------+ - | |\ - | local variables | | var_size - | |/ - +-----------------------+ - | | - | alloca allocations | - | | - +-----------------------+ - /| | - cprestore_size | | GP save for V.4 abi | - \| | - +-----------------------+ - | |\ - | arguments on stack | | - | | | - +-----------------------+ | - | 4 words to save | | args_size - | arguments passed | | - | in registers, even | | - | if not passed. | | - low | (TARGET_OLDABI only) |/ - memory SP->+-----------------------+ - -*/ + +-------------------------------+ + | | + | incoming stack arguments | + | | + +-------------------------------+ + | | + | caller-allocated save area | + A | for register arguments | + | | + +-------------------------------+ <-- incoming stack pointer + | | + | callee-allocated save area | + B | for arguments that are | + | split between registers and | + | the stack | + | | + +-------------------------------+ <-- arg_pointer_rtx + | | + C | callee-allocated save area | + | for register varargs | + | | + +-------------------------------+ <-- frame_pointer_rtx + fp_sp_offset + | | + UNITS_PER_HWFPVALUE + | FPR save area | + | | + +-------------------------------+ <-- frame_pointer_rtx + gp_sp_offset + | | + UNITS_PER_WORD + | GPR save area | + | | + +-------------------------------+ + | | \ + | local variables | | var_size + | | / + +-------------------------------+ + | | \ + | $gp save area | | cprestore_size + | | / + P +-------------------------------+ <-- hard_frame_pointer_rtx for + | | MIPS16 code + | outgoing stack arguments | + | | + +-------------------------------+ + | | + | caller-allocated save area | + | for register arguments | + | | + +-------------------------------+ <-- stack_pointer_rtx + frame_pointer_rtx + hard_frame_pointer_rtx for + non-MIPS16 code. + + At least two of A, B and C will be empty. + + Dynamic stack allocations such as alloca insert data at point P. + They decrease stack_pointer_rtx but leave frame_pointer_rtx and + hard_frame_pointer_rtx unchanged. */ HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT size) { - unsigned int regno; - HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ - HOST_WIDE_INT var_size; /* # bytes that variables take up */ - 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; - fp_reg_size = 0; - 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; + struct mips_frame_info *frame; + HOST_WIDE_INT offset; + unsigned int regno, i; - /* The space set aside by STARTING_FRAME_OFFSET isn't needed in leaf - 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; + frame = &cfun->machine->frame; + memset (frame, 0, sizeof (*frame)); - /* The MIPS 3.0 linker does not like functions that dynamically - 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 - function, so allocate some stack space to make it happy. */ + cfun->machine->global_pointer = mips_global_pointer (); - if (args_size == 0 && current_function_calls_alloca) - args_size = 4 * UNITS_PER_WORD; + /* 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 + 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 + 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; - total_size = var_size + args_size + cprestore_size; + /* Move above the local variables. */ + frame->var_size = MIPS_STACK_ALIGN (size); + offset += frame->var_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++) if (mips_save_reg_p (regno)) { - gp_reg_size += GET_MODE_SIZE (gpr_mode); - mask |= 1 << (regno - GP_REG_FIRST); + frame->num_gp++; + 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) - { - unsigned int i; - for (i = 0; ; ++i) - { - 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); - } - } + for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++) + { + frame->num_gp++; + frame->mask |= 1 << (EH_RETURN_DATA_REGNO (i) - GP_REG_FIRST); + } /* The MIPS16e SAVE and RESTORE instructions have two ranges of registers: $a3-$a0 and $s2-$s8. If we save one register in the range, we must save all later registers too. */ if (GENERATE_MIPS16E_SAVE_RESTORE) { - mips16e_mask_registers (&mask, mips16e_s2_s8_regs, - ARRAY_SIZE (mips16e_s2_s8_regs), &gp_reg_size); - mips16e_mask_registers (&mask, mips16e_a0_a3_regs, - ARRAY_SIZE (mips16e_a0_a3_regs), &gp_reg_size); + mips16e_mask_registers (&frame->mask, mips16e_s2_s8_regs, + ARRAY_SIZE (mips16e_s2_s8_regs), &frame->num_gp); + mips16e_mask_registers (&frame->mask, mips16e_a0_a3_regs, + ARRAY_SIZE (mips16e_a0_a3_regs), &frame->num_gp); } - /* This loop must iterate over the same space as its companion in - mips_for_each_saved_reg. */ + /* Move above the GPR save area. */ + if (frame->num_gp > 0) + { + frame->gp_reg_size = frame->num_gp * UNITS_PER_WORD; + offset += MIPS_STACK_ALIGN (frame->gp_reg_size); + frame->gp_sp_offset = offset - UNITS_PER_WORD; + } + + /* Find out which FPRs we need to save. This loop must iterate over + the same space as its companion in mips_for_each_saved_reg. */ if (TARGET_HARD_FLOAT) - for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1); - regno >= FP_REG_FIRST; - regno -= MAX_FPRS_PER_FMT) + for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += MAX_FPRS_PER_FMT) if (mips_save_reg_p (regno)) { - fp_reg_size += MAX_FPRS_PER_FMT * UNITS_PER_FPREG; - fmask |= ((1 << MAX_FPRS_PER_FMT) - 1) << (regno - FP_REG_FIRST); + frame->num_fp += MAX_FPRS_PER_FMT; + frame->fmask |= ~(~0 << MAX_FPRS_PER_FMT) << (regno - FP_REG_FIRST); } - gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size); - total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size); - - /* Add in the space required for saving incoming register arguments. */ - total_size += current_function_pretend_args_size; - 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; - - 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; - cfun->machine->frame.gp_save_offset = 0; + frame->fp_reg_size = frame->num_fp * UNITS_PER_FPREG; + offset += MIPS_STACK_ALIGN (frame->fp_reg_size); + frame->fp_sp_offset = offset - UNITS_PER_HWFPVALUE; } - if (fmask) - { - HOST_WIDE_INT offset; + /* Move above the callee-allocated varargs save area. */ + offset += MIPS_STACK_ALIGN (cfun->machine->varargs_size); - offset = (args_size + cprestore_size + var_size - + gp_reg_rounded + fp_reg_size - - MAX_FPRS_PER_FMT * UNITS_PER_FPREG); - cfun->machine->frame.fp_sp_offset = offset; - cfun->machine->frame.fp_save_offset = offset - total_size; - } - else - { - cfun->machine->frame.fp_sp_offset = 0; - cfun->machine->frame.fp_save_offset = 0; - } + /* Move above the callee-allocated area for pretend stack arguments. */ + offset += current_function_pretend_args_size; + frame->total_size = offset; + + /* Work out the offsets of the save areas from the top of the frame. */ + if (frame->gp_sp_offset > 0) + frame->gp_save_offset = frame->gp_sp_offset - offset; + if (frame->fp_sp_offset > 0) + frame->fp_save_offset = frame->fp_sp_offset - offset; - /* Ok, we're done. */ - return total_size; + frame->initialized = reload_completed; + return frame->total_size; } /* Return the style of GP load sequence that is being used for the diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 2c401ec6c0c..ac4320a763e 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1885,21 +1885,10 @@ enum reg_class #define STACK_GROWS_DOWNWARD /* The offset of the first local variable from the beginning of the frame. - 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. */ + See compute_frame_size for details about the frame layout. */ #define STARTING_FRAME_OFFSET \ - ((flag_profile_values && ! TARGET_64BIT \ - ? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \ - : current_function_outgoing_args_size) \ + (current_function_outgoing_args_size \ + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0)) #define RETURN_ADDR_RTX mips_return_addr -- 2.30.2