aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2002-08-26 18:18:19 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2002-08-26 18:18:19 +0000
commitc3cc6b78a1487e9c05be9770f811b79706318867 (patch)
tree9c119df126330ad4a35fad49d9f309abceb20145 /gcc
parent3f66218653d7905c186e050208545d9f8d0b020f (diff)
downloadgcc-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/ChangeLog34
-rw-r--r--gcc/config/s390/s390-protos.h3
-rw-r--r--gcc/config/s390/s390.c511
-rw-r--r--gcc/config/s390/s390.h11
-rw-r--r--gcc/config/s390/s390.md10
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;
}")