diff options
author | Andreas Krebbel <krebbel@gcc.gnu.org> | 2019-03-20 15:28:38 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2019-03-20 15:28:38 +0000 |
commit | 3ad7fed1cc87d281881757477c5197d9d3a97232 (patch) | |
tree | ba232f7a2cef02750efc9fe2bced2ecbf161e80e /gcc | |
parent | a5b821e448e6debe73e1154128b4ea6f7f73fbdd (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/s390/pr89775-1.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/s390/pr89775-2.c | 25 |
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; +} |