From d1d0c603c48e38c8b0c25cf78427e5b0475419f1 Mon Sep 17 00:00:00 2001 From: Janis Johnson Date: Wed, 12 Nov 2003 22:52:09 +0000 Subject: [PATCH] rs6000-protos.h (rs6000_initial_elimination_offset): Add. 2003-11-12 Janis Johnson * rs6000-protos.h (rs6000_initial_elimination_offset): Add. (rs6000_stack_info): Remove. (debug_stack_info): Remove. (rs6000_emit_eh_reg_restore): Add * rs6000.c (rs6000_stack_t): Move from rs6000.h, change data type of vars_size and total_size to HOST_WIDE_INT. (emit_frame_save): Change parameter size to HOST_WIDE_INT. (rs6000_stack_info): Make static; change data size to HOST_WIDE_INT. (debug_stack_info): Make static; change output format of HOST_WIDE_INT values. (rs6000_emit_eh_reg_restore): New, with code formerly in rs6000.md. (rs6000_initial_elimination_offset): New, with code formerly in INITIAL_ELIMINATION_OFFSET. * rs6000.h (rs6000_stack_t): Remove. (INITIAL_ELIMINATION_OFFSET): Replace code with call to function rs6000_initial_elimination_offset. * rs6000.md (UNSPECV_EH_RR split): Replace code with call to rs6000_emit_eh_reg_restore. From-SVN: r73517 --- gcc/ChangeLog | 20 +++++ gcc/config/rs6000/rs6000-protos.h | 4 +- gcc/config/rs6000/rs6000.c | 119 ++++++++++++++++++++++++++++-- gcc/config/rs6000/rs6000.h | 60 +-------------- gcc/config/rs6000/rs6000.md | 25 +------ 5 files changed, 137 insertions(+), 91 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d3820e46c9f9..dfb51cfea704 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2003-11-12 Janis Johnson + + * rs6000-protos.h (rs6000_initial_elimination_offset): Add. + (rs6000_stack_info): Remove. (debug_stack_info): Remove. + (rs6000_emit_eh_reg_restore): Add + * rs6000.c (rs6000_stack_t): Move from rs6000.h, change data type + of vars_size and total_size to HOST_WIDE_INT. + (emit_frame_save): Change parameter size to HOST_WIDE_INT. + (rs6000_stack_info): Make static; change data size to HOST_WIDE_INT. + (debug_stack_info): Make static; change output format of HOST_WIDE_INT + values. + (rs6000_emit_eh_reg_restore): New, with code formerly in rs6000.md. + (rs6000_initial_elimination_offset): New, with code formerly in + INITIAL_ELIMINATION_OFFSET. + * rs6000.h (rs6000_stack_t): Remove. + (INITIAL_ELIMINATION_OFFSET): Replace code with call to function + rs6000_initial_elimination_offset. + * rs6000.md (UNSPECV_EH_RR split): Replace code with call to + rs6000_emit_eh_reg_restore. + 2003-11-12 Mike Stump * c-typeck.c (c_convert_parm_for_inlining): Add argnum, which diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 2f50d1ef7ba9..ed13c34955fe 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -134,6 +134,7 @@ extern int rs6000_legitimate_address (enum machine_mode, rtx, int); extern bool rs6000_mode_dependent_address (rtx); extern rtx rs6000_return_addr (int, rtx); extern void rs6000_output_symbol_ref (FILE*, rtx); +extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int); extern rtx rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg); @@ -168,7 +169,6 @@ extern void rs6000_override_options (const char *); extern int direct_return (void); extern int first_reg_to_save (void); extern int first_fp_reg_to_save (void); -extern rs6000_stack_t *rs6000_stack_info (void); extern void output_ascii (FILE *, const char *, int); extern void rs6000_gen_section_name (char **, const char *, const char *); extern void output_function_profiler (FILE *, int); @@ -187,7 +187,7 @@ extern void rs6000_emit_prologue (void); extern void rs6000_emit_load_toc_table (int); extern void rs6000_aix_emit_builtin_unwind_init (void); extern void rs6000_emit_epilogue (int); -extern void debug_stack_info (rs6000_stack_t *); +extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern const char * output_isel (rtx *); extern int vrsave_operation (rtx, enum machine_mode); extern int rs6000_register_move_cost (enum machine_mode, diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ccbf2158882a..5ca78420a6b8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -70,6 +70,49 @@ #define min(A,B) ((A) < (B) ? (A) : (B)) #define max(A,B) ((A) > (B) ? (A) : (B)) +/* Structure used to define the rs6000 stack */ +typedef struct rs6000_stack { + int first_gp_reg_save; /* first callee saved GP register used */ + int first_fp_reg_save; /* first callee saved FP register used */ + int first_altivec_reg_save; /* first callee saved AltiVec register used */ + int lr_save_p; /* true if the link reg needs to be saved */ + int cr_save_p; /* true if the CR reg needs to be saved */ + unsigned int vrsave_mask; /* mask of vec registers to save */ + int toc_save_p; /* true if the TOC needs to be saved */ + int push_p; /* true if we need to allocate stack space */ + int calls_p; /* true if the function makes any calls */ + enum rs6000_abi abi; /* which ABI to use */ + int gp_save_offset; /* offset to save GP regs from initial SP */ + int fp_save_offset; /* offset to save FP regs from initial SP */ + int altivec_save_offset; /* offset to save AltiVec regs from initial SP */ + int lr_save_offset; /* offset to save LR from initial SP */ + int cr_save_offset; /* offset to save CR from initial SP */ + int vrsave_save_offset; /* offset to save VRSAVE from initial SP */ + int spe_gp_save_offset; /* offset to save spe 64-bit gprs */ + int toc_save_offset; /* offset to save the TOC pointer */ + int varargs_save_offset; /* offset to save the varargs registers */ + int ehrd_offset; /* offset to EH return data */ + int reg_size; /* register size (4 or 8) */ + int varargs_size; /* size to hold V.4 args passed in regs */ + HOST_WIDE_INT vars_size; /* variable save area size */ + int parm_size; /* outgoing parameter size */ + int save_size; /* save area size */ + int fixed_size; /* fixed size of stack frame */ + int gp_size; /* size of saved GP registers */ + int fp_size; /* size of saved FP registers */ + int altivec_size; /* size of saved AltiVec registers */ + int cr_size; /* size to hold CR if not in save_size */ + int lr_size; /* size to hold LR if not in save_size */ + int vrsave_size; /* size to hold VRSAVE if not in save_size */ + int altivec_padding_size; /* size of altivec alignment padding if + not in save_size */ + int spe_gp_size; /* size of 64-bit GPR save size for SPE */ + int spe_padding_size; + int toc_size; /* size to hold TOC if not in save_size */ + HOST_WIDE_INT total_size; /* total bytes allocated for stack */ + int spe_64bit_regs_used; +} rs6000_stack_t; + /* Target cpu type */ enum processor_type rs6000_cpu; @@ -222,7 +265,7 @@ static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx); static rtx spe_synthesize_frame_save (rtx); static bool spe_func_has_64bit_regs_p (void); static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int, - int, int); + int, HOST_WIDE_INT); static rtx gen_frame_mem_offset (enum machine_mode, rtx, int); static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int); static unsigned rs6000_hash_constant (rtx); @@ -317,6 +360,8 @@ static rtx spe_expand_builtin (tree, rtx, bool *); static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx); static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx); static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx); +static rs6000_stack_t *rs6000_stack_info (void); +static void debug_stack_info (rs6000_stack_t *); static rtx altivec_expand_builtin (tree, rtx, bool *); static rtx altivec_expand_ld_builtin (tree, rtx, bool *); @@ -10269,14 +10314,14 @@ is_altivec_return_reg (rtx reg, void *xyes) #define ABI_STACK_BOUNDARY STACK_BOUNDARY #endif -rs6000_stack_t * +static rs6000_stack_t * rs6000_stack_info (void) { static rs6000_stack_t info, zero_info; rs6000_stack_t *info_ptr = &info; int reg_size = TARGET_POWERPC64 ? 8 : 4; int ehrd_size; - int total_raw_size; + HOST_WIDE_INT total_raw_size; /* Zero all fields portably. */ info = zero_info; @@ -10608,7 +10653,7 @@ spe_func_has_64bit_regs_p (void) return false; } -void +static void debug_stack_info (rs6000_stack_t *info) { const char *abi_string; @@ -10697,13 +10742,15 @@ debug_stack_info (rs6000_stack_t *info) fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset); if (info->total_size) - fprintf (stderr, "\ttotal_size = %5d\n", info->total_size); + fprintf (stderr, "\ttotal_size = "HOST_WIDE_INT_PRINT_DEC"\n", + info->total_size); if (info->varargs_size) fprintf (stderr, "\tvarargs_size = %5d\n", info->varargs_size); if (info->vars_size) - fprintf (stderr, "\tvars_size = %5d\n", info->vars_size); + fprintf (stderr, "\tvars_size = "HOST_WIDE_INT_PRINT_DEC"\n", + info->vars_size); if (info->parm_size) fprintf (stderr, "\tparm_size = %5d\n", info->parm_size); @@ -10976,6 +11023,42 @@ rs6000_emit_load_toc_table (int fromprolog) abort (); } +/* Emit instructions to restore the link register after determining where + its value has been stored. */ + +void +rs6000_emit_eh_reg_restore (rtx source, rtx scratch) +{ + rs6000_stack_t *info = rs6000_stack_info (); + rtx operands[2]; + + operands[0] = source; + operands[1] = scratch; + + if (info->lr_save_p) + { + rtx frame_rtx = stack_pointer_rtx; + HOST_WIDE_INT sp_offset = 0; + rtx tmp; + + if (frame_pointer_needed + || current_function_calls_alloca + || info->total_size > 32767) + { + emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx)); + frame_rtx = operands[1]; + } + else if (info->push_p) + sp_offset = info->total_size; + + tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset); + tmp = gen_rtx_MEM (Pmode, tmp); + emit_move_insn (tmp, operands[0]); + } + else + emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]); +} + int get_TOC_alias_set (void) { @@ -11374,7 +11457,7 @@ generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep) static void emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode, - unsigned int regno, int offset, int total_size) + unsigned int regno, int offset, HOST_WIDE_INT total_size) { rtx reg, offset_rtx, insn, mem, addr, int_rtx; rtx replacea, replaceb; @@ -15575,6 +15658,28 @@ rs6000_libcall_value (enum machine_mode mode) return gen_rtx_REG (mode, regno); } +/* Define the offset between two registers, FROM to be eliminated and its + replacement TO, at the start of a routine. */ +HOST_WIDE_INT +rs6000_initial_elimination_offset (int from, int to) +{ + rs6000_stack_t *info = rs6000_stack_info (); + HOST_WIDE_INT offset; + + if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + offset = info->push_p ? 0 : -info->total_size; + else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) + offset = info->total_size; + else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + offset = info->push_p ? info->total_size : 0; + else if (from == RS6000_PIC_OFFSET_TABLE_REGNUM) + offset = 0; + else + abort (); + + return offset; +} + /* Return true if TYPE is of type __ev64_opaque__. */ static bool diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 37d851b3c4f2..2e93b8aa06d6 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1491,49 +1491,6 @@ enum rs6000_abi { extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */ -/* Structure used to define the rs6000 stack */ -typedef struct rs6000_stack { - int first_gp_reg_save; /* first callee saved GP register used */ - int first_fp_reg_save; /* first callee saved FP register used */ - int first_altivec_reg_save; /* first callee saved AltiVec register used */ - int lr_save_p; /* true if the link reg needs to be saved */ - int cr_save_p; /* true if the CR reg needs to be saved */ - unsigned int vrsave_mask; /* mask of vec registers to save */ - int toc_save_p; /* true if the TOC needs to be saved */ - int push_p; /* true if we need to allocate stack space */ - int calls_p; /* true if the function makes any calls */ - enum rs6000_abi abi; /* which ABI to use */ - int gp_save_offset; /* offset to save GP regs from initial SP */ - int fp_save_offset; /* offset to save FP regs from initial SP */ - int altivec_save_offset; /* offset to save AltiVec regs from initial SP */ - int lr_save_offset; /* offset to save LR from initial SP */ - int cr_save_offset; /* offset to save CR from initial SP */ - int vrsave_save_offset; /* offset to save VRSAVE from initial SP */ - int spe_gp_save_offset; /* offset to save spe 64-bit gprs */ - int toc_save_offset; /* offset to save the TOC pointer */ - int varargs_save_offset; /* offset to save the varargs registers */ - int ehrd_offset; /* offset to EH return data */ - int reg_size; /* register size (4 or 8) */ - int varargs_size; /* size to hold V.4 args passed in regs */ - int vars_size; /* variable save area size */ - int parm_size; /* outgoing parameter size */ - int save_size; /* save area size */ - int fixed_size; /* fixed size of stack frame */ - int gp_size; /* size of saved GP registers */ - int fp_size; /* size of saved FP registers */ - int altivec_size; /* size of saved AltiVec registers */ - int cr_size; /* size to hold CR if not in save_size */ - int lr_size; /* size to hold LR if not in save_size */ - int vrsave_size; /* size to hold VRSAVE if not in save_size */ - int altivec_padding_size; /* size of altivec alignment padding if - not in save_size */ - int spe_gp_size; /* size of 64-bit GPR save size for SPE */ - int spe_padding_size; - int toc_size; /* size to hold TOC if not in save_size */ - int total_size; /* total bytes allocated for stack */ - int spe_64bit_regs_used; -} rs6000_stack_t; - /* Define this if pushing a word on the stack makes the stack pointer a smaller address. */ #define STACK_GROWS_DOWNWARD @@ -1984,21 +1941,8 @@ typedef struct rs6000_args /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - rs6000_stack_t *info = rs6000_stack_info (); \ - \ - if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = (info->push_p) ? 0 : - info->total_size; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ - (OFFSET) = info->total_size; \ - else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ - (OFFSET) = (info->push_p) ? info->total_size : 0; \ - else if ((FROM) == RS6000_PIC_OFFSET_TABLE_REGNUM) \ - (OFFSET) = 0; \ - else \ - abort (); \ -} +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + ((OFFSET) = rs6000_initial_elimination_offset(FROM, TO)) /* Addressing modes, and classification of registers for them. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 57d569482fa0..1c7f38b03477 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14684,30 +14684,7 @@ [(const_int 0)] " { - rs6000_stack_t *info = rs6000_stack_info (); - - if (info->lr_save_p) - { - rtx frame_rtx = stack_pointer_rtx; - int sp_offset = 0; - rtx tmp; - - if (frame_pointer_needed - || current_function_calls_alloca - || info->total_size > 32767) - { - emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx)); - frame_rtx = operands[1]; - } - else if (info->push_p) - sp_offset = info->total_size; - - tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset); - tmp = gen_rtx_MEM (Pmode, tmp); - emit_move_insn (tmp, operands[0]); - } - else - emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]); + rs6000_emit_eh_reg_restore (operands[0], operands[1]); DONE; }") -- 2.39.5