diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2002-08-26 18:18:19 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2002-08-26 18:18:19 +0000 |
commit | c3cc6b78a1487e9c05be9770f811b79706318867 (patch) | |
tree | 9c119df126330ad4a35fad49d9f309abceb20145 /gcc | |
parent | 3f66218653d7905c186e050208545d9f8d0b020f (diff) | |
download | gcc-c3cc6b78a1487e9c05be9770f811b79706318867.zip gcc-c3cc6b78a1487e9c05be9770f811b79706318867.tar.gz gcc-c3cc6b78a1487e9c05be9770f811b79706318867.tar.bz2 |
s390-protos.h (s390_function_prologue, [...]): Remove.
* config/s390/s390-protos.h (s390_function_prologue,
s390_function_epilogue): Remove.
config/s390/s390.c (s390_function_prologue, s390_function_epilogue,
TARGET_ASM_FUNCTION_PROLOGUE, TARGET_ASM_FUNCTION_EPILOGUE): Remove.
config/s390/s390.c (s390_machine_dependent_recorg): New function.
config/s390/s390-protos.h (s390_machine_dependent_reorg): Declare it.
config/s390/s390.h (MACHINE_DEPENDENT_REORG): Call it.
config/s390/s390.c (s390_split_branches, s390_chunkify_pool): Adapt
to being called from MACHINE_DEPENDENT_REORG. Update regs_ever_live.
config/s390/s390.c (s390_frame_info): Inline save_fprs_p. Always
assume BASE_REGISTER and RETURN_REGNUM need to be saved.
(s390_emit_prologue): Assume RETURN_REGNUM to be saved iff
function is not a leaf function. Use save_gprs and restore_gprs.
(s390_emit_epilogue): Likewise.
(save_gprs, restore_gprs): New functions.
(struct s390_frame): Remove return_reg_saved_p member.
(save_fprs_p): Remove.
(s390_optimize_prolog): New function.
(s390_legitimate_reload_constant): Remove now unnecessary check.
(s390_function_count): Remove.
(s390_output_symbolic_const): Replace s390_function_count by
current_function_funcdef_no.
(s390_output_constant_pool): Likewise.
(legitimize_pic_address): Use regs_ever_live to track PIC register
instead of current_function_uses_pic_offset_table.
(s390_emit_prologue): Likewise.
config/s390/s390.md ("call", "call_value"): Likewise.
From-SVN: r56584
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 34 | ||||
-rw-r--r-- | gcc/config/s390/s390-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 511 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 11 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 10 |
5 files changed, 363 insertions, 206 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 552e434..4192aad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2002-08-26 Ulrich Weigand <uweigand@de.ibm.com> + + * config/s390/s390-protos.h (s390_function_prologue, + s390_function_epilogue): Remove. + config/s390/s390.c (s390_function_prologue, s390_function_epilogue, + TARGET_ASM_FUNCTION_PROLOGUE, TARGET_ASM_FUNCTION_EPILOGUE): Remove. + + config/s390/s390.c (s390_machine_dependent_recorg): New function. + config/s390/s390-protos.h (s390_machine_dependent_reorg): Declare it. + config/s390/s390.h (MACHINE_DEPENDENT_REORG): Call it. + config/s390/s390.c (s390_split_branches, s390_chunkify_pool): Adapt + to being called from MACHINE_DEPENDENT_REORG. Update regs_ever_live. + + config/s390/s390.c (s390_frame_info): Inline save_fprs_p. Always + assume BASE_REGISTER and RETURN_REGNUM need to be saved. + (s390_emit_prologue): Assume RETURN_REGNUM to be saved iff + function is not a leaf function. Use save_gprs and restore_gprs. + (s390_emit_epilogue): Likewise. + (save_gprs, restore_gprs): New functions. + (struct s390_frame): Remove return_reg_saved_p member. + (save_fprs_p): Remove. + (s390_optimize_prolog): New function. + (s390_legitimate_reload_constant): Remove now unnecessary check. + + (s390_function_count): Remove. + (s390_output_symbolic_const): Replace s390_function_count by + current_function_funcdef_no. + (s390_output_constant_pool): Likewise. + + (legitimize_pic_address): Use regs_ever_live to track PIC register + instead of current_function_uses_pic_offset_table. + (s390_emit_prologue): Likewise. + config/s390/s390.md ("call", "call_value"): Likewise. + 2002-08-26 Neil Booth <neil@daikokuya.co.uk> * c-opts.c (find_opt): Don't complain about wrong languages diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 38c5c0b..c44ffb3 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -24,8 +24,6 @@ Boston, MA 02111-1307, USA. */ extern void optimization_options PARAMS ((int, int)); extern void override_options PARAMS ((void)); extern int s390_arg_frame_offset PARAMS ((void)); -extern void s390_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); -extern void s390_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); extern void s390_emit_prologue PARAMS ((void)); extern void s390_emit_epilogue PARAMS ((void)); extern void s390_function_profiler PARAMS ((FILE *, int)); @@ -72,6 +70,7 @@ extern void s390_trampoline_template PARAMS ((FILE *)); extern void s390_initialize_trampoline PARAMS ((rtx, rtx, rtx)); extern rtx s390_gen_rtx_const_DI PARAMS ((int, int)); extern rtx s390_simplify_dwarf_addr PARAMS ((rtx)); +extern void s390_machine_dependent_reorg PARAMS ((rtx)); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 85952c5..6ee09c5 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -61,12 +61,6 @@ static void s390_encode_section_info PARAMS ((tree, int)); #undef TARGET_ASM_INTEGER #define TARGET_ASM_INTEGER s390_assemble_integer -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE s390_function_prologue - -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE s390_function_epilogue - #undef TARGET_ASM_OPEN_PAREN #define TARGET_ASM_OPEN_PAREN "" @@ -92,9 +86,6 @@ extern int reload_completed; /* The alias set for prologue/epilogue register save/restore. */ static int s390_sr_alias_set = 0; -/* Function count for creating unique internal labels in a compile unit. */ -int s390_function_count = 0; - /* Save information from a "cmpxx" operation until the branch or scc is emitted. */ rtx s390_compare_op0, s390_compare_op1; @@ -121,7 +112,6 @@ struct s390_address struct s390_frame { int frame_pointer_p; - int return_reg_saved_p; int save_fprs_p; int first_save_gpr; int first_restore_gpr; @@ -143,11 +133,13 @@ static void s390_split_branches PARAMS ((void)); static void find_constant_pool_ref PARAMS ((rtx, rtx *)); static void replace_constant_pool_ref PARAMS ((rtx *, rtx, rtx)); static void s390_chunkify_pool PARAMS ((void)); -static int save_fprs_p PARAMS ((void)); +static void s390_optimize_prolog PARAMS ((void)); static int find_unused_clobbered_reg PARAMS ((void)); static void s390_frame_info PARAMS ((struct s390_frame *)); static rtx save_fpr PARAMS ((rtx, int, int)); static rtx restore_fpr PARAMS ((rtx, int, int)); +static rtx save_gprs PARAMS ((rtx, int, int, int)); +static rtx restore_gprs PARAMS ((rtx, int, int, int)); static int s390_function_arg_size PARAMS ((enum machine_mode, tree)); @@ -1269,15 +1261,6 @@ legitimate_reload_constant_p (op) && larl_operand (op, VOIDmode)) return 1; - /* If reload is completed, and we do not already have a - literal pool, and OP must be forced to the literal - pool, then something must have gone wrong earlier. - We *cannot* force the constant any more, because the - prolog generation already decided we don't need to - set up the base register. */ - if (reload_completed && !regs_ever_live[BASE_REGISTER]) - abort (); - /* Everything else cannot be handled without reload. */ return 0; } @@ -1826,7 +1809,8 @@ legitimize_pic_address (orig, reg) /* Assume GOT offset < 4k. This is handled the same way in both 31- and 64-bit code (@GOT12). */ - current_function_uses_pic_offset_table = 1; + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 110); new = gen_rtx_CONST (Pmode, new); @@ -1859,7 +1843,8 @@ legitimize_pic_address (orig, reg) rtx temp = gen_reg_rtx (Pmode); - current_function_uses_pic_offset_table = 1; + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 112); addr = gen_rtx_CONST (SImode, addr); @@ -2218,7 +2203,7 @@ s390_output_symbolic_const (file, x) { case 100: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "-.LT%X", s390_function_count); + fprintf (file, "-.LT%d", current_function_funcdef_no); break; case 110: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); @@ -2238,7 +2223,7 @@ s390_output_symbolic_const (file, x) break; case 114: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@PLT-.LT%X", s390_function_count); + fprintf (file, "@PLT-.LT%d", current_function_funcdef_no); break; default: output_operand_lossage ("invalid UNSPEC as operand (2)"); @@ -2638,6 +2623,10 @@ s390_split_branches () if (TARGET_64BIT) return; + /* We need correct insn addresses. */ + + shorten_branches (get_insns ()); + /* Find all branches that exceed 64KB, and split them. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) @@ -2668,6 +2657,8 @@ s390_split_branches () if (get_attr_length (insn) == 4) continue; + regs_ever_live[RETURN_REGNUM] = 1; + if (flag_pic) { target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, label), 100); @@ -3061,6 +3052,14 @@ s390_chunkify_pool () if (get_pool_size () < S390_POOL_CHUNK_MAX) return; + if (!TARGET_64BIT) + regs_ever_live[RETURN_REGNUM] = 1; + + /* We need correct insn addresses. */ + + shorten_branches (get_insns ()); + + /* Scan all insns and move literals to pool chunks. Replace all occurrances of literal pool references by explicit references to pool chunk entries. */ @@ -3352,17 +3351,17 @@ s390_output_constant_pool (file) { if (TARGET_64BIT) { - fprintf (file, "\tlarl\t%s,.LT%X\n", reg_names[BASE_REGISTER], - s390_function_count); + fprintf (file, "\tlarl\t%s,.LT%d\n", reg_names[BASE_REGISTER], + current_function_funcdef_no); readonly_data_section (); ASM_OUTPUT_ALIGN (file, 3); } else { - fprintf (file, "\tbras\t%s,.LTN%X\n", reg_names[BASE_REGISTER], - s390_function_count); + fprintf (file, "\tbras\t%s,.LTN%d\n", reg_names[BASE_REGISTER], + current_function_funcdef_no); } - fprintf (file, ".LT%X:\n", s390_function_count); + fprintf (file, ".LT%d:\n", current_function_funcdef_no); s390_pool_count = 0; output_constant_pool (current_function_name, current_function_decl); @@ -3371,27 +3370,159 @@ s390_output_constant_pool (file) if (TARGET_64BIT) function_section (current_function_decl); else - fprintf (file, ".LTN%X:\n", s390_function_count); + fprintf (file, ".LTN%d:\n", current_function_funcdef_no); } } -/* Return true if floating point registers need to be saved. */ +/* Rework the prolog/epilog to avoid saving/restoring + registers unnecessarily. */ -static int -save_fprs_p () +static void +s390_optimize_prolog () { - int i; - if (!TARGET_64BIT) - return 0; - for (i=24; i<=31; i++) + int save_first, save_last, restore_first, restore_last; + int i, j; + rtx insn, new_insn, next_insn; + + /* Find first and last gpr to be saved. */ + + for (i = 6; i < 16; i++) + if (regs_ever_live[i]) + break; + + for (j = 15; j > i; j--) + if (regs_ever_live[j]) + break; + + if (i == 16) { - if (regs_ever_live[i] == 1) - return 1; + /* Nothing to save/restore. */ + save_first = restore_first = -1; + save_last = restore_last = -1; } - return 0; + else + { + /* Save/restore from i to j. */ + save_first = restore_first = i; + save_last = restore_last = j; + } + + /* Varargs functions need to save gprs 2 to 6. */ + if (current_function_stdarg) + { + save_first = 2; + if (save_last < 6) + save_last = 6; + } + + + /* If all special registers are in fact used, there's nothing we + can do, so no point in walking the insn list. */ + if (i <= BASE_REGISTER && j >= BASE_REGISTER + && i <= RETURN_REGNUM && j >= RETURN_REGNUM) + return; + + + /* Search for prolog/epilog insns and replace them. */ + + for (insn = get_insns (); insn; insn = next_insn) + { + int first, last, off; + rtx set, base, offset; + + next_insn = NEXT_INSN (insn); + + if (GET_CODE (insn) != INSN) + continue; + if (GET_CODE (PATTERN (insn)) != PARALLEL) + continue; + + if (store_multiple_operation (PATTERN (insn), VOIDmode)) + { + set = XVECEXP (PATTERN (insn), 0, 0); + first = REGNO (SET_SRC (set)); + last = first + XVECLEN (PATTERN (insn), 0) - 1; + offset = const0_rtx; + base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset); + off = INTVAL (offset) - first * UNITS_PER_WORD; + + if (GET_CODE (base) != REG || off < 0) + continue; + if (first > BASE_REGISTER && first > RETURN_REGNUM) + continue; + if (last < BASE_REGISTER && last < RETURN_REGNUM) + continue; + + if (save_first != -1) + { + new_insn = save_gprs (base, off, save_first, save_last); + new_insn = emit_insn_before (new_insn, insn); + INSN_ADDRESSES_NEW (new_insn, -1); + } + + remove_insn (insn); + } + + if (load_multiple_operation (PATTERN (insn), VOIDmode)) + { + set = XVECEXP (PATTERN (insn), 0, 0); + first = REGNO (SET_DEST (set)); + last = first + XVECLEN (PATTERN (insn), 0) - 1; + offset = const0_rtx; + base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset); + off = INTVAL (offset) - first * UNITS_PER_WORD; + + if (GET_CODE (base) != REG || off < 0) + continue; + if (first > BASE_REGISTER && first > RETURN_REGNUM) + continue; + if (last < BASE_REGISTER && last < RETURN_REGNUM) + continue; + + if (restore_first != -1) + { + new_insn = restore_gprs (base, off, restore_first, restore_last); + new_insn = emit_insn_before (new_insn, insn); + INSN_ADDRESSES_NEW (new_insn, -1); + } + + remove_insn (insn); + } + } +} + +/* Perform machine-dependent processing. */ + +void +s390_machine_dependent_reorg (first) + rtx first ATTRIBUTE_UNUSED; +{ + struct s390_frame frame; + s390_frame_info (&frame); + + /* Recompute regs_ever_live data for special registers. */ + regs_ever_live[BASE_REGISTER] = 0; + regs_ever_live[RETURN_REGNUM] = 0; + regs_ever_live[STACK_POINTER_REGNUM] = frame.frame_size > 0; + + /* If there is (possibly) any pool entry, we need to + load the base register. + ??? FIXME: this should be more precise. */ + if (get_pool_size ()) + regs_ever_live[BASE_REGISTER] = 1; + + /* In non-leaf functions, the prolog/epilog code relies + on RETURN_REGNUM being saved in any case. */ + if (!current_function_is_leaf) + regs_ever_live[RETURN_REGNUM] = 1; + + s390_chunkify_pool (); + s390_split_branches (); + s390_optimize_prolog (); } + /* Find first call clobbered register unsused in a function. This could be used as base register in a leaf function or for holding the return address before epilogue. */ @@ -3412,6 +3543,7 @@ static void s390_frame_info (frame) struct s390_frame *frame; { + char gprs_ever_live[16]; int i, j; HOST_WIDE_INT fsize = get_frame_size (); @@ -3419,7 +3551,14 @@ s390_frame_info (frame) fatal_error ("Total size of local variables exceeds architecture limit."); /* fprs 8 - 15 are caller saved for 64 Bit ABI. */ - frame->save_fprs_p = save_fprs_p (); + frame->save_fprs_p = 0; + if (TARGET_64BIT) + for (i = 24; i < 32; i++) + if (regs_ever_live[i]) + { + frame->save_fprs_p = 1; + break; + } frame->frame_size = fsize + frame->save_fprs_p * 64; @@ -3431,66 +3570,41 @@ s390_frame_info (frame) || current_function_stdarg) frame->frame_size += STARTING_FRAME_OFFSET; - /* If we need to allocate a frame, the stack pointer is changed. */ - - if (frame->frame_size > 0) - regs_ever_live[STACK_POINTER_REGNUM] = 1; - - /* If the literal pool might overflow, the return register might - be used as temp literal pointer. */ - - if (!TARGET_64BIT && get_pool_size () >= S390_POOL_CHUNK_MAX / 2) - regs_ever_live[RETURN_REGNUM] = 1; - - /* If there is (possibly) any pool entry, we need to - load base register. */ - - if (get_pool_size () - || !CONST_OK_FOR_LETTER_P (frame->frame_size, 'K') - || (!TARGET_64BIT && current_function_uses_pic_offset_table)) - regs_ever_live[BASE_REGISTER] = 1; - - /* If we need the GOT pointer, remember to save/restore it. */ - - if (current_function_uses_pic_offset_table) - regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; - /* Frame pointer needed. */ frame->frame_pointer_p = frame_pointer_needed; - /* Find first and last gpr to be saved. */ + /* Find first and last gpr to be saved. Note that at this point, + we assume the return register and the base register always + need to be saved. This is done because the usage of these + register might change even after the prolog was emitted. + If it turns out later that we really don't need them, the + prolog/epilog code is modified again. */ + + for (i = 0; i < 16; i++) + gprs_ever_live[i] = regs_ever_live[i]; + + gprs_ever_live[BASE_REGISTER] = 1; + gprs_ever_live[RETURN_REGNUM] = 1; + gprs_ever_live[STACK_POINTER_REGNUM] = frame->frame_size > 0; for (i = 6; i < 16; i++) - if (regs_ever_live[i]) + if (gprs_ever_live[i]) break; for (j = 15; j > i; j--) - if (regs_ever_live[j]) + if (gprs_ever_live[j]) break; - - if (i == 16) - { - /* Nothing to save / restore. */ - frame->first_save_gpr = -1; - frame->first_restore_gpr = -1; - frame->last_save_gpr = -1; - frame->return_reg_saved_p = 0; - } - else - { - /* Save / Restore from gpr i to j. */ - frame->first_save_gpr = i; - frame->first_restore_gpr = i; - frame->last_save_gpr = j; - frame->return_reg_saved_p = (j >= RETURN_REGNUM && i <= RETURN_REGNUM); - } + + /* Save / Restore from gpr i to j. */ + frame->first_save_gpr = i; + frame->first_restore_gpr = i; + frame->last_save_gpr = j; + + /* Varargs functions need to save gprs 2 to 6. */ if (current_function_stdarg) - { - /* Varargs function need to save from gpr 2 to gpr 15. */ - frame->first_save_gpr = 2; - } + frame->first_save_gpr = 2; } /* Return offset between argument pointer and frame pointer @@ -3540,30 +3654,118 @@ restore_fpr (base, offset, regnum) return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr); } -/* Output the function prologue assembly code to the - stdio stream FILE. The local frame size is passed - in LSIZE. */ +/* Generate insn to save registers FIRST to LAST into + the register save area located at offset OFFSET + relative to register BASE. */ -void -s390_function_prologue (file, lsize) - FILE *file ATTRIBUTE_UNUSED; - HOST_WIDE_INT lsize ATTRIBUTE_UNUSED; +static rtx +save_gprs (base, offset, first, last) + rtx base; + int offset; + int first; + int last; { - s390_chunkify_pool (); - s390_split_branches (); + rtx addr, insn, note; + int i; + + addr = plus_constant (base, offset + first * UNITS_PER_WORD); + addr = gen_rtx_MEM (Pmode, addr); + set_mem_alias_set (addr, s390_sr_alias_set); + + /* Special-case single register. */ + if (first == last) + { + if (TARGET_64BIT) + insn = gen_movdi (addr, gen_rtx_REG (Pmode, first)); + else + insn = gen_movsi (addr, gen_rtx_REG (Pmode, first)); + + RTX_FRAME_RELATED_P (insn) = 1; + return insn; + } + + + insn = gen_store_multiple (addr, + gen_rtx_REG (Pmode, first), + GEN_INT (last - first + 1)); + + + /* We need to set the FRAME_RELATED flag on all SETs + inside the store-multiple pattern. + + However, we must not emit DWARF records for registers 2..5 + if they are stored for use by variable arguments ... + + ??? Unfortunately, it is not enough to simply not the the + FRAME_RELATED flags for those SETs, because the first SET + of the PARALLEL is always treated as if it had the flag + set, even if it does not. Therefore we emit a new pattern + without those registers as REG_FRAME_RELATED_EXPR note. */ + + if (first >= 6) + { + rtx pat = PATTERN (insn); + + for (i = 0; i < XVECLEN (pat, 0); i++) + if (GET_CODE (XVECEXP (pat, 0, i)) == SET) + RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1; + + RTX_FRAME_RELATED_P (insn) = 1; + } + else if (last >= 6) + { + addr = plus_constant (base, offset + 6 * UNITS_PER_WORD); + note = gen_store_multiple (gen_rtx_MEM (Pmode, addr), + gen_rtx_REG (Pmode, 6), + GEN_INT (last - 6 + 1)); + note = PATTERN (note); + + REG_NOTES (insn) = + gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, + note, REG_NOTES (insn)); + + for (i = 0; i < XVECLEN (note, 0); i++) + if (GET_CODE (XVECEXP (note, 0, i)) == SET) + RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1; + + RTX_FRAME_RELATED_P (insn) = 1; + } + + return insn; } -/* Output the function epilogue assembly code to the - stdio stream FILE. The local frame size is passed - in LSIZE. */ +/* Generate insn to restore registers FIRST to LAST from + the register save area located at offset OFFSET + relative to register BASE. */ -void -s390_function_epilogue (file, lsize) - FILE *file ATTRIBUTE_UNUSED; - HOST_WIDE_INT lsize ATTRIBUTE_UNUSED; +static rtx +restore_gprs (base, offset, first, last) + rtx base; + int offset; + int first; + int last; { - current_function_uses_pic_offset_table = 0; - s390_function_count++; + rtx addr, insn; + + addr = plus_constant (base, offset + first * UNITS_PER_WORD); + addr = gen_rtx_MEM (Pmode, addr); + set_mem_alias_set (addr, s390_sr_alias_set); + + /* Special-case single register. */ + if (first == last) + { + if (TARGET_64BIT) + insn = gen_movdi (gen_rtx_REG (Pmode, first), addr); + else + insn = gen_movsi (gen_rtx_REG (Pmode, first), addr); + + return insn; + } + + insn = gen_load_multiple (gen_rtx_REG (Pmode, first), + addr, + GEN_INT (last - first + 1)); + return insn; } /* Expand the prologue into a bunch of separate insns. */ @@ -3582,7 +3784,7 @@ s390_emit_prologue () /* Choose best register to use for temp use within prologue. */ - if (frame.return_reg_saved_p + if (!current_function_is_leaf && !has_hard_reg_initial_val (Pmode, RETURN_REGNUM) && get_pool_size () < S390_POOL_CHUNK_MAX / 2) temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM); @@ -3591,69 +3793,9 @@ s390_emit_prologue () /* Save call saved gprs. */ - if (frame.first_save_gpr != -1) - { - addr = plus_constant (stack_pointer_rtx, - frame.first_save_gpr * UNITS_PER_WORD); - addr = gen_rtx_MEM (Pmode, addr); - set_mem_alias_set (addr, s390_sr_alias_set); - - if (frame.first_save_gpr != frame.last_save_gpr ) - { - insn = emit_insn (gen_store_multiple (addr, - gen_rtx_REG (Pmode, frame.first_save_gpr), - GEN_INT (frame.last_save_gpr - - frame.first_save_gpr + 1))); - - /* We need to set the FRAME_RELATED flag on all SETs - inside the store-multiple pattern. - - However, we must not emit DWARF records for registers 2..5 - if they are stored for use by variable arguments ... - - ??? Unfortunately, it is not enough to simply not the the - FRAME_RELATED flags for those SETs, because the first SET - of the PARALLEL is always treated as if it had the flag - set, even if it does not. Therefore we emit a new pattern - without those registers as REG_FRAME_RELATED_EXPR note. */ - - if (frame.first_save_gpr >= 6) - { - rtx pat = PATTERN (insn); - - for (i = 0; i < XVECLEN (pat, 0); i++) - if (GET_CODE (XVECEXP (pat, 0, i)) == SET) - RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1; - - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (frame.last_save_gpr >= 6) - { - rtx note, naddr; - naddr = plus_constant (stack_pointer_rtx, 6 * UNITS_PER_WORD); - note = gen_store_multiple (gen_rtx_MEM (Pmode, naddr), - gen_rtx_REG (Pmode, 6), - GEN_INT (frame.last_save_gpr - 6 + 1)); - note = PATTERN (note); - - REG_NOTES (insn) = - gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, - note, REG_NOTES (insn)); - - for (i = 0; i < XVECLEN (note, 0); i++) - if (GET_CODE (XVECEXP (note, 0, i)) == SET) - RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1; - - RTX_FRAME_RELATED_P (insn) = 1; - } - } - else - { - insn = emit_move_insn (addr, - gen_rtx_REG (Pmode, frame.first_save_gpr)); - RTX_FRAME_RELATED_P (insn) = 1; - } - } + insn = save_gprs (stack_pointer_rtx, 0, + frame.first_save_gpr, frame.last_save_gpr); + emit_insn (insn); /* Dump constant pool and set constant pool register (13). */ @@ -3765,7 +3907,7 @@ s390_emit_prologue () /* Set up got pointer, if needed. */ - if (current_function_uses_pic_offset_table) + if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) { rtx got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); SYMBOL_REF_FLAG (got_symbol) = 1; @@ -3912,7 +4054,7 @@ s390_emit_epilogue () if (frame.first_restore_gpr != -1) { - rtx addr; + rtx insn, addr; int i; /* Check for global register and save them @@ -3943,8 +4085,7 @@ s390_emit_epilogue () /* Fetch return address from stack before load multiple, this will do good for scheduling. */ - if (frame.last_save_gpr >= RETURN_REGNUM - && frame.first_restore_gpr < RETURN_REGNUM) + if (!current_function_is_leaf) { int return_regnum = find_unused_clobbered_reg(); if (!return_regnum) @@ -3964,23 +4105,9 @@ s390_emit_epilogue () emit_insn (gen_blockage()); - addr = plus_constant (frame_pointer, - offset + frame.first_restore_gpr * UNITS_PER_WORD); - addr = gen_rtx_MEM (Pmode, addr); - set_mem_alias_set (addr, s390_sr_alias_set); - - if (frame.first_restore_gpr != frame.last_save_gpr) - { - emit_insn (gen_load_multiple ( - gen_rtx_REG (Pmode, frame.first_restore_gpr), - addr, - GEN_INT (frame.last_save_gpr - frame.first_restore_gpr + 1))); - } - else - { - emit_move_insn (gen_rtx_REG (Pmode, frame.first_restore_gpr), - addr); - } + insn = restore_gprs (frame_pointer, offset, + frame.first_restore_gpr, frame.last_save_gpr); + emit_insn (insn); } /* Return to caller. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index c5ba427..781dc2e 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -94,10 +94,6 @@ extern int target_flags; #define TARGET_IBM_FLOAT 0 #define TARGET_IEEE_FLOAT 1 -/* The current function count for create unique internal labels. */ - -extern int s390_function_count; - /* The amount of space used for outgoing arguments. */ extern int current_function_outgoing_args_size; @@ -1349,4 +1345,11 @@ extern int s390_pool_overflow; goto WIN; \ } +/* In rare cases, correct code generation requires extra machine dependent + processing between the second jump optimization pass and delayed branch + scheduling. On those machines, define this macro as a C statement to act on + the code starting at INSN. */ + +#define MACHINE_DEPENDENT_REORG(INSN) s390_machine_dependent_reorg (INSN) + #endif diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index f8ddc2f..e1612dd 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -6228,10 +6228,7 @@ compiler doesn't know about it, because the PLT glue code uses it. In 64-bit, this is not necessary. */ if (plt_call && !TARGET_64BIT) - { - current_function_uses_pic_offset_table = 1; - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); - } + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); DONE; }") @@ -6353,10 +6350,7 @@ compiler doesn't know about it, because the PLT glue code uses it. In 64-bit, this is not necessary. */ if (plt_call && !TARGET_64BIT) - { - current_function_uses_pic_offset_table = 1; - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); - } + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); DONE; }") |