s390.c (struct s390_frame_layout): New fields first_save_gpr_slot and last_save_gpr_slot.
authorAndreas Krebbel <krebbel1@de.ibm.com>
Wed, 9 Nov 2005 11:45:01 +0000 (11:45 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 9 Nov 2005 11:45:01 +0000 (11:45 +0000)
2005-11-09  Andreas Krebbel  <krebbel1@de.ibm.com>

* 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
gcc/config/s390/s390.c
gcc/testsuite/gcc.dg/pr24624.c [new file with mode: 0644]

index d5043a75969b51f920ba0a2c4c9d20914e745c57..d3dc23e04651d2bf5346e78cb9a68b4c1dab5c48 100644 (file)
@@ -1,3 +1,14 @@
+2005-11-09  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * 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  <krebbel1@de.ibm.com>
 
        * config/s390/s390.c (s390_regs_ever_clobbered): Only save live eh regs
index 75192e4b89b1972ff558841ee57c07932b610834..de049bf1c0eb91df3a92f01d4fd378ad38a6b8af 100644 (file)
@@ -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 (file)
index 0000000..bc2070c
--- /dev/null
@@ -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++);
+}