s390x: Fix popcounthi2_z196 expander [PR93533]
authorJakub Jelinek <jakub@redhat.com>
Mon, 3 Feb 2020 08:00:19 +0000 (09:00 +0100)
committerJakub Jelinek <jakub@redhat.com>
Mon, 3 Feb 2020 08:03:12 +0000 (09:03 +0100)
The following testcase started to ICE when .POPCOUNT matching has been added
to match.pd; we had __builtin_popcount*, but nothing would use the
popcounthi2 expander before.

The problem is that the popcounthi2_z196 expander doesn't emit valid RTL:
error: unrecognizable insn:
(insn 138 137 139 27 (set (reg:SI 190)
        (ashift:SI (reg:HI 95 [ _105 ])
            (const_int 8 [0x8]))) -1
     (nil))
during RTL pass: vregs
The following patch is an attempt to fix that, furthermore I've tried to
slightly simplify it as well, it makes no sense to me to perform
(x + (x << 8)) >> 8 when we need to either zero extend or mask the result
at the end in order to avoid bits from above HImode to affect it, when we
can do
(x + (x >> 8)) & 0xff (or zero extension).

2020-02-03  Jakub Jelinek  <jakub@redhat.com>

PR target/93533
* config/s390/s390.md (popcounthi2_z196): Fix up expander to emit
valid RTL to sum up the lowest and second lowest bytes of the popcnt
result.

* gcc.c-torture/compile/pr93533.c: New test.
* gcc.target/s390/pr93533.c: New test.

gcc/ChangeLog
gcc/config/s390/s390.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr93533.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/pr93533.c [new file with mode: 0644]

index 3c0f1176eadba1df60378cf70a9981f42d6d5e4e..2cb1b9f7361ccdd6ea6d8cd90d8f3e5b45c96176 100644 (file)
@@ -1,3 +1,10 @@
+2020-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/93533
+       * config/s390/s390.md (popcounthi2_z196): Fix up expander to emit
+       valid RTL to sum up the lowest and second lowest bytes of the popcnt
+       result.
+
 2020-02-02  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR rtl-optimization/91333
index 2959d8c0f17187f806d77032ec13ebc4bfe6f518..e37ba49444a3569ecdc129493a0cb74b078caf8f 100644 (file)
 })
 
 (define_expand "popcounthi2_z196"
-  [; popcnt op0, op1
-   (parallel [(set (match_operand:HI 0 "register_operand" "")
+  [; popcnt op2, op1
+   (parallel [(set (match_dup 2)
                   (unspec:HI [(match_operand:HI 1 "register_operand")]
                              UNSPEC_POPCNT))
              (clobber (reg:CC CC_REGNUM))])
-   ; sllk op2, op0, 8
-   (set (match_dup 2)
-       (ashift:SI (match_dup 0) (const_int 8)))
-   ; ar op0, op2
-   (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
+   ; lr op3, op2
+   (set (match_dup 3) (subreg:SI (match_dup 2) 0))
+   ; srl op4, op3, 8
+   (set (match_dup 4) (lshiftrt:SI (match_dup 3) (const_int 8)))
+   ; ar op3, op4
+   (parallel [(set (match_dup 3) (plus:SI (match_dup 3) (match_dup 4)))
              (clobber (reg:CC CC_REGNUM))])
-   ; srl op0, op0, 8
-   (set (match_dup 0) (lshiftrt:HI (match_dup 0) (const_int 8)))]
+   ; llgc op0, op3
+   (parallel [(set (match_operand:HI 0 "register_operand" "")
+                  (and:HI (subreg:HI (match_dup 3) 2) (const_int 255)))
+             (clobber (reg:CC CC_REGNUM))])]
   "TARGET_Z196"
-  "operands[2] = gen_reg_rtx (SImode);")
+{
+  operands[2] = gen_reg_rtx (HImode);
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = gen_reg_rtx (SImode);
+})
 
 (define_expand "popcounthi2"
   [(set (match_dup 2)
index 5471778da0babbf2178f159610420bc501b08026..86b9edcad56813b77a19f7d2c0ab68badc3d95d3 100644 (file)
@@ -1,4 +1,10 @@
-2020-02-03  Jun Ma <JunMa@linux.alibaba.com>
+2020-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/93533
+       * gcc.c-torture/compile/pr93533.c: New test.
+       * gcc.target/s390/pr93533.c: New test.
+
+2020-02-03  Jun Ma  <JunMa@linux.alibaba.com>
 
        * g++.dg/coroutines/co-await-04-control-flow.C: Add label.
 
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr93533.c b/gcc/testsuite/gcc.c-torture/compile/pr93533.c
new file mode 100644 (file)
index 0000000..8b9b1be
--- /dev/null
@@ -0,0 +1,9 @@
+/* PR target/93533 */
+
+unsigned
+foo (unsigned short a)
+{
+  a = a - (a >> 1 & 21845);
+  a = (a & 13107) + (a >> 2 & 13107);
+  return (unsigned short) ((a + (a >> 4) & 3855) * 257) >> 8;
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr93533.c b/gcc/testsuite/gcc.target/s390/pr93533.c
new file mode 100644 (file)
index 0000000..1a49c73
--- /dev/null
@@ -0,0 +1,5 @@
+/* PR target/93533 */
+/* { dg-do compile } */
+/* { dg-options "-march=z196 -O2" } */
+
+#include "../../gcc.c-torture/compile/pr93533.c"