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