From fb3712f61f4ecb0fca8738013f68f75b901a33b4 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 9 Nov 2005 11:45:01 +0000 Subject: [PATCH] s390.c (struct s390_frame_layout): New fields first_save_gpr_slot and last_save_gpr_slot. 2005-11-09 Andreas Krebbel * config/s390/s390.c (struct s390_frame_layout): New fields first_save_gpr_slot and last_save_gpr_slot. (cfun_grps_save_area_size, s390_frame_info, s390_emit_prologue, s390_emit_epilogue, s390_initial_elimination_offset): Replaced first_save_gpr and last_save_gpr with the _slot variants. (s390_register_info): Calculate first_save_gpr_slot and last_save_gpr_slot using regs_ever_live. * testsuite/gcc.dg/pr24624.c: Testcase added. From-SVN: r106688 --- gcc/ChangeLog | 11 +++++ gcc/config/s390/s390.c | 78 +++++++++++++++++++++++++--------- gcc/testsuite/gcc.dg/pr24624.c | 67 +++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr24624.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d5043a75969..d3dc23e0465 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-11-09 Andreas Krebbel + + * config/s390/s390.c (struct s390_frame_layout): New fields + first_save_gpr_slot and last_save_gpr_slot. + (cfun_grps_save_area_size, s390_frame_info, s390_emit_prologue, + s390_emit_epilogue, s390_initial_elimination_offset): Replaced + first_save_gpr and last_save_gpr with the _slot variants. + (s390_register_info): Calculate first_save_gpr_slot and + last_save_gpr_slot using regs_ever_live. + * testsuite/gcc.dg/pr24624.c: Testcase added. + 2005-11-09 Andreas Krebbel * config/s390/s390.c (s390_regs_ever_clobbered): Only save live eh regs diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 75192e4b89b..de049bf1c0e 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -233,7 +233,12 @@ struct s390_frame_layout GTY (()) HOST_WIDE_INT f4_offset; HOST_WIDE_INT f8_offset; HOST_WIDE_INT backchain_offset; - + + /* Number of first and last gpr where slots in the register + save area are reserved for. */ + int first_save_gpr_slot; + int last_save_gpr_slot; + /* Number of first and last gpr to be saved, restored. */ int first_save_gpr; int first_restore_gpr; @@ -283,8 +288,8 @@ struct machine_function GTY(()) #define cfun_frame_layout (cfun->machine->frame_layout) #define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs) -#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr - \ - cfun_frame_layout.first_save_gpr + 1) * UNITS_PER_WORD) +#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \ + cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_WORD) #define cfun_set_fpr_bit(BITNUM) (cfun->machine->frame_layout.fpr_bitmap |= \ (1 << (BITNUM))) #define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \ @@ -6135,15 +6140,17 @@ s390_register_info (int clobbered_regs[]) || current_function_stdarg); for (i = 6; i < 16; i++) - if (clobbered_regs[i]) + if (regs_ever_live[i] || clobbered_regs[i]) break; for (j = 15; j > i; j--) - if (clobbered_regs[j]) + if (regs_ever_live[j] || clobbered_regs[j]) break; if (i == 16) { /* Nothing to save/restore. */ + cfun_frame_layout.first_save_gpr_slot = -1; + cfun_frame_layout.last_save_gpr_slot = -1; cfun_frame_layout.first_save_gpr = -1; cfun_frame_layout.first_restore_gpr = -1; cfun_frame_layout.last_save_gpr = -1; @@ -6151,11 +6158,36 @@ s390_register_info (int clobbered_regs[]) } else { - /* Save / Restore from gpr i to j. */ - cfun_frame_layout.first_save_gpr = i; - cfun_frame_layout.first_restore_gpr = i; - cfun_frame_layout.last_save_gpr = j; - cfun_frame_layout.last_restore_gpr = j; + /* Save slots for gprs from i to j. */ + cfun_frame_layout.first_save_gpr_slot = i; + cfun_frame_layout.last_save_gpr_slot = j; + + for (i = cfun_frame_layout.first_save_gpr_slot; + i < cfun_frame_layout.last_save_gpr_slot + 1; + i++) + if (clobbered_regs[i]) + break; + + for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--) + if (clobbered_regs[j]) + break; + + if (i == cfun_frame_layout.last_save_gpr_slot + 1) + { + /* Nothing to save/restore. */ + cfun_frame_layout.first_save_gpr = -1; + cfun_frame_layout.first_restore_gpr = -1; + cfun_frame_layout.last_save_gpr = -1; + cfun_frame_layout.last_restore_gpr = -1; + } + else + { + /* Save / Restore from gpr i to j. */ + cfun_frame_layout.first_save_gpr = i; + cfun_frame_layout.first_restore_gpr = i; + cfun_frame_layout.last_save_gpr = j; + cfun_frame_layout.last_restore_gpr = j; + } } if (current_function_stdarg) @@ -6171,11 +6203,17 @@ s390_register_info (int clobbered_regs[]) if (cfun_frame_layout.first_save_gpr == -1 || cfun_frame_layout.first_save_gpr > 2 + min_gpr) - cfun_frame_layout.first_save_gpr = 2 + min_gpr; + { + cfun_frame_layout.first_save_gpr = 2 + min_gpr; + cfun_frame_layout.first_save_gpr_slot = 2 + min_gpr; + } if (cfun_frame_layout.last_save_gpr == -1 || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1) - cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1; + { + cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1; + cfun_frame_layout.last_save_gpr_slot = 2 + max_gpr - 1; + } } /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */ @@ -6220,7 +6258,7 @@ s390_frame_info (void) cfun_frame_layout.f0_offset = 16 * UNITS_PER_WORD; cfun_frame_layout.f4_offset = cfun_frame_layout.f0_offset + 2 * 8; cfun_frame_layout.f8_offset = -cfun_frame_layout.high_fprs * 8; - cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr + cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr_slot * UNITS_PER_WORD); } else if (TARGET_BACKCHAIN) /* kernel stack layout */ @@ -6229,7 +6267,7 @@ s390_frame_info (void) - UNITS_PER_WORD); cfun_frame_layout.gprs_offset = (cfun_frame_layout.backchain_offset - - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr + 1) + - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_WORD); if (TARGET_64BIT) @@ -6460,7 +6498,7 @@ s390_initial_elimination_offset (int from, int to) case RETURN_ADDRESS_POINTER_REGNUM: s390_init_frame_layout (); - index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr; + index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot; gcc_assert (index >= 0); offset = cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset; offset += index * UNITS_PER_WORD; @@ -6705,7 +6743,9 @@ s390_emit_prologue (void) if (cfun_frame_layout.first_save_gpr != -1) { insn = save_gprs (stack_pointer_rtx, - cfun_frame_layout.gprs_offset, + cfun_frame_layout.gprs_offset + + UNITS_PER_WORD * (cfun_frame_layout.first_save_gpr + - cfun_frame_layout.first_save_gpr_slot), cfun_frame_layout.first_save_gpr, cfun_frame_layout.last_save_gpr); emit_insn (insn); @@ -7059,7 +7099,7 @@ s390_emit_epilogue (bool sibcall) { addr = plus_constant (frame_pointer, offset + cfun_frame_layout.gprs_offset - + (i - cfun_frame_layout.first_save_gpr) + + (i - cfun_frame_layout.first_save_gpr_slot) * UNITS_PER_WORD); addr = gen_rtx_MEM (Pmode, addr); set_mem_alias_set (addr, get_frame_alias_set ()); @@ -7084,7 +7124,7 @@ s390_emit_epilogue (bool sibcall) addr = plus_constant (frame_pointer, offset + cfun_frame_layout.gprs_offset + (RETURN_REGNUM - - cfun_frame_layout.first_save_gpr) + - cfun_frame_layout.first_save_gpr_slot) * UNITS_PER_WORD); addr = gen_rtx_MEM (Pmode, addr); set_mem_alias_set (addr, get_frame_alias_set ()); @@ -7095,7 +7135,7 @@ s390_emit_epilogue (bool sibcall) insn = restore_gprs (frame_pointer, offset + cfun_frame_layout.gprs_offset + (cfun_frame_layout.first_restore_gpr - - cfun_frame_layout.first_save_gpr) + - cfun_frame_layout.first_save_gpr_slot) * UNITS_PER_WORD, cfun_frame_layout.first_restore_gpr, cfun_frame_layout.last_restore_gpr); diff --git a/gcc/testsuite/gcc.dg/pr24624.c b/gcc/testsuite/gcc.dg/pr24624.c new file mode 100644 index 00000000000..bc2070c4b79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr24624.c @@ -0,0 +1,67 @@ +/* This used to ICE due to a backend problem on s390. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -mpacked-stack" } */ + +typedef unsigned int __u32; +typedef struct +{ + volatile int counter; +} __attribute__ ((aligned (4))) atomic_t; +static __inline__ __attribute__ ((always_inline)) + void atomic_inc (volatile atomic_t * v) +{ + ( + { + typeof (v->counter) old_val, new_val; + __asm__ __volatile__ ( + " l %0,0(%3)\n" + "0: lr %1,%0\n" + " ar %1,%4\n" + " cs %0,%1,0(%3)\n" + " jl 0b": + "=&d" (old_val), "=&d" (new_val), "=m" (((atomic_t *) (v))->counter): + "a" (v), "d" (1), "m" (((atomic_t *) (v))->counter): + "cc", "memory"); + }); +} +extern unsigned long volatile __attribute__ ((section (".data"))) jiffies; +struct inet_peer +{ + unsigned long dtime; + atomic_t refcnt; +}; +static volatile int peer_total; +int inet_peer_threshold = 65536 + 128; +int inet_peer_minttl = 120 * 100; +int inet_peer_maxttl = 10 * 60 * 100; +static int +cleanup_once (unsigned long ttl) +{ + struct inet_peer *p; + if (p != ((void *) 0)) + { + if ((( + { + 1;} + ) && ((long) (jiffies) - (long) (p->dtime + ttl) < 0))) + { + return -1; + } + atomic_inc (&p->refcnt); + } +} +struct inet_peer * +inet_getpeer (__u32 daddr, int create) +{ + int i; + int ttl; + if (peer_total >= inet_peer_threshold) + ttl = inet_peer_minttl; + else + ttl = + inet_peer_maxttl - (inet_peer_maxttl - + inet_peer_minttl) / 100 * peer_total / + inet_peer_threshold * 100; + for (i = 0; i < 30 && !cleanup_once (ttl); i++); +}