From 582fe481f4bb800f822035b8a17000d0efaecef4 Mon Sep 17 00:00:00 2001
From: Andreas Krebbel <krebbel@linux.ibm.com>
Date: Mon, 20 Apr 2020 20:06:53 +0200
Subject: [PATCH] S/390: Fix PR94666

The vector popcount expanders use a hardcoded subreg.  This might lead
to double subregs being generated which then fail to match.  With this
patch simplify_gen_subreg is used instead to fold the subregs.

gcc/ChangeLog:

2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>

	* config/s390/vector.md ("popcountv8hi2_vx", "popcountv4si2_vx")
	("popcountv2di2_vx"): Use simplify_gen_subreg.

gcc/testsuite/ChangeLog:

2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>

	* g++.dg/pr94666.C: New test.
---
 gcc/ChangeLog                  |  5 +++++
 gcc/config/s390/vector.md      | 10 +++++++---
 gcc/testsuite/ChangeLog        |  4 ++++
 gcc/testsuite/g++.dg/pr94666.C | 20 ++++++++++++++++++++
 4 files changed, 36 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr94666.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ed3541d1264c..721928d931d2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>
+
+	* config/s390/vector.md ("popcountv8hi2_vx", "popcountv4si2_vx")
+	("popcountv2di2_vx"): Use simplify_gen_subreg.
+
 2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>
 
 	PR target/94613
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 9d3df9813c94..08f2d4cbda69 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -871,7 +871,7 @@
 
 (define_expand "popcountv8hi2_vx"
   [(set (match_dup 2)
-	(unspec:V16QI [(subreg:V16QI (match_operand:V8HI 1 "register_operand" "v") 0)]
+	(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")]
 		      UNSPEC_POPCNT))
    ; Make a copy of the result
    (set (match_dup 3) (match_dup 2))
@@ -903,6 +903,8 @@
 ]
   "TARGET_VX && !TARGET_VXE"
 {
+  operands[1] = simplify_gen_subreg (V16QImode, operands[1],
+				     V8HImode, 0);
   operands[2] = gen_reg_rtx (V16QImode);
   operands[3] = gen_reg_rtx (V16QImode);
   operands[4] = gen_reg_rtx (V16QImode);
@@ -911,20 +913,21 @@
 
 (define_expand "popcountv4si2_vx"
   [(set (match_dup 2)
-	(unspec:V16QI [(subreg:V16QI (match_operand:V4SI 1 "register_operand" "v") 0)]
+	(unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")]
 		      UNSPEC_POPCNT))
    (set (match_operand:V4SI 0 "register_operand" "=v")
 	(unspec:V4SI [(match_dup 2) (match_dup 3)]
 		     UNSPEC_VEC_VSUM))]
   "TARGET_VX && !TARGET_VXE"
 {
+  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V4SImode, 0);
   operands[2] = gen_reg_rtx (V16QImode);
   operands[3] = force_reg (V16QImode, CONST0_RTX (V16QImode));
 })
 
 (define_expand "popcountv2di2_vx"
   [(set (match_dup 2)
-	(unspec:V16QI [(subreg:V16QI (match_operand:V2DI 1 "register_operand" "v") 0)]
+	(unspec:V16QI [(match_operand:V2DI 1 "register_operand" "v")]
 		      UNSPEC_POPCNT))
    (set (match_dup 3)
 	(unspec:V4SI [(match_dup 2) (match_dup 4)]
@@ -934,6 +937,7 @@
 		     UNSPEC_VEC_VSUMG))]
   "TARGET_VX && !TARGET_VXE"
 {
+  operands[1] = simplify_gen_subreg (V16QImode, operands[1], V2DImode, 0);
   operands[2] = gen_reg_rtx (V16QImode);
   operands[3] = gen_reg_rtx (V4SImode);
   operands[4] = force_reg (V16QImode, CONST0_RTX (V16QImode));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 117eed9e35b9..ce31ed0cd448 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>
+
+	* g++.dg/pr94666.C: New test.
+
 2020-04-20  Andreas Krebbel  <krebbel@linux.ibm.com>
 
 	PR target/94613
diff --git a/gcc/testsuite/g++.dg/pr94666.C b/gcc/testsuite/g++.dg/pr94666.C
new file mode 100644
index 000000000000..a9bfb24f7952
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr94666.C
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-O3" }
+// { dg-additional-options "-march=z13" { target s390*-*-* } }
+
+int a, c;
+struct A {
+  int e() {
+    int f;
+    for (int b = 0; b < 4; b++) {
+      a = __builtin_popcountl(d[b]);
+      f += a;
+    }
+    return f;
+  }
+  long d[4];
+} * g;
+void h() {
+  for (int b; b; b++)
+    c += g[b].e();
+}
-- 
GitLab