diff mbox

S/390: PR69709 Fix risbg splitter

Message ID 1456498858-28756-1-git-send-email-krebbel@linux.vnet.ibm.com
State New
Headers show

Commit Message

Andreas Krebbel Feb. 26, 2016, 3 p.m. UTC
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.
---
 gcc/config/s390/s390.md                 | 24 ++++++++++++++++----
 gcc/testsuite/gcc.target/s390/pr69709.c | 39 +++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/pr69709.c
diff mbox

Patch

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 2c90eae..8f92018 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]) >= <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
@@ -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]) >= <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"
diff --git a/gcc/testsuite/gcc.target/s390/pr69709.c b/gcc/testsuite/gcc.target/s390/pr69709.c
new file mode 100644
index 0000000..e9aa024
--- /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;
+}