From 1d11f7ce7081fc9e28ac0a66c6b3f6b7950971d6 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 26 Feb 2016 18:03:51 +0000 Subject: [PATCH] S/390: PR69709 Fix risbg splitter This fixes a wrong code generation problem with the splitters introduced with that patch: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01840.html The target operand is used as temporary. This fails if it matches the source of the left shift which is read after writing the temporary. Thanks to Dominik for debugging it and thanks to Richard for the fix! Bootstrapped and regtested on s390x with-arch=z13. Bye, -Andreas- gcc/ChangeLog: 2016-02-26 Richard Henderson PR target/69709 * config/s390/s390.md (risbg and risbgn splitters): Allocate new pseudo in case the target rtx matches the source of the left shift. gcc/testsuite/ChangeLog: 2016-02-26 Andreas Krebbel PR target/69709 * gcc.target/s390/pr69709.c: New test. From-SVN: r233752 --- gcc/ChangeLog | 7 +++++ gcc/config/s390/s390.md | 24 ++++++++++++--- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.target/s390/pr69709.c | 39 +++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/pr69709.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6550115c9fdb..2668f2e7c694 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-02-26 Richard Henderson + + PR target/69709 + * config/s390/s390.md (risbg and risbgn splitters): Allocate new + pseudo in case the target rtx matches the source of the left + shift. + 2016-02-26 Martin Jambor PR hsa/69568 diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 2c90eae0fab3..8f92018f0b05 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3876,13 +3876,21 @@ (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "") (match_operand:GPR 4 "nonzero_shift_count_operand" ""))))] "TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= " - [(set (match_dup 0) + [(set (match_dup 6) (lshiftrt:GPR (match_dup 1) (match_dup 2))) (set (match_dup 0) - (ior:GPR (and:GPR (match_dup 0) (match_dup 5)) + (ior:GPR (and:GPR (match_dup 6) (match_dup 5)) (ashift:GPR (match_dup 3) (match_dup 4))))] { operands[5] = GEN_INT ((1UL << UINTVAL (operands[4])) - 1); + if (rtx_equal_p (operands[0], operands[3])) + { + if (!can_create_pseudo_p ()) + FAIL; + operands[6] = gen_reg_rtx (mode); + } + else + operands[6] = operands[0]; }) (define_split @@ -3894,15 +3902,23 @@ (match_operand:GPR 4 "nonzero_shift_count_operand" "")))) (clobber (reg:CC CC_REGNUM))])] "TARGET_Z10 && !TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= " - [(set (match_dup 0) + [(set (match_dup 6) (lshiftrt:GPR (match_dup 1) (match_dup 2))) (parallel [(set (match_dup 0) - (ior:GPR (and:GPR (match_dup 0) (match_dup 5)) + (ior:GPR (and:GPR (match_dup 6) (match_dup 5)) (ashift:GPR (match_dup 3) (match_dup 4)))) (clobber (reg:CC CC_REGNUM))])] { operands[5] = GEN_INT ((1UL << UINTVAL (operands[4])) - 1); + if (rtx_equal_p (operands[0], operands[3])) + { + if (!can_create_pseudo_p ()) + FAIL; + operands[6] = gen_reg_rtx (mode); + } + else + operands[6] = operands[0]; }) (define_insn "*rsbg__noshift" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 99e0f2ff1d63..a70a06970bc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-02-26 Andreas Krebbel + + PR target/69709 + * gcc.target/s390/pr69709.c: New test. + 2016-02-26 Kyrylo Tkachov PR target/69245 diff --git a/gcc/testsuite/gcc.target/s390/pr69709.c b/gcc/testsuite/gcc.target/s390/pr69709.c new file mode 100644 index 000000000000..e9aa024521d5 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/pr69709.c @@ -0,0 +1,39 @@ +/* PR69709 This testcase used to fail due to a broken risbg + splitter. */ + +/* { dg-do run } */ +/* { dg-options "-O3 -march=z10" } */ + + +typedef struct +{ + unsigned int sig[2]; +} +val_t; + +unsigned int __attribute__ ((noinline)) +div_significands (const val_t * a) +{ + val_t u = *a; + int bit = 64; + unsigned int r; + do + { + u.sig[1] = (u.sig[1] << 1) | (u.sig[0] >> 31); + u.sig[0] = 42; + + if (bit == 64) + r = u.sig[1]; + } + while (--bit >= 0); + return r; +} + +int +main (void) +{ + val_t a = { { 0x1, 0x1 } }; + if (div_significands (&a) != 2) + __builtin_abort (); + return 0; +} -- 2.47.2