Hi!

Apparently VECTOR_CSTs shouldn't be stepped if they contain floating
elements and also widening conversions can be problematic if there is
wrapping in the narrower type.  On the following testcase, we create a
stepped VECTOR_CST with REAL_CST elts and ICE whenever we try to print it or
when we try to expand it.  The following patch follows what fold_convert_const
does.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-02-05  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/89210
        * fold-const-call.c (fold_const_vec_convert): Pass true as last
        operand to new_unary_operation only if both element types are integral
        and it isn't a widening conversion.  Return NULL_TREE if
        new_unary_operation failed.

        * c-c++-common/builtin-convertvector-2.c: New test.

--- gcc/fold-const-call.c.jj    2019-01-07 09:47:33.046517940 +0100
+++ gcc/fold-const-call.c       2019-02-05 19:15:44.111209138 +0100
@@ -665,8 +665,17 @@ fold_const_vec_convert (tree ret_type, t
           && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
     code = FLOAT_EXPR;
 
+  /* We can't handle steps directly when extending, since the
+     values need to wrap at the original precision first.  */
+  bool step_ok_p
+    = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
+       && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
+       && (TYPE_PRECISION (TREE_TYPE (ret_type))
+          <= TYPE_PRECISION (TREE_TYPE (arg_type))));
   tree_vector_builder elts;
-  elts.new_unary_operation (ret_type, arg, true);
+  if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
+    return NULL_TREE;
+
   unsigned int count = elts.encoded_nelts ();
   for (unsigned int i = 0; i < count; ++i)
     {
--- gcc/testsuite/c-c++-common/builtin-convertvector-2.c.jj     2019-02-05 
19:19:16.981705824 +0100
+++ gcc/testsuite/c-c++-common/builtin-convertvector-2.c        2019-02-05 
19:17:20.217627468 +0100
@@ -0,0 +1,12 @@
+/* PR middle-end/89210 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int v4si __attribute__((vector_size (4 * sizeof (int))));
+typedef double v4df __attribute__((vector_size (4 * sizeof (double))));
+void
+foo (v4df *x)
+{
+  v4si a = { 1, 2, 3, 4 };
+  *x = __builtin_convertvector (a, v4df);
+}

        Jakub

Reply via email to