New tests verify that sharing of masks does not
go wrong: masks must only be shared between SLP groups of
different sizes and different truth-vector types, where a
conversion ratio is satisfied, or between SLP groups of the same
size and truth-vector type.  However, this cannot be verified
solely using scan-assembler-times and scan_assembler-not because
the 'fre' (redundancy elimination) pass turns masks shared by
means of VIEW_CONVERT_EXPR back into separate constants.  It does
so even if each mask requires two instructions to set up (mov
and whilelo).

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/sve/slp_pred_11.c: New test.
        * gcc.target/aarch64/sve/slp_pred_12.c: New test.
        * gcc.target/aarch64/sve/slp_pred_13.c: New test.
        * gcc.target/aarch64/sve/slp_pred_14.c: New test.
        * gcc.target/aarch64/sve/slp_pred_15.c: New test.
---
 .../gcc.target/aarch64/sve/slp_pred_11.c      | 36 +++++++++++++
 .../gcc.target/aarch64/sve/slp_pred_12.c      | 51 +++++++++++++++++++
 .../gcc.target/aarch64/sve/slp_pred_13.c      | 45 ++++++++++++++++
 .../gcc.target/aarch64/sve/slp_pred_14.c      | 35 +++++++++++++
 .../gcc.target/aarch64/sve/slp_pred_15.c      | 36 +++++++++++++
 5 files changed, 203 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_pred_11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_pred_12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_pred_13.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_pred_14.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/slp_pred_15.c

diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_11.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_11.c
new file mode 100644
index 00000000000..d1ca8f4a5ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_11.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize 
--param=aarch64-autovec-preference=sve-only -msve-vector-bits=scalable 
-fdump-tree-slp2" } */
+
+#include <stdint.h>
+
+/* Test that SVE predicate masks are not shared between SLP groups of the same
+   size if they use different vector types that have different element sizes.  
*/
+
+void
+f (uint8_t *x, uint16_t *y)
+{
+  x[0] += 1;
+  x[1] += 2;
+  x[2] += 1;
+  x[3] += 2;
+  x[4] += 1;
+  x[5] += 2;
+  x[6] += 1;
+
+  y[0] += 1;
+  y[1] += 2;
+  y[2] += 1;
+  y[3] += 2;
+  y[4] += 1;
+  y[5] += 2;
+  y[6] += 1;
+}
+
+/* A single mask must not be shared between x and y in GIMPLE so expect two
+   masks to be set up.  */
+
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 7, \{ 
0, \.\.\. \}\)} 2 "slp2" } } */
+/* { dg-final { scan-tree-dump-not {VIEW_CONVERT_EXPR} "slp2" } } */
+
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.b, vl7\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.h, vl7\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_12.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_12.c
new file mode 100644
index 00000000000..3ec52099cbc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_12.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize 
--param=aarch64-autovec-preference=sve-only -msve-vector-bits=scalable 
-fdump-tree-slp2" } */
+
+#include <stdint.h>
+
+/* Test that SVE predicate masks are shared between SLP groups despite those
+   groups having different sizes and using vector types that have different
+   element sizes, if the ratio between element sizes is the reciprocal of the
+   ratio between group sizes.  */
+
+void
+f (uint8_t *x, uint32_t *y)
+{
+  x[0] += 1;
+  x[1] += 2;
+  x[2] += 1;
+  x[3] += 2;
+  x[4] += 1;
+  x[5] += 2;
+  x[6] += 1;
+  x[7] += 2;
+  x[8] += 1;
+  x[9] += 2;
+  x[10] += 1;
+  x[11] += 2;
+
+  y[0] += 1;
+  y[1] += 2;
+  y[2] += 1;
+}
+
+/* A twelve-element mask should be shared between x and y in GIMPLE, although y
+   has only three active elements.  Expect two conversions: one for the load
+   operation and one for the store operation.
+ */
+
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 12, 
\{ 0, \.\.\. \}\)} 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-times {VIEW_CONVERT_EXPR<vector\(\[4,4\]\) 
<signed-boolean:4>>\(slp_mask_[0-9]+\)} 2 "slp2" } } */
+
+/* Although the mask is shared in GIMPLE, the 'fre' (redundancy elimination)
+   pass converts it to separate constants.  It does so even if both masks
+   require a mov and whilelo (which is not the case here).  */
+
+/* { dg-final { scan-assembler-times {\tmov\tw[0-7], 12\n} 1 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, xzr, x[0-9]+\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+.b, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 1 } } */
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+.b, p[0-7], 
\[x[0-9]+[^]]*\]} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.s, vl3\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+.s, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 1 } } */
+/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+.s, p[0-7], 
\[x[0-9]+[^]]*\]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_13.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_13.c
new file mode 100644
index 00000000000..f0245e8df52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_13.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize 
--param=aarch64-autovec-preference=sve-only -msve-vector-bits=scalable 
-fdump-tree-slp2" } */
+
+#include <stdint.h>
+
+/* Test that SVE predicate masks are not shared between SLP groups of different
+   sizes that use different vector types, if the ratio between element sizes is
+   not the reciprocal of the ratio between group sizes.  */
+
+void
+f (uint8_t *x, uint16_t *y)
+{
+  x[0] += 1;
+  x[1] += 2;
+  x[2] += 1;
+  x[3] += 2;
+  x[4] += 1;
+  x[5] += 2;
+  x[6] += 1;
+  x[7] += 2;
+  x[8] += 1;
+  x[9] += 2;
+  x[10] += 1;
+  x[11] += 2;
+
+  y[0] += 1;
+  y[1] += 2;
+  y[2] += 1;
+}
+
+/* A single mask must not be shared between x and y in GIMPLE so expect two
+   masks to be set up.  */
+
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 12, 
\{ 0, \.\.\. \}\)} 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 3, \{ 
0, \.\.\. \}\)} 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-not {VIEW_CONVERT_EXPR} "slp2" } } */
+
+/* { dg-final { scan-assembler-times {\tmov\tw[0-7], 12\n} 1 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, xzr, x[0-9]+\n} 1 
} } */
+/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+.b, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 1 } } */
+/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+.b, p[0-7], 
\[x[0-9]+[^]]*\]} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.h, vl3\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+.h, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 1 } } */
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+.h, p[0-7], 
\[x[0-9]+[^]]*\]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_14.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_14.c
new file mode 100644
index 00000000000..6eee3f5705d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_14.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize 
--param=aarch64-autovec-preference=sve-only -msve-vector-bits=scalable 
-fdump-tree-slp2" } */
+
+#include <stdint.h>
+
+/* Test that SVE predicate masks are shared between SLP groups of the same
+   size that use the same vector type.  */
+
+void
+f (uint16_t *x, uint16_t *y)
+{
+  x[0] += 1;
+  x[1] += 2;
+  x[2] += 1;
+  x[3] += 2;
+  x[4] += 1;
+  x[5] += 2;
+
+  y[0] += 1;
+  y[1] += 2;
+  y[2] += 3;
+  y[3] += 4;
+  y[4] += 5;
+  y[5] += 6;
+}
+
+/* The six-element mask should be shared between x and y in GIMPLE.  Expect no
+   conversions because they have the same truth type.  */
+
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 6, \{ 
0, \.\.\. \}\)} 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-not {VIEW_CONVERT_EXPR} "slp2" } } */
+
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.h, vl6\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+.h, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 2 } } */
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+.h, p[0-7], 
\[x[0-9]+[^]]*\]} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_15.c 
b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_15.c
new file mode 100644
index 00000000000..3978a1bd39b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_pred_15.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize 
--param=aarch64-autovec-preference=sve-only -msve-vector-bits=scalable 
-fdump-tree-slp2" } */
+
+#include <stdint.h>
+
+/* Test that SVE predicate masks are shared between SLP groups of the same
+   size despite those groups using different vector types if those types have
+   the same element size. */
+
+void
+f (uint16_t *x, _Float16 *y)
+{
+  x[0] += 1;
+  x[1] += 2;
+  x[2] += 1;
+  x[3] += 2;
+  x[4] += 1;
+  x[5] += 2;
+
+  y[0] += 1;
+  y[1] += 2;
+  y[2] += 3;
+  y[3] += 4;
+  y[4] += 5;
+  y[5] += 6;
+}
+
+/* The six-element mask should be shared between x and y in GIMPLE.  Expect no
+   conversions because they have the same truth type.  */
+
+/* { dg-final { scan-tree-dump-times {max_mask_[0-9]+ = \.WHILE_ULT \(0, 6, \{ 
0, \.\.\. \}\)} 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-not {VIEW_CONVERT_EXPR} "slp2" } } */
+
+/* { dg-final { scan-assembler-times {\tptrue\tp[0-7]\.h, vl6\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+.h, p[0-7]\/z, 
\[x[0-9]+[^]]*\]} 2 } } */
+/* { dg-final { scan-assembler-times {\tst1h\tz[0-9]+.h, p[0-7], 
\[x[0-9]+[^]]*\]} 2 } } */
-- 
2.43.0

Reply via email to