aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@gcc.gnu.org>2019-03-20 15:28:38 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2019-03-20 15:28:38 +0000
commit3ad7fed1cc87d281881757477c5197d9d3a97232 (patch)
treeba232f7a2cef02750efc9fe2bced2ecbf161e80e /gcc
parenta5b821e448e6debe73e1154128b4ea6f7f73fbdd (diff)
downloadgcc-3ad7fed1cc87d281881757477c5197d9d3a97232.zip
gcc-3ad7fed1cc87d281881757477c5197d9d3a97232.tar.gz
gcc-3ad7fed1cc87d281881757477c5197d9d3a97232.tar.bz2
S/390: Fix PR89775. Stackpointer save/restore instructions removed
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/s390/s390.c34
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/s390/pr89775-1.c17
-rw-r--r--gcc/testsuite/gcc.target/s390/pr89775-2.c25
5 files changed, 74 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b32d93..7774af8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
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/ChangeLog b/gcc/testsuite/ChangeLog
index b6a42d9..00d0e97 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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
* g++.target/aarch64/aarch64.exp: New file.
* g++.target/aarch64/pr89752.C: New test.
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;
+}