From 7bcebb25b9bb31b27f7d1e71f01d1988d3217ac7 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Tue, 28 Jun 2005 14:25:17 +0000 Subject: s390.c (machine_function): New field has_landing_pad_p. 2005-06-28 Andreas Krebbel * 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 --- gcc/ChangeLog | 14 ++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.c | 148 ++++++++++++++++++++++++++++++++++++------ gcc/config/s390/s390.md | 7 ++ 4 files changed, 149 insertions(+), 21 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d32c3d..272d7f7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2005-06-28 Andreas Krebbel + * 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 + * except.c (current_function_has_exception_handlers): Function description added and if statements merged. diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 0fef8f6..87cf98e 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -29,6 +29,7 @@ extern void s390_emit_prologue (void); extern void s390_emit_epilogue (bool); extern void s390_function_profiler (FILE *, int); extern void s390_conditional_register_usage (void); +extern void s390_set_has_landing_pad_p (bool); #ifdef RTX_CODE extern int s390_extra_constraint_str (rtx, int, const char *); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index fed9b26..6311833 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -245,6 +245,8 @@ struct machine_function GTY(()) /* Some local-dynamic TLS symbol name. */ const char *some_ld_name; + + bool has_landing_pad_p; }; /* Few accessor macros for struct cfun->machine->s390_frame_layout. */ @@ -262,6 +264,13 @@ struct machine_function GTY(()) #define GP_ARG_NUM_REG 5 #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 the source and destination have matching CC modes and that @@ -5480,8 +5489,14 @@ s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) if (count == 0) { - cfun_frame_layout.save_return_addr_p = true; - return gen_rtx_MEM (Pmode, return_address_pointer_rtx); + /* On non-z architectures branch splitting could overwrite r14. */ + 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) @@ -5528,6 +5543,88 @@ find_unused_clobbered_reg (void) 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 in the function epilogue. The values are stored at the given pointers AREA_BOTTOM (address of the lowest used stack @@ -5571,10 +5668,10 @@ s390_frame_area (int *area_bottom, int *area_top) } /* 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 -s390_register_info (int live_regs[]) +s390_register_info (int clobbered_regs[]) { int i, j; @@ -5595,34 +5692,39 @@ s390_register_info (int live_regs[]) Also, all registers with special meaning to the compiler need to be handled extra. */ + s390_regs_ever_clobbered (clobbered_regs); + 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) - live_regs[PIC_OFFSET_TABLE_REGNUM] + clobbered_regs[PIC_OFFSET_TABLE_REGNUM] = regs_ever_live[PIC_OFFSET_TABLE_REGNUM]; - live_regs[BASE_REGNUM] + clobbered_regs[BASE_REGNUM] = cfun->machine->base_reg && REGNO (cfun->machine->base_reg) == BASE_REGNUM; - live_regs[RETURN_REGNUM] + clobbered_regs[RETURN_REGNUM] = cfun->machine->split_branches_pending_p || cfun_frame_layout.save_return_addr_p; - live_regs[STACK_POINTER_REGNUM] + clobbered_regs[STACK_POINTER_REGNUM] = !current_function_is_leaf || TARGET_TPF_PROFILING || cfun_save_high_fprs_p || get_frame_size () > 0 || current_function_calls_alloca || current_function_stdarg; - + for (i = 6; i < 16; i++) - if (live_regs[i]) + if (clobbered_regs[i]) break; for (j = 15; j > i; j--) - if (live_regs[j]) + if (clobbered_regs[j]) break; if (i == 16) @@ -5804,10 +5906,12 @@ s390_init_frame_layout (void) { HOST_WIDE_INT frame_size; int base_used; - int live_regs[16]; + int clobbered_regs[16]; /* 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 || TARGET_TPF_PROFILING || current_function_stdarg @@ -5841,7 +5945,7 @@ s390_init_frame_layout (void) else cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM); - s390_register_info (live_regs); + s390_register_info (clobbered_regs); s390_frame_info (); } while (frame_size != cfun_frame_layout.frame_size); @@ -5855,13 +5959,13 @@ s390_init_frame_layout (void) static 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[RETURN_REGNUM] = live_regs[RETURN_REGNUM]; - regs_ever_live[STACK_POINTER_REGNUM] = live_regs[STACK_POINTER_REGNUM]; + regs_ever_live[BASE_REGNUM] = clobbered_regs[BASE_REGNUM]; + regs_ever_live[RETURN_REGNUM] = clobbered_regs[RETURN_REGNUM]; + regs_ever_live[STACK_POINTER_REGNUM] = clobbered_regs[STACK_POINTER_REGNUM]; if (cfun->machine->base_reg) regs_ever_live[REGNO (cfun->machine->base_reg)] = 1; @@ -6131,7 +6235,9 @@ s390_emit_prologue (void) /* Choose best register to use for temp use within prologue. 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); else temp_reg = gen_rtx_REG (Pmode, 1); diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 754955b..826261d 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -6895,6 +6895,13 @@ DONE; }) +(define_expand "exception_receiver" + [(const_int 0)] + "" +{ + s390_set_has_landing_pad_p (true); + DONE; +}) ; ; nop instruction pattern(s). -- cgit v1.1