Commit 7bcebb25 by Andreas Krebbel Committed by Ulrich Weigand

s390.c (machine_function): New field has_landing_pad_p.

2005-06-28  Andreas Krebbel  <krebbel1@de.ibm.com>

	* config/s390/s390.c (machine_function): New field has_landing_pad_p.
	(s390_set_has_landing_pad_p, s390_reg_clobbered_rtx,
	 s390_regs_ever_clobbered): New functions.
	(s390_return_addr_rtx): Use get_hard_reg_initial_value.
	(s390_register_info, s390_init_frame_layout, s390_update_frame_layout):
	Use s390_regs_ever_clobbered.
	(s390_emit_prologue): Don't use r14 as temp reg if its content is used
	for builtin_return_address.
	* config/s390/s390.md ("exception_receiver"): New expander.
	* config/s390/s390-protos.h (s390_set_has_landing_pad_p): Prototype
	added.

From-SVN: r101381
parent 16c5f6e1
2005-06-28 Andreas Krebbel <krebbel1@de.ibm.com> 2005-06-28 Andreas Krebbel <krebbel1@de.ibm.com>
* config/s390/s390.c (machine_function): New field has_landing_pad_p.
(s390_set_has_landing_pad_p, s390_reg_clobbered_rtx,
s390_regs_ever_clobbered): New functions.
(s390_return_addr_rtx): Use get_hard_reg_initial_value.
(s390_register_info, s390_init_frame_layout, s390_update_frame_layout):
Use s390_regs_ever_clobbered.
(s390_emit_prologue): Don't use r14 as temp reg if its content is used
for builtin_return_address.
* config/s390/s390.md ("exception_receiver"): New expander.
* config/s390/s390-protos.h (s390_set_has_landing_pad_p): Prototype
added.
2005-06-28 Andreas Krebbel <krebbel1@de.ibm.com>
* except.c (current_function_has_exception_handlers): Function * except.c (current_function_has_exception_handlers): Function
description added and if statements merged. description added and if statements merged.
......
...@@ -29,6 +29,7 @@ extern void s390_emit_prologue (void); ...@@ -29,6 +29,7 @@ extern void s390_emit_prologue (void);
extern void s390_emit_epilogue (bool); extern void s390_emit_epilogue (bool);
extern void s390_function_profiler (FILE *, int); extern void s390_function_profiler (FILE *, int);
extern void s390_conditional_register_usage (void); extern void s390_conditional_register_usage (void);
extern void s390_set_has_landing_pad_p (bool);
#ifdef RTX_CODE #ifdef RTX_CODE
extern int s390_extra_constraint_str (rtx, int, const char *); extern int s390_extra_constraint_str (rtx, int, const char *);
......
...@@ -245,6 +245,8 @@ struct machine_function GTY(()) ...@@ -245,6 +245,8 @@ struct machine_function GTY(())
/* Some local-dynamic TLS symbol name. */ /* Some local-dynamic TLS symbol name. */
const char *some_ld_name; const char *some_ld_name;
bool has_landing_pad_p;
}; };
/* Few accessor macros for struct cfun->machine->s390_frame_layout. */ /* Few accessor macros for struct cfun->machine->s390_frame_layout. */
...@@ -262,6 +264,13 @@ struct machine_function GTY(()) ...@@ -262,6 +264,13 @@ struct machine_function GTY(())
#define GP_ARG_NUM_REG 5 #define GP_ARG_NUM_REG 5
#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2) #define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
/* Set the has_landing_pad_p flag in struct machine_function to VALUE. */
void
s390_set_has_landing_pad_p (bool value)
{
cfun->machine->has_landing_pad_p = value;
}
/* Return true if SET either doesn't set the CC register, or else /* Return true if SET either doesn't set the CC register, or else
the source and destination have matching CC modes and that the source and destination have matching CC modes and that
...@@ -5480,8 +5489,14 @@ s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) ...@@ -5480,8 +5489,14 @@ s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
if (count == 0) if (count == 0)
{ {
cfun_frame_layout.save_return_addr_p = true; /* On non-z architectures branch splitting could overwrite r14. */
return gen_rtx_MEM (Pmode, return_address_pointer_rtx); if (TARGET_CPU_ZARCH)
return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
else
{
cfun_frame_layout.save_return_addr_p = true;
return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
}
} }
if (TARGET_PACKED_STACK) if (TARGET_PACKED_STACK)
...@@ -5528,6 +5543,88 @@ find_unused_clobbered_reg (void) ...@@ -5528,6 +5543,88 @@ find_unused_clobbered_reg (void)
return 0; return 0;
} }
/* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all
clobbered hard regs in SETREG. */
static void
s390_reg_clobbered_rtx (rtx setreg, rtx set_insn ATTRIBUTE_UNUSED, void *data)
{
int *regs_ever_clobbered = (int *)data;
unsigned int i, regno;
enum machine_mode mode = GET_MODE (setreg);
if (GET_CODE (setreg) == SUBREG)
{
rtx inner = SUBREG_REG (setreg);
if (!GENERAL_REG_P (inner))
return;
regno = subreg_regno (setreg);
}
else if (GENERAL_REG_P (setreg))
regno = REGNO (setreg);
else
return;
for (i = regno;
i < regno + HARD_REGNO_NREGS (regno, mode);
i++)
regs_ever_clobbered[i] = 1;
}
/* Walks through all basic blocks of the current function looking
for clobbered hard regs using s390_reg_clobbered_rtx. The fields
of the passed integer array REGS_EVER_CLOBBERED are set to one for
each of those regs. */
static void
s390_regs_ever_clobbered (int *regs_ever_clobbered)
{
basic_block cur_bb;
rtx cur_insn;
unsigned int i;
memset (regs_ever_clobbered, 0, 16 * sizeof (int));
/* For non-leaf functions we have to consider all call clobbered regs to be
clobbered. */
if (!current_function_is_leaf)
{
for (i = 0; i < 16; i++)
regs_ever_clobbered[i] = call_really_used_regs[i];
}
/* Make the "magic" eh_return registers live if necessary. For regs_ever_live
this work is done by liveness analysis (mark_regs_live_at_end).
Special care is needed for functions containing landing pads. Landing pads
may use the eh registers, but the code which sets these registers is not
contained in that function. Hence s390_regs_ever_clobbered is not able to
deal with this automatically. */
if (current_function_calls_eh_return || cfun->machine->has_landing_pad_p)
for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM ; i++)
regs_ever_clobbered[EH_RETURN_DATA_REGNO (i)] = 1;
/* For nonlocal gotos all call-saved registers have to be saved.
This flag is also set for the unwinding code in libgcc.
See expand_builtin_unwind_init. For regs_ever_live this is done by
reload. */
if (current_function_has_nonlocal_label)
for (i = 0; i < 16; i++)
if (!call_really_used_regs[i])
regs_ever_clobbered[i] = 1;
FOR_EACH_BB (cur_bb)
{
FOR_BB_INSNS (cur_bb, cur_insn)
{
if (INSN_P (cur_insn))
note_stores (PATTERN (cur_insn),
s390_reg_clobbered_rtx,
regs_ever_clobbered);
}
}
}
/* Determine the frame area which actually has to be accessed /* Determine the frame area which actually has to be accessed
in the function epilogue. The values are stored at the in the function epilogue. The values are stored at the
given pointers AREA_BOTTOM (address of the lowest used stack given pointers AREA_BOTTOM (address of the lowest used stack
...@@ -5571,10 +5668,10 @@ s390_frame_area (int *area_bottom, int *area_top) ...@@ -5571,10 +5668,10 @@ s390_frame_area (int *area_bottom, int *area_top)
} }
/* Fill cfun->machine with info about register usage of current function. /* Fill cfun->machine with info about register usage of current function.
Return in LIVE_REGS which GPRs are currently considered live. */ Return in CLOBBERED_REGS which GPRs are currently considered set. */
static void static void
s390_register_info (int live_regs[]) s390_register_info (int clobbered_regs[])
{ {
int i, j; int i, j;
...@@ -5595,34 +5692,39 @@ s390_register_info (int live_regs[]) ...@@ -5595,34 +5692,39 @@ s390_register_info (int live_regs[])
Also, all registers with special meaning to the compiler need Also, all registers with special meaning to the compiler need
to be handled extra. */ to be handled extra. */
s390_regs_ever_clobbered (clobbered_regs);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
live_regs[i] = regs_ever_live[i] && !global_regs[i]; clobbered_regs[i] = clobbered_regs[i] && !global_regs[i];
if (frame_pointer_needed)
clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
if (flag_pic) if (flag_pic)
live_regs[PIC_OFFSET_TABLE_REGNUM] clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
= regs_ever_live[PIC_OFFSET_TABLE_REGNUM]; = regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
live_regs[BASE_REGNUM] clobbered_regs[BASE_REGNUM]
= cfun->machine->base_reg = cfun->machine->base_reg
&& REGNO (cfun->machine->base_reg) == BASE_REGNUM; && REGNO (cfun->machine->base_reg) == BASE_REGNUM;
live_regs[RETURN_REGNUM] clobbered_regs[RETURN_REGNUM]
= cfun->machine->split_branches_pending_p = cfun->machine->split_branches_pending_p
|| cfun_frame_layout.save_return_addr_p; || cfun_frame_layout.save_return_addr_p;
live_regs[STACK_POINTER_REGNUM] clobbered_regs[STACK_POINTER_REGNUM]
= !current_function_is_leaf = !current_function_is_leaf
|| TARGET_TPF_PROFILING || TARGET_TPF_PROFILING
|| cfun_save_high_fprs_p || cfun_save_high_fprs_p
|| get_frame_size () > 0 || get_frame_size () > 0
|| current_function_calls_alloca || current_function_calls_alloca
|| current_function_stdarg; || current_function_stdarg;
for (i = 6; i < 16; i++) for (i = 6; i < 16; i++)
if (live_regs[i]) if (clobbered_regs[i])
break; break;
for (j = 15; j > i; j--) for (j = 15; j > i; j--)
if (live_regs[j]) if (clobbered_regs[j])
break; break;
if (i == 16) if (i == 16)
...@@ -5804,10 +5906,12 @@ s390_init_frame_layout (void) ...@@ -5804,10 +5906,12 @@ s390_init_frame_layout (void)
{ {
HOST_WIDE_INT frame_size; HOST_WIDE_INT frame_size;
int base_used; int base_used;
int live_regs[16]; int clobbered_regs[16];
/* If return address register is explicitly used, we need to save it. */ /* If return address register is explicitly used, we need to save it. */
if (regs_ever_live[RETURN_REGNUM] s390_regs_ever_clobbered (clobbered_regs);
if (clobbered_regs[RETURN_REGNUM]
|| !current_function_is_leaf || !current_function_is_leaf
|| TARGET_TPF_PROFILING || TARGET_TPF_PROFILING
|| current_function_stdarg || current_function_stdarg
...@@ -5841,7 +5945,7 @@ s390_init_frame_layout (void) ...@@ -5841,7 +5945,7 @@ s390_init_frame_layout (void)
else else
cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM); cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
s390_register_info (live_regs); s390_register_info (clobbered_regs);
s390_frame_info (); s390_frame_info ();
} }
while (frame_size != cfun_frame_layout.frame_size); while (frame_size != cfun_frame_layout.frame_size);
...@@ -5855,13 +5959,13 @@ s390_init_frame_layout (void) ...@@ -5855,13 +5959,13 @@ s390_init_frame_layout (void)
static void static void
s390_update_frame_layout (void) s390_update_frame_layout (void)
{ {
int live_regs[16]; int clobbered_regs[16];
s390_register_info (live_regs); s390_register_info (clobbered_regs);
regs_ever_live[BASE_REGNUM] = live_regs[BASE_REGNUM]; regs_ever_live[BASE_REGNUM] = clobbered_regs[BASE_REGNUM];
regs_ever_live[RETURN_REGNUM] = live_regs[RETURN_REGNUM]; regs_ever_live[RETURN_REGNUM] = clobbered_regs[RETURN_REGNUM];
regs_ever_live[STACK_POINTER_REGNUM] = live_regs[STACK_POINTER_REGNUM]; regs_ever_live[STACK_POINTER_REGNUM] = clobbered_regs[STACK_POINTER_REGNUM];
if (cfun->machine->base_reg) if (cfun->machine->base_reg)
regs_ever_live[REGNO (cfun->machine->base_reg)] = 1; regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
...@@ -6131,7 +6235,9 @@ s390_emit_prologue (void) ...@@ -6131,7 +6235,9 @@ s390_emit_prologue (void)
/* Choose best register to use for temp use within prologue. /* Choose best register to use for temp use within prologue.
See below for why TPF must use the register 1. */ See below for why TPF must use the register 1. */
if (!current_function_is_leaf && !TARGET_TPF_PROFILING) if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
&& !current_function_is_leaf
&& !TARGET_TPF_PROFILING)
temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM); temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
else else
temp_reg = gen_rtx_REG (Pmode, 1); temp_reg = gen_rtx_REG (Pmode, 1);
......
...@@ -6895,6 +6895,13 @@ ...@@ -6895,6 +6895,13 @@
DONE; DONE;
}) })
(define_expand "exception_receiver"
[(const_int 0)]
""
{
s390_set_has_landing_pad_p (true);
DONE;
})
; ;
; nop instruction pattern(s). ; nop instruction pattern(s).
......
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