]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
S/390: PR69709 Fix risbg splitter
authorAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 26 Feb 2016 18:03:51 +0000 (18:03 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 26 Feb 2016 18:03:51 +0000 (18:03 +0000)
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  <rth@redhat.com>

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  <krebbel@linux.vnet.ibm.com>

PR target/69709
* gcc.target/s390/pr69709.c: New test.

From-SVN: r233752

gcc/ChangeLog
gcc/config/s390/s390.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/pr69709.c [new file with mode: 0644]

index 6550115c9fdb89532127ae95a3ee91d811b90a3d..2668f2e7c694d01fb025a7d109a2e6d7ec040732 100644 (file)
@@ -1,3 +1,10 @@
+2016-02-26  Richard Henderson  <rth@redhat.com>
+
+       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  <mjambor@suse.cz>
 
        PR hsa/69568
index 2c90eae0fab3234a4fcadb38f2c7c124e87385fa..8f92018f0b0586318c247ef2df500c811fbdcb64 100644 (file)
                 (ashift:GPR (match_operand:GPR 3 "nonimmediate_operand" "")
                             (match_operand:GPR 4 "nonzero_shift_count_operand" ""))))]
   "TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= <bitsize>"
-  [(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>mode);
+    }
+  else
+    operands[6] = operands[0];
 })
 
 (define_split
                               (match_operand:GPR 4 "nonzero_shift_count_operand" ""))))
      (clobber (reg:CC CC_REGNUM))])]
   "TARGET_Z10 && !TARGET_ZEC12 && UINTVAL (operands[2]) + UINTVAL (operands[4]) >= <bitsize>"
-  [(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>mode);
+    }
+  else
+    operands[6] = operands[0];
 })
 
 (define_insn "*r<noxa>sbg_<mode>_noshift"
index 99e0f2ff1d6344c0d92a100dd4ad84202b7132f1..a70a06970bc665928eb39b822507e162c8d7ad0d 100644 (file)
@@ -1,3 +1,8 @@
+2016-02-26  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
+       PR target/69709
+       * gcc.target/s390/pr69709.c: New test.
+
 2016-02-26  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        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 (file)
index 0000000..e9aa024
--- /dev/null
@@ -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;
+}