The following adds a missing check to prevent vectorizing conversions
from _BitInt values which are not appropriately sign-/zero-extended
to their mode.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
To get the testcase to break I had to store garbage into the
upper bits. I'm not sure whether targets that have defined
upper bits will fail this. Shouldn't we have defined
in-memory values? I can imagine a lack of that will cause
interesting portability issues ...
OK?
Thanks,
Richard.
* tree-vect-stmts.cc (vectorizable_conversion): Prevent
conversions from non-mode-precision _BitInt.
* gcc.dg/vect/vect-bitint-1.c: New testcase.
---
gcc/testsuite/gcc.dg/vect/vect-bitint-1.c | 36 +++++++++++++++++++++++
gcc/tree-vect-stmts.cc | 11 +++++++
2 files changed, 47 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/vect/vect-bitint-1.c
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bitint-1.c
b/gcc/testsuite/gcc.dg/vect/vect-bitint-1.c
new file mode 100644
index 00000000000..455463ccdba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-bitint-1.c
@@ -0,0 +1,36 @@
+#include <stdint.h>
+#include "tree-vect.h"
+
+void __attribute__((noipa))
+foo (int64_t *a, signed _BitInt(17) *b)
+{
+ for (int i = 0; i < 32; i++)
+ a[i] = b[i];
+}
+
+int
+main ()
+{
+ int64_t a[32];
+ _BitInt(17) b[32];
+
+ check_vect ();
+
+#pragma GCC novector
+ for (int i = 0; i < 32; ++i)
+ b[i] = i;
+#pragma GCC novector
+ for (int i = 0; i < 32; ++i)
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ *((char *)&b[i] + 3) = 0x80;
+#else
+ ;
+#endif
+ foo (a, b);
+#pragma GCC novector
+ for (int i = 0; i < 32; ++i)
+ if (a[i] != i)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 42c8516ea0a..36c0d34733b 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -5413,6 +5413,17 @@ vectorizable_conversion (vec_info *vinfo,
"type conversion to bit-precision unsupported\n");
return false;
}
+ /* _BitInt values are not sign-/zero-extended to mode precision. */
+ if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
+ && TREE_CODE (rhs_type) == BITINT_TYPE
+ && !type_has_mode_precision_p (rhs_type))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "type conversion from _BitInt unsupported\n");
+ return false;
+ }
+
if (op_type == binary_op)
{
--
2.51.0