S/390: Fix PR89775. Stackpointer save/restore instructions removed
authorAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 20 Mar 2019 15:28:38 +0000 (15:28 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 20 Mar 2019 15:28:38 +0000 (15:28 +0000)
Even if a global register is being clobbered in a function we usually
do not save and restore it. However, we still have to do this if it is
a special register. Most of the places in the backend handle this
correctly but not the prologue/epilogue optimization.

gcc/ChangeLog:

2019-03-20  Andreas Krebbel  <krebbel@linux.ibm.com>

PR target/89775
* config/s390/s390.c (global_not_special_regno_p): Move to make it
available to ...
(s390_optimize_register_info): Use global_not_special_regno_p to
check for global regs.

2019-03-20  Jakub Jelinek  <jakub@redhat.com>

PR target/89775
* gcc.target/s390/pr89775-1.c: New test.
* gcc.target/s390/pr89775-2.c: New test.

From-SVN: r269823

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/pr89775-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/pr89775-2.c [new file with mode: 0644]

index 9b32d9352cc185e6d229c8aee080c508f4018167..7774af878622c7866b4d607a75d74f1b7f875e69 100644 (file)
@@ -1,3 +1,11 @@
+2019-03-20  Andreas Krebbel  <krebbel@linux.ibm.com>
+
+       PR target/89775
+       * config/s390/s390.c (global_not_special_regno_p): Move to make it
+       available to ...
+       (s390_optimize_register_info): Use global_not_special_regno_p to
+       check for global regs.
+
 2019-03-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/89752
index 41f2665a73a7cad7e7a4d33cd00fc54d042165f2..5f26437bed907e43c664c347cfc71ad2b3d4750c 100644 (file)
@@ -9588,6 +9588,21 @@ s390_register_info ()
   s390_register_info_stdarg_gpr ();
 }
 
+/* Return true if REGNO is a global register, but not one
+   of the special ones that need to be saved/restored in anyway.  */
+
+static inline bool
+global_not_special_regno_p (int regno)
+{
+  return (global_regs[regno]
+         /* These registers are special and need to be
+            restored in any case.  */
+         && !(regno == STACK_POINTER_REGNUM
+              || regno == RETURN_REGNUM
+              || regno == BASE_REGNUM
+              || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM)));
+}
+
 /* This function is called by s390_optimize_prologue in order to get
    rid of unnecessary GPR save/restore instructions.  The register info
    for the GPRs is re-computed and the ranges are re-calculated.  */
@@ -9602,8 +9617,10 @@ s390_optimize_register_info ()
 
   s390_regs_ever_clobbered (clobbered_regs);
 
+  /* Global registers do not need to be saved and restored unless it
+     is one of our special regs.  (r12, r13, r14, or r15).  */
   for (i = 0; i < 32; i++)
-    clobbered_regs[i] = clobbered_regs[i] && !global_regs[i];
+    clobbered_regs[i] = clobbered_regs[i] && !global_not_special_regno_p (i);
 
   /* There is still special treatment needed for cases invisible to
      s390_regs_ever_clobbered.  */
@@ -10345,21 +10362,6 @@ restore_fpr (rtx base, int offset, int regnum)
   return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
 }
 
-/* Return true if REGNO is a global register, but not one
-   of the special ones that need to be saved/restored in anyway.  */
-
-static inline bool
-global_not_special_regno_p (int regno)
-{
-  return (global_regs[regno]
-         /* These registers are special and need to be
-            restored in any case.  */
-         && !(regno == STACK_POINTER_REGNUM
-              || regno == RETURN_REGNUM
-              || regno == BASE_REGNUM
-              || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM)));
-}
-
 /* Generate insn to save registers FIRST to LAST into
    the register save area located at offset OFFSET
    relative to register BASE.  */
index b6a42d945a3330d77b8be83712dd3c4abcf51a20..00d0e9711e3f365ae0ae27843de886ff62616b6c 100644 (file)
@@ -1,3 +1,9 @@
+2019-03-20  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/89775
+       * gcc.target/s390/pr89775-1.c: New test.
+       * gcc.target/s390/pr89775-2.c: New test.
+
 2019-03-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/89752
diff --git a/gcc/testsuite/gcc.target/s390/pr89775-1.c b/gcc/testsuite/gcc.target/s390/pr89775-1.c
new file mode 100644 (file)
index 0000000..2c0f6fd
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR target/89775 */
+/* { dg-do run } */
+/* { dg-options "-O0 -fomit-frame-pointer" } */
+/* { dg-additional-sources "pr89775-2.c" } */
+
+register void *sp __asm ("15");
+
+__attribute__((noipa)) int
+foo (const char *a, const char *b)
+{
+  while (1)
+    {
+      char c = *a++;
+      if (c != *b++) return 0;
+      if (c == '\0') return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr89775-2.c b/gcc/testsuite/gcc.target/s390/pr89775-2.c
new file mode 100644 (file)
index 0000000..645661e
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR target/89775 */
+/* { dg-do compile } */
+
+extern int foo (const char *, const char *);
+
+__attribute__((noipa)) void
+bar (const char *p)
+{
+  static const char *x;
+  if (!x)
+    x = p;
+  else if (p != x)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  char a[8] = "abcdefg";
+  bar (a);
+  if (foo (a, a) != 1)
+    __builtin_abort ();
+  bar (a);
+  return 0;
+}