[AArch64] Add support for SVE CLS and CLZ
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 14 Aug 2019 09:02:47 +0000 (09:02 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 14 Aug 2019 09:02:47 +0000 (09:02 +0000)
This patch adds support for unpredicated SVE CLS and CLZ.  A later patch
will add support for predicated unary integer arithmetic.

2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* config/aarch64/iterators.md (SVE_INT_UNARY): Add clrsb and clz.
(optab, sve_int_op): Handle them.
* config/aarch64/aarch64-sve.md: Expand comment.

gcc/testsuite/
* gcc.target/aarch64/vect-clz.c: Force SVE off.
* gcc.target/aarch64/sve/clrsb_1.c: New test.
* gcc.target/aarch64/sve/clrsb_1_run.c: Likewise.
* gcc.target/aarch64/sve/clz_1.c: Likewise.
* gcc.target/aarch64/sve/clz_1_run.c: Likewise.

From-SVN: r274437

gcc/ChangeLog
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sve/clrsb_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/clrsb_1_run.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/clz_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/clz_1_run.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/vect-clz.c

index c325192459188fc433b38ae0142942a8aee3e50d..b5b4414911c4bca8c8bb2ce1511f86b0af4e2d47 100644 (file)
@@ -1,3 +1,9 @@
+2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * config/aarch64/iterators.md (SVE_INT_UNARY): Add clrsb and clz.
+       (optab, sve_int_op): Handle them.
+       * config/aarch64/aarch64-sve.md: Expand comment.
+
 2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/aarch64/predicates.md (const_1_to_3_operand): New predicate.
index 6fed4efaaaa8701f9240ba4678d952df7ddc4073..7e696d8c72317c53c660d3ba1c940d625e2a1a69 100644 (file)
 ;; -------------------------------------------------------------------------
 ;; Includes:
 ;; - ABS
+;; - CLS (= clrsb)
+;; - CLZ
 ;; - CNT (= popcount)
 ;; - NEG
 ;; - NOT
index 75e672b8609fb6f23df7af781db4300e56d885e3..bc5b96a29d45191de4077a93edca595dd121e605 100644 (file)
 (define_code_iterator FAC_COMPARISONS [lt le ge gt])
 
 ;; SVE integer unary operations.
-(define_code_iterator SVE_INT_UNARY [abs neg not popcount])
+(define_code_iterator SVE_INT_UNARY [abs neg not clrsb clz popcount])
 
 ;; SVE integer binary operations.
 (define_code_iterator SVE_INT_BINARY [plus minus mult smax umax smin umin
                         (unsigned_fix "fixuns")
                         (float "float")
                         (unsigned_float "floatuns")
+                        (clrsb "clrsb")
+                        (clz "clz")
                         (popcount "popcount")
                         (and "and")
                         (ior "ior")
                              (ior "orr")
                              (xor "eor")
                              (not "not")
+                             (clrsb "cls")
+                             (clz "clz")
                              (popcount "cnt")])
 
 (define_code_attr sve_int_op_rev [(plus "add")
index c33667ead1860797a4de210a4eb5948071b35845..1a2d800361ab21115695774ff48fc824713e1cb4 100644 (file)
@@ -1,3 +1,11 @@
+2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * gcc.target/aarch64/vect-clz.c: Force SVE off.
+       * gcc.target/aarch64/sve/clrsb_1.c: New test.
+       * gcc.target/aarch64/sve/clrsb_1_run.c: Likewise.
+       * gcc.target/aarch64/sve/clz_1.c: Likewise.
+       * gcc.target/aarch64/sve/clz_1_run.c: Likewise.
+
 2019-08-14  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/aarch64/sve/adr_1.c: New test.
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/clrsb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/clrsb_1.c
new file mode 100644 (file)
index 0000000..bdc9856
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O2 -ftree-vectorize --save-temps" } */
+
+#include <stdint.h>
+
+void __attribute__ ((noinline, noclone))
+clrsb_32 (unsigned int *restrict dst, uint32_t *restrict src, int size)
+{
+  for (int i = 0; i < size; ++i)
+    dst[i] = __builtin_clrsb (src[i]);
+}
+
+void __attribute__ ((noinline, noclone))
+clrsb_64 (unsigned int *restrict dst, uint64_t *restrict src, int size)
+{
+  for (int i = 0; i < size; ++i)
+    dst[i] = __builtin_clrsbll (src[i]);
+}
+
+/* { dg-final { scan-assembler-times {\tcls\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tcls\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 2 } } */
+/* { dg-final { scan-assembler-times {\tuzp1\tz[0-9]+\.s, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/clrsb_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve/clrsb_1_run.c
new file mode 100644 (file)
index 0000000..287630d
--- /dev/null
@@ -0,0 +1,50 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "clrsb_1.c"
+
+extern void abort (void) __attribute__ ((noreturn));
+
+unsigned int data[] = {
+  0xffffff80, 24,
+  0xffffffff, 31,
+  0x00000000, 31,
+  0x80000000, 0,
+  0x7fffffff, 0,
+  0x000003ff, 21,
+  0x1fffffff, 2,
+  0x0000ffff, 15,
+  0xffff0000, 15
+};
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+  unsigned int count = sizeof (data) / sizeof (data[0]) / 2;
+
+  uint32_t in32[count];
+  unsigned int out32[count];
+  for (unsigned int i = 0; i < count; ++i)
+    {
+      in32[i] = data[i * 2];
+      asm volatile ("" ::: "memory");
+    }
+  clrsb_32 (out32, in32, count);
+  for (unsigned int i = 0; i < count; ++i)
+    if (out32[i] != data[i * 2 + 1])
+      abort ();
+
+  uint64_t in64[count];
+  unsigned int out64[count];
+  for (unsigned int i = 0; i < count; ++i)
+    {
+      in64[i] = (uint64_t) data[i * 2] << 32;
+      asm volatile ("" ::: "memory");
+    }
+  clrsb_64 (out64, in64, count);
+  for (unsigned int i = 0; i < count; ++i)
+    if (out64[i] != (data[i * 2] ? data[i * 2 + 1] : 63))
+      abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/clz_1.c b/gcc/testsuite/gcc.target/aarch64/sve/clz_1.c
new file mode 100644 (file)
index 0000000..0c7a4e6
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O2 -ftree-vectorize --save-temps" } */
+
+#include <stdint.h>
+
+void __attribute__ ((noinline, noclone))
+clz_32 (unsigned int *restrict dst, uint32_t *restrict src, int size)
+{
+  for (int i = 0; i < size; ++i)
+    dst[i] = __builtin_clz (src[i]);
+}
+
+void __attribute__ ((noinline, noclone))
+clz_64 (unsigned int *restrict dst, uint64_t *restrict src, int size)
+{
+  for (int i = 0; i < size; ++i)
+    dst[i] = __builtin_clzll (src[i]);
+}
+
+/* { dg-final { scan-assembler-times {\tclz\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tclz\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 2 } } */
+/* { dg-final { scan-assembler-times {\tuzp1\tz[0-9]+\.s, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/clz_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve/clz_1_run.c
new file mode 100644 (file)
index 0000000..12d9cf2
--- /dev/null
@@ -0,0 +1,50 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "clz_1.c"
+
+extern void abort (void) __attribute__ ((noreturn));
+
+unsigned int data[] = {
+  0xffffff80, 0,
+  0xffffffff, 0,
+  0x00000000, 32,
+  0x80000000, 0,
+  0x7fffffff, 1,
+  0x000003ff, 22,
+  0x1fffffff, 3,
+  0x0000ffff, 16,
+  0xffff0000, 0
+};
+
+int __attribute__ ((optimize (1)))
+main (void)
+{
+  unsigned int count = sizeof (data) / sizeof (data[0]) / 2;
+
+  uint32_t in32[count];
+  unsigned int out32[count];
+  for (unsigned int i = 0; i < count; ++i)
+    {
+      in32[i] = data[i * 2];
+      asm volatile ("" ::: "memory");
+    }
+  clz_32 (out32, in32, count);
+  for (unsigned int i = 0; i < count; ++i)
+    if (out32[i] != data[i * 2 + 1])
+      abort ();
+
+  uint64_t in64[count];
+  unsigned int out64[count];
+  for (unsigned int i = 0; i < count; ++i)
+    {
+      in64[i] = (uint64_t) data[i * 2] << 10;
+      asm volatile ("" ::: "memory");
+    }
+  clz_64 (out64, in64, count);
+  for (unsigned int i = 0; i < count; ++i)
+    if (out64[i] != (data[i * 2] ? data[i * 2 + 1] + 22 : 64))
+      abort ();
+
+  return 0;
+}
index 044fa9e996ea8ea25e3682c8581dde117e546ca6..cd181c3461df06ad7f2d686769d96a0a5fd2e796 100644 (file)
@@ -1,6 +1,8 @@
 /* { dg-do run } */
 /* { dg-options "-O3 -save-temps -fno-inline -fno-vect-cost-model" } */
 
+#pragma GCC target "+nosve"
+
 extern void abort ();
 
 void