Since r15-5777 the SVE ACLE types are GNU vectors, so operators,
__builtin_shuffle and __builtin_convertvector can create
variable-length vector operations that the target cannot do. Vector
lowering ICEs on them, or in release builds lowers the first 128 bits.
Report these with sorry (), as suggested in the PR, where piecewise
lowering starts, and use zero as the result. Supported operations
never get there; expand_vector_divmod now gives up on variable-length
vectors so that they do. lower_vec_perm checks for target support
before its sorry, so supported constant selectors work at -O0 too.
Bootstrapped and regression tested on x86_64-pc-linux-gnu. The SVE
and vect tests have no regressions on aarch64-linux-gnu (qemu, VL128
and VL2048).
Assisted-by: Claude Opus 5 (Anthropic)
PR target/118377
gcc/ChangeLog:
* tree-vect-generic.cc (expand_vector_piecewise): Diagnose
variable-length vectors with sorry and return zero.
(expand_vector_divmod): Give up on variable-length vectors.
(lower_vec_perm): Check for target support before rejecting
variable-length vectors, and diagnose them with sorry. Replace
the result with zero.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/sve/acle/general-c/pr118377.c: New test.
* gcc.target/aarch64/sve/acle/general-c/vla_compare_1.c: New test.
* gcc.target/aarch64/sve/acle/general-c/vla_shuffle_1.c: New test.
* gcc.target/aarch64/sve/acle/general-c/vla_shuffle_2.c: New test.
* gcc.target/aarch64/sve/pr118377.c: New test.
* g++.target/aarch64/sve/acle/general-c++/pr118377.C: New test.
* g++.target/aarch64/sve/acle/general-c++/vla_compare_1.C: New test.
* g++.target/aarch64/sve/acle/general-c++/vla_shuffle_1.C: New test.
* g++.target/aarch64/sve/acle/general-c++/vla_shuffle_2.C: New test.
Signed-off-by: Dominic P <[email protected]>
---
OK for trunk?
sorry () follows Tejas's suggestion and Richard Sandiford's comment 10
in PR118377 (valid ACLE code; sorry for what is not supported yet).
The zero result is what tree-complex.cc does after its sorry for
PR105165. Constant selectors at -O0 now take the -O2 path, including
its existing wrong code for stepped selectors that wrap
(svindex_u8 (0, 3)), which is a separate bug. Tejas, the PR stays
yours for the real lowering (variable divisors, bf16, shuffles).
.../aarch64/sve/acle/general-c++/pr118377.C | 63 +++++++++++++++++++
.../sve/acle/general-c++/vla_compare_1.C | 15 +++++
.../sve/acle/general-c++/vla_shuffle_1.C | 27 ++++++++
.../sve/acle/general-c++/vla_shuffle_2.C | 28 +++++++++
.../aarch64/sve/acle/general-c/pr118377.c | 63 +++++++++++++++++++
.../sve/acle/general-c/vla_compare_1.c | 15 +++++
.../sve/acle/general-c/vla_shuffle_1.c | 27 ++++++++
.../sve/acle/general-c/vla_shuffle_2.c | 28 +++++++++
.../gcc.target/aarch64/sve/pr118377.c | 20 ++++++
gcc/tree-vect-generic.cc | 25 ++++++--
10 files changed, 305 insertions(+), 6 deletions(-)
create mode 100644
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/pr118377.C
create mode 100644
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_compare_1.C
create mode 100644
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_1.C
create mode 100644
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_2.C
create mode 100644
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr118377.c
create mode 100644
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_compare_1.c
create mode 100644
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_1.c
create mode 100644
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr118377.c
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/pr118377.C
b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/pr118377.C
new file mode 100644
index 00000000000..e614ded7c4b
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/pr118377.C
@@ -0,0 +1,63 @@
+// { dg-options "-O2" }
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y)
+{
+ return x / y; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svint16_t
+f2 (svint16_t x)
+{
+ return x / 4; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svint32_t
+f3 (svint32_t x, svint32_t y)
+{
+ return x % y; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svuint8_t
+f4 (svuint8_t x)
+{
+ return x % 3; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svbfloat16_t
+f5 (svbfloat16_t x, svbfloat16_t y)
+{
+ return x + y; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svint16_t
+f6 (svbfloat16_t x, svbfloat16_t y)
+{
+ return x < y; // { dg-message {unsupported operation on variable-length
vectors} }
+}
+
+svint16_t
+f7 (svbfloat16_t x)
+{
+ return __builtin_convertvector (x, svint16_t); // { dg-message {unsupported
operation on variable-length vectors} }
+}
+
+svbfloat16_t
+f8 (svint16_t x)
+{
+ return __builtin_convertvector (x, svbfloat16_t); // { dg-message
{unsupported operation on variable-length vectors} }
+}
+
+svint16_t
+f9 (svint16_t x)
+{
+ return x / svindex_s16 (1, 1); // { dg-message {unsupported operation on
variable-length vectors} }
+}
+
+svint16_t
+f10 (svint16_t x)
+{
+ return x % svdupq_s16 (1, 2, 3, 4, 5, 6, 7, 8); // { dg-message {unsupported
operation on variable-length vectors} }
+}
diff --git
a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_compare_1.C
b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_compare_1.C
new file mode 100644
index 00000000000..26bb8b4f6bf
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_compare_1.C
@@ -0,0 +1,15 @@
+// { dg-options "-O0" }
+
+#include <arm_sve.h>
+
+svint32_t
+f1 (svint32_t x, svint32_t y)
+{
+ return x < y;
+}
+
+svint64_t
+f2 (svfloat64_t x, svfloat64_t y)
+{
+ return x != y;
+}
diff --git
a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_1.C
b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_1.C
new file mode 100644
index 00000000000..6ec8ed888d8
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_1.C
@@ -0,0 +1,27 @@
+// { dg-options "-O2" }
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y, svint8_t z)
+{
+ return __builtin_shuffle (x, y, z); // { dg-message {unsupported permutation
of variable-length vectors} }
+}
+
+svint8_t
+f2 (svint8_t x, svint8_t z)
+{
+ return __builtin_shuffle (x, z); // { dg-message {unsupported permutation of
variable-length vectors} }
+}
+
+svfloat64_t
+f3 (svfloat64_t x, svfloat64_t y, svuint64_t z)
+{
+ return __builtin_shuffle (x, y, z); // { dg-message {unsupported permutation
of variable-length vectors} }
+}
+
+svbool_t
+f4 (svbool_t x, svint8_t z)
+{
+ return __builtin_shuffle (x, x, z); // { dg-message {unsupported permutation
of variable-length vectors} }
+}
diff --git
a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_2.C
b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_2.C
new file mode 100644
index 00000000000..f4c7e05aa0b
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/vla_shuffle_2.C
@@ -0,0 +1,28 @@
+// { dg-options "-O0" }
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, (svint8_t) {});
+}
+
+svint8_t
+f2 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, svdup_s8 (1));
+}
+
+svuint8_t
+f3 (svuint8_t x)
+{
+ return __builtin_shuffle (x, svindex_u8 (0, 2));
+}
+
+svint8_t
+f4 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, svdupq_s8 (0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15));
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr118377.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr118377.c
new file mode 100644
index 00000000000..c26b36bb96e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pr118377.c
@@ -0,0 +1,63 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y)
+{
+ return x / y; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svint16_t
+f2 (svint16_t x)
+{
+ return x / 4; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svint32_t
+f3 (svint32_t x, svint32_t y)
+{
+ return x % y; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svuint8_t
+f4 (svuint8_t x)
+{
+ return x % 3; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svbfloat16_t
+f5 (svbfloat16_t x, svbfloat16_t y)
+{
+ return x + y; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svint16_t
+f6 (svbfloat16_t x, svbfloat16_t y)
+{
+ return x < y; /* { dg-message {unsupported operation on variable-length
vectors} } */
+}
+
+svint16_t
+f7 (svbfloat16_t x)
+{
+ return __builtin_convertvector (x, svint16_t); /* { dg-message {unsupported
operation on variable-length vectors} } */
+}
+
+svbfloat16_t
+f8 (svint16_t x)
+{
+ return __builtin_convertvector (x, svbfloat16_t); /* { dg-message
{unsupported operation on variable-length vectors} } */
+}
+
+svint16_t
+f9 (svint16_t x)
+{
+ return x / svindex_s16 (1, 1); /* { dg-message {unsupported operation on
variable-length vectors} } */
+}
+
+svint16_t
+f10 (svint16_t x)
+{
+ return x % svdupq_s16 (1, 2, 3, 4, 5, 6, 7, 8); /* { dg-message {unsupported
operation on variable-length vectors} } */
+}
diff --git
a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_compare_1.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_compare_1.c
new file mode 100644
index 00000000000..f423d818838
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_compare_1.c
@@ -0,0 +1,15 @@
+/* { dg-options "-O0" } */
+
+#include <arm_sve.h>
+
+svint32_t
+f1 (svint32_t x, svint32_t y)
+{
+ return x < y;
+}
+
+svint64_t
+f2 (svfloat64_t x, svfloat64_t y)
+{
+ return x != y;
+}
diff --git
a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_1.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_1.c
new file mode 100644
index 00000000000..434f63007fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_1.c
@@ -0,0 +1,27 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y, svint8_t z)
+{
+ return __builtin_shuffle (x, y, z); /* { dg-message {unsupported permutation
of variable-length vectors} } */
+}
+
+svint8_t
+f2 (svint8_t x, svint8_t z)
+{
+ return __builtin_shuffle (x, z); /* { dg-message {unsupported permutation of
variable-length vectors} } */
+}
+
+svfloat64_t
+f3 (svfloat64_t x, svfloat64_t y, svuint64_t z)
+{
+ return __builtin_shuffle (x, y, z); /* { dg-message {unsupported permutation
of variable-length vectors} } */
+}
+
+svbool_t
+f4 (svbool_t x, svint8_t z)
+{
+ return __builtin_shuffle (x, x, z); /* { dg-message {unsupported permutation
of variable-length vectors} } */
+}
diff --git
a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_2.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_2.c
new file mode 100644
index 00000000000..9ca74f45860
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/vla_shuffle_2.c
@@ -0,0 +1,28 @@
+/* { dg-options "-O0" } */
+
+#include <arm_sve.h>
+
+svint8_t
+f1 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, (svint8_t) {});
+}
+
+svint8_t
+f2 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, svdup_s8 (1));
+}
+
+svuint8_t
+f3 (svuint8_t x)
+{
+ return __builtin_shuffle (x, svindex_u8 (0, 2));
+}
+
+svint8_t
+f4 (svint8_t x, svint8_t y)
+{
+ return __builtin_shuffle (x, y, svdupq_s8 (0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15));
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr118377.c
b/gcc/testsuite/gcc.target/aarch64/sve/pr118377.c
new file mode 100644
index 00000000000..8c860752730
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr118377.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svint32_t
+f1 (svint32_t x, svint32_t y)
+{
+ return x < y;
+}
+
+void
+f2 (int *restrict a, int *restrict b, int n)
+{
+ for (int i = 0; i < n; i++)
+ if (b[i] > 3)
+ a[i] = b[i];
+}
+
+/* { dg-final { scan-assembler-times {\tcmp[gl]t\t} 2 } } */
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index 5f9086615e3..5681a92454f 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -288,6 +288,13 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi,
elem_op_func f,
tree a, tree b, enum tree_code code,
bool parallel_p, tree ret_type = NULL_TREE)
{
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant ())
+ {
+ sorry_at (loc, "unsupported operation on variable-length vectors");
+ return build_zero_cst (ret_type ? ret_type : type);
+ }
+
vec<constructor_elt, va_gc> *v;
tree part_width = TYPE_SIZE (inner_type);
tree index = bitsize_int (0);
@@ -295,7 +302,6 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi,
elem_op_func f,
int delta = (VECTOR_TYPE_P (inner_type)
? nunits_for_known_piecewise_op (inner_type) : 1);
int i;
- location_t loc = gimple_location (gsi_stmt (*gsi));
if (nunits == 1
|| warning_suppressed_p (gsi_stmt (*gsi),
@@ -704,7 +710,9 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type,
tree op0,
bool use_abs_op1 = false;
int mode = -1, this_mode;
int pre_shift = -1, post_shift;
- unsigned int nunits = nunits_for_known_piecewise_op (type);
+ unsigned HOST_WIDE_INT nunits;
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nunits))
+ return NULL_TREE;
int *shifts = XALLOCAVEC (int, nunits * 4);
int *pre_shifts = shifts + nunits;
int *post_shifts = pre_shifts + nunits;
@@ -1628,10 +1636,6 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (gsi_stmt (*gsi));
unsigned i;
- if (!TYPE_VECTOR_SUBPARTS (res_vect_type).is_constant (&elements)
- || !TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&in_elements))
- return;
-
if (TREE_CODE (mask) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
@@ -1658,6 +1662,15 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
return;
+ if (!TYPE_VECTOR_SUBPARTS (res_vect_type).is_constant (&elements)
+ || !TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&in_elements))
+ {
+ sorry_at (loc, "unsupported permutation of variable-length vectors");
+ gimple_assign_set_rhs_from_tree (gsi, build_zero_cst (res_vect_type));
+ update_stmt (gsi_stmt (*gsi));
+ return;
+ }
+
if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
warning_at (loc, OPT_Wvector_operation_performance,
"vector shuffling operation will be expanded piecewise");
--
2.56.0