From 2b3e722a3ca1b9dcfff1c016e651d0d681de1af0 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Tue, 27 Oct 2020 20:57:39 +0100 Subject: [PATCH] Fix PR97497 This works around a limitation of gcse with handling of partially clobbered registers. With this patch our GOT pointer register r12 is not marked as partially clobbered anymore for the -m31 -mzarch -fpic combination. This is correct since all the bits in r12 we actually care about are in fact preserved. gcc/ChangeLog: PR rtl-optimization/97497 * config/s390/s390.c (s390_hard_regno_call_part_clobbered): Do not return true for r12 when -fpic is used. gcc/testsuite/ChangeLog: * gcc.target/s390/pr97497.c: New test. --- gcc/config/s390/s390.c | 7 +++++ gcc/testsuite/gcc.target/s390/pr97497.c | 36 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 gcc/testsuite/gcc.target/s390/pr97497.c diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f9b27f96fd7..3c3feb2769b 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -10376,9 +10376,16 @@ static bool s390_hard_regno_call_part_clobbered (unsigned int, unsigned int regno, machine_mode mode) { + /* For r12 we know that the only bits we actually care about are + preserved across function calls. Since r12 is a fixed reg all + accesses to r12 are generated by the backend. + + This workaround is necessary until gcse implements proper + tracking of partially clobbered registers. */ if (!TARGET_64BIT && TARGET_ZARCH && GET_MODE_SIZE (mode) > 4 + && (!flag_pic || regno != PIC_OFFSET_TABLE_REGNUM) && ((regno >= 6 && regno <= 15) || regno == 32)) return true; diff --git a/gcc/testsuite/gcc.target/s390/pr97497.c b/gcc/testsuite/gcc.target/s390/pr97497.c new file mode 100644 index 00000000000..460c8503f8c --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/pr97497.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -march=z900 -mzarch -fpic" } */ + +char *t; + +void __attribute__((noinline,noclone)) +bar(int a, char* b) +{ + if (a != 1) + __builtin_abort(); +} + +void __attribute__((noinline,noclone)) +baz(char* a, int b) +{ + if (b != 1) + __builtin_abort(); +} + +int __attribute__((noinline,noclone)) +foo (int a) +{ + bar (1, t); + if (a) + baz (t, 1); + + bar (1, t); +} + +int +main () +{ + foo (1); + + return 0; +} -- 2.30.2