The following patch fixes invariant vector construction in vector CTOR
optimization.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2019-12-05  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/92803
        * tree-ssa-forwprop.c (simplify_vector_constructor): Fix
        invariant vector construction.

        * gcc.target/i386/pr92803.c: New testcase.

Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c     (revision 278985)
+++ gcc/tree-ssa-forwprop.c     (working copy)
@@ -2286,24 +2286,28 @@ simplify_vector_constructor (gimple_stmt
       else if (orig[1] == error_mark_node
               && one_nonconstant)
        {
-         orig[1] = gimple_build_vector_from_val (&stmts, UNKNOWN_LOCATION,
-                                                 type, one_nonconstant);
          /* ???  We can see if we can safely convert to the original
             element type.  */
          converted_orig1 = conv_code != ERROR_MARK;
+         orig[1] = gimple_build_vector_from_val (&stmts, UNKNOWN_LOCATION,
+                                                 converted_orig1
+                                                 ? type : perm_type,
+                                                 one_nonconstant);
        }
       else if (orig[1] == error_mark_node)
        {
-         tree_vector_builder vec (type, nelts, 1);
-         for (unsigned i = 0; i < nelts; ++i)
-           if (constants[i])
+         /* ???  See if we can convert the vector to the original type.  */
+         converted_orig1 = conv_code != ERROR_MARK;
+         unsigned n = converted_orig1 ? nelts : refnelts;
+         tree_vector_builder vec (converted_orig1
+                                  ? type : perm_type, n, 1);
+         for (unsigned i = 0; i < n; ++i)
+           if (i < nelts && constants[i])
              vec.quick_push (constants[i]);
            else
              /* ??? Push a don't-care value.  */
              vec.quick_push (one_constant);
          orig[1] = vec.build ();
-         /* ???  See if we can convert the vector to the original type.  */
-         converted_orig1 = conv_code != ERROR_MARK;
        }
       tree blend_op2 = NULL_TREE;
       if (converted_orig1)
Index: gcc/testsuite/gcc.target/i386/pr92803.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr92803.c     (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr92803.c     (working copy)
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wno-psabi -mavx2 -fdump-tree-forwprop1" } */
+
+typedef double v4df __attribute__((vector_size (32)));
+typedef float v8sf __attribute__((vector_size (32)));
+typedef float v4sf __attribute__((vector_size (16)));
+typedef int v4si __attribute__((vector_size (16)));
+typedef double v2df __attribute__((vector_size (16)));
+
+v2df
+foo (v4df x, double *p, v2df y)
+{
+  return (v2df) { x[3], *p };
+}
+
+v4sf
+bar (v4si x, float *p)
+{
+  return (v4sf) { x[0], x[1], x[2], *p };
+}
+
+v4sf
+baz (v4si x)
+{
+  return (v4sf) { x[0], x[1], 3.0f, 1.0f };
+}
+
+v4sf
+barf (v8sf x)
+{
+  return (v4sf) { x[4], x[5], 1.0f, 2.0f };
+}
+
+/* We expect all CTORs to turn into permutes, the FP converting ones
+   to two each with the one with constants possibly elided in the future
+   by converting 3.0f and 1.0f "back" to integers.  */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 6 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 5 "forwprop1" { xfail 
*-*-* } } } */

Reply via email to