The attached patch rewrites the pr67443.c testcase in a different way so that the test still works with the changed allocation of globals pinned to registers. The test ist hopefully more robust now. The test ist hopefully more robust now. Tested on s390 and s390x biarch.
Ciao Dominik ^_^ ^_^ -- Dominik Vogt IBM Germany
gcc/testsuite/ChangeLog * gcc.target/s390/pr67443.c: Fix test case.
>From fe5dd36da6cea172a5cebdbc33a8a60cb5e0e9ad Mon Sep 17 00:00:00 2001 From: Dominik Vogt <v...@linux.vnet.ibm.com> Date: Wed, 20 Jul 2016 12:50:52 +0100 Subject: [PATCH] S/390: Fix pr67443.c. --- gcc/testsuite/gcc.target/s390/pr67443.c | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/gcc/testsuite/gcc.target/s390/pr67443.c b/gcc/testsuite/gcc.target/s390/pr67443.c index e011a11..771b56f 100644 --- a/gcc/testsuite/gcc.target/s390/pr67443.c +++ b/gcc/testsuite/gcc.target/s390/pr67443.c @@ -2,21 +2,10 @@ /* { dg-do run { target s390*-*-* } } */ /* { dg-prune-output "call-clobbered register used for global register variable" } */ -/* { dg-options "-march=z900 -fPIC -fomit-frame-pointer -O3" } */ +/* { dg-options "-march=z900 -fPIC -fomit-frame-pointer -O3 -save-temps" } */ #include <assert.h> -/* Block all registers except the first three argument registers. */ -register long r0 asm ("r0"); -register long r1 asm ("r1"); -register long r5 asm ("r5"); -register long r6 asm ("r6"); -register long r7 asm ("r7"); -register long r8 asm ("r8"); -register long r9 asm ("r9"); -register long r10 asm ("r10"); -register long r11 asm ("r11"); - struct s_t { unsigned f1 : 8; @@ -24,25 +13,40 @@ struct s_t }; __attribute__ ((noinline)) -void foo (struct s_t *ps, int c, int i) +int bar () { + return 0; +} + +__attribute__ ((noinline)) +void foo (struct s_t *ps, int c) +{ + int tmp; + /* Uses r2 as address register. */ ps->f1 = c; - /* The calculation of the value is so expensive that it's cheaper to spill ps - to the stack and reload it later (into a different register). - ==> Uses r4 as address register.*/ - ps->f2 = i + i % 3; + /* Clobber all registers that r2 could be stored into. */ + __asm__ __volatile__ ("" : : : "memory", + "r0","r1","r6","r7","r8","r9","r10","r11"); + /* Force that the pointer is evicted from r2 and stored on the stack. */ + tmp = bar (); + /* User the pointer again. It gets reloaded to a different register because + r2 is already occupied. */ + ps->f2 = tmp; /* If dead store elimination fails to detect that the address in r2 during - the first assignment is an alias of the address in r4 during the second + the first assignment is an alias of the address in rX during the second assignment, it eliminates the first assignment and the f1 field is not written (bug). */ } +/* Make sure that r2 is used only once as an address register for storing. + If this check fails, the test case needs to be fixed. + { dg-final { scan-assembler-times "\tst.\?\t.*,0\\(%r2\\)" 1 } } */ int main (void) { struct s_t s = { 0x01u, 0x020304u }; - foo (&s, 0, 0); + foo (&s, 0); assert (s.f1 == 0&& s.f2 == 0); return 0; -- 2.3.0