From 3ad7fed1cc87d281881757477c5197d9d3a97232 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 20 Mar 2019 15:28:38 +0000 Subject: [PATCH] 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 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 PR target/89775 * gcc.target/s390/pr89775-1.c: New test. * gcc.target/s390/pr89775-2.c: New test. From-SVN: r269823 --- gcc/ChangeLog | 8 ++++++ gcc/config/s390/s390.c | 34 ++++++++++++----------- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.target/s390/pr89775-1.c | 17 ++++++++++++ gcc/testsuite/gcc.target/s390/pr89775-2.c | 25 +++++++++++++++++ 5 files changed, 74 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 --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b32d9352cc..7774af87862 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-03-20 Andreas Krebbel + + 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 PR target/89752 diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 41f2665a73a..5f26437bed9 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 b6a42d945a3..00d0e9711e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-03-20 Jakub Jelinek + + PR target/89775 + * gcc.target/s390/pr89775-1.c: New test. + * gcc.target/s390/pr89775-2.c: New test. + 2019-03-20 Jakub Jelinek 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 index 00000000000..2c0f6fd1f9b --- /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 00000000000..645661e5852 --- /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; +} -- 2.30.2