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

Reply via email to