Three new tests verify that GCC generates still code that uses
the 'rev' instruction instead of using predicated vector tails
to vectorise 32-bit byte-order-reversal code.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/sve/slp_rev_32_1.c: New test.
        * gcc.target/aarch64/sve/slp_rev_32_2.c: New test.
        * gcc.target/aarch64/sve/slp_rev_32_3.c: New test.
---
 .../gcc.target/aarch64/sve/slp_rev_32_1.c     | 25 ++++++++++++++++
 .../gcc.target/aarch64/sve/slp_rev_32_2.c     | 29 +++++++++++++++++++
 .../gcc.target/aarch64/sve/slp_rev_32_3.c     | 26 +++++++++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_3.c

diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_1.c
new file mode 100644
index 00000000000..fb07c2b86c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_1.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -march=armv8.2-a+sve" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* If the compiler mistakenly vectorizes byte order reversal
+ * then the resultant code is inevitably less efficient than a
+ * rev instruction.  Guard against such regressions.
+ */
+typedef unsigned int __u32;
+typedef unsigned char __u8;
+
+/*
+** rev:
+**     rev     w1, w1
+**     str     w1, \[x0\]
+**     ret
+*/
+void
+rev (__u8 (*dst)[4], __u32 src)
+{
+  (*dst)[0] = src >> 24;
+  (*dst)[1] = src >> 16;
+  (*dst)[2] = src >> 8;
+  (*dst)[3] = src >> 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_2.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_2.c
new file mode 100644
index 00000000000..358017b6587
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -march=armv8.2-a+sve" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* If the compiler mistakenly vectorizes byte order reversal
+ * then the resultant code is inevitably less efficient than a
+ * rev instruction.  Guard against such regressions.
+ */
+typedef unsigned int __u32;
+typedef unsigned char __u8;
+
+/*
+** rev2:
+**     ldr     w0, \[x0\]
+**     rev     w0, w0
+**     ret
+*/
+__u32
+rev2 (const __u8 (*src)[4])
+{
+  __u32 dst = 0;
+
+  dst |= (__u32) (*src)[3] << 0;
+  dst |= (__u32) (*src)[2] << 8;
+  dst |= (__u32) (*src)[1] << 16;
+  dst |= (__u32) (*src)[0] << 24;
+
+  return dst;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_3.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_3.c
new file mode 100644
index 00000000000..dbddaebf1e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_rev_32_3.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -march=armv8.2-a+sve" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* If the compiler mistakenly vectorizes byte order reversal
+ * then the resultant code is inevitably less efficient than a
+ * rev instruction.  Guard against such regressions.
+ */
+typedef unsigned char __u8;
+
+/*
+** rev3:
+**     ldr     w1, \[x1\]
+**     rev     w1, w1
+**     str     w1, \[x0\]
+**     ret
+*/
+void
+rev3 (unsigned char (*__restrict dst)[4],
+      const unsigned char (*__restrict src)[4])
+{
+  (*dst)[0] = (*src)[3];
+  (*dst)[1] = (*src)[2];
+  (*dst)[2] = (*src)[1];
+  (*dst)[3] = (*src)[0];
+}
-- 
2.43.0

Reply via email to