diff mbox series

[Committed] S/390: Fix PR89775. Stackpointer save/restore instructions removed

Message ID 1553095832-17637-1-git-send-email-krebbel@linux.ibm.com
State New
Headers show
Series [Committed] S/390: Fix PR89775. Stackpointer save/restore instructions removed | expand

Commit Message

Andreas Krebbel March 20, 2019, 3:30 p.m. UTC
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.

Bootstrapped and regression tested on s390x.

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.
---
 gcc/config/s390/s390.c                    | 34 ++++++++++++++++---------------
 gcc/testsuite/gcc.target/s390/pr89775-1.c | 17 ++++++++++++++++
 gcc/testsuite/gcc.target/s390/pr89775-2.c | 25 +++++++++++++++++++++++
 3 files changed, 60 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/pr89775-1.c
 create mode 100644 gcc/testsuite/gcc.target/s390/pr89775-2.c
diff mbox series

Patch

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 41f2665..5f26437 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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.  */
diff --git a/gcc/testsuite/gcc.target/s390/pr89775-1.c b/gcc/testsuite/gcc.target/s390/pr89775-1.c
new file mode 100644
index 0000000..2c0f6fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr89775-1.c
@@ -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
index 0000000..645661e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr89775-2.c
@@ -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;
+}