re PR tree-optimization/92690 (vector CTOR optimization performs invalid conversion)
authorRichard Biener <rguenther@suse.de>
Wed, 27 Nov 2019 12:16:54 +0000 (12:16 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 27 Nov 2019 12:16:54 +0000 (12:16 +0000)
2019-11-27  Richard Biener  <rguenther@suse.de>

PR tree-optimization/92690
* tree-ssa-forwprop.c (simplify_vector_constructor): Avoid
converting elements not originally converted.

* gcc.dg/torture/pr92690.c: New testcase.
* gcc.dg/tree-ssa/forwprop-35.c: Adjust.

From-SVN: r278764

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr92690.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
gcc/tree-ssa-forwprop.c

index d46ba4cbc4e2aee07df3c3244969d9438380adbe..b0385da7c8f664bc0067b765b86ceea142c26f28 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-27  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/92690
+       * tree-ssa-forwprop.c (simplify_vector_constructor): Avoid
+       converting elements not originally converted.
+
 2019-11-27  Tobias Burnus  <tobias@codesourcery.com>
 
        PR middle-end/92463
index 92d6855694b6b53ef822903963eb8b11a952e6b5..2fd0ae744114f17b0773f8a3f628cbbfa0c41c9f 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-27  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/92690
+       * gcc.dg/torture/pr92690.c: New testcase.
+       * gcc.dg/tree-ssa/forwprop-35.c: Adjust.
+
 2019-11-27  Jakub Jelinek  <jakub@redhat.com>
 
        PR fortran/91944
diff --git a/gcc/testsuite/gcc.dg/torture/pr92690.c b/gcc/testsuite/gcc.dg/torture/pr92690.c
new file mode 100644 (file)
index 0000000..b49f184
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do run { target *-*-*gnu* } } */
+/* { dg-additional-options "-D_GNU_SOURCE" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef float v4sf __attribute__((vector_size(16)));
+
+void __attribute__((noipa))
+foo (v4si *dstp, v4sf *srcp)
+{
+  v4sf src = *srcp;
+  *dstp = (v4si) { src[0], src[1], 3, 4 };
+}
+
+void __attribute__((noipa))
+bar (v4sf *dstp, v4si *srcp)
+{
+  v4si src = *srcp;
+  *dstp = (v4sf) { src[0], src[1], 3.5, 4.5 };
+}
+
+int
+main()
+{
+  feenableexcept (FE_INVALID|FE_INEXACT);
+  v4sf x = (v4sf) { 1, 2, __builtin_nanf (""), 3.5 };
+  v4si y;
+  foo (&y, &x);
+  if (y[0] != 1 || y[1] != 2 || y[2] != 3 || y[3] != 4)
+    __builtin_abort ();
+  y = (v4si) { 0, 1, __INT_MAX__, -__INT_MAX__ };
+  bar (&x, &y);
+  if (x[0] != 0 || x[1] != 1 || x[2] != 3.5 || x[3] != 4.5)
+    __builtin_abort ();
+  return 0;
+}
index d55197bceb94478c3cd72187bbb8865e2566b777..24e63386960285699a636862fc7619bc0c8e4814 100644 (file)
@@ -16,4 +16,5 @@ v4sf vec_cast_perm(v4si f)
 }
 
 /* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
-/* { dg-final { scan-tree-dump-times "\\\(v4sf\\\) " 2 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
+/* Catch (v4sf) and (vector(4) float).  */
+/* { dg-final { scan-tree-dump-times " = \\\(v" 2 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
index 7202d4ac554b9a2739687382911e3da475e581c4..e1bdb49e91c86e4a30581d7d3ae339f273831469 100644 (file)
@@ -2034,7 +2034,7 @@ static bool
 simplify_vector_constructor (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
-  tree op, op2, orig[2], type, elem_type;
+  tree op, orig[2], type, elem_type;
   unsigned elem_size, i;
   unsigned HOST_WIDE_INT nelts;
   unsigned HOST_WIDE_INT refnelts;
@@ -2175,23 +2175,10 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   else
     {
       tree mask_type, perm_type, conv_src_type;
-      if (orig[1] == error_mark_node && conv_code != ERROR_MARK)
-       {
-         /* ???  For subsetting a larger vector we need to permute the original
-            but then the constants are in the converted type already which is
-            why for that case we first convert and then permute.  */
-         if (nelts != refnelts)
-           return false;
-         conv_src_type = TREE_TYPE (orig[0]);
-         perm_type = type;
-       }
-      else
-       {
-         perm_type = TREE_TYPE (orig[0]);
-         conv_src_type = (nelts == refnelts
-                          ? perm_type
-                          : build_vector_type (TREE_TYPE (perm_type), nelts));
-       }
+      perm_type = TREE_TYPE (orig[0]);
+      conv_src_type = (nelts == refnelts
+                      ? perm_type
+                      : build_vector_type (TREE_TYPE (perm_type), nelts));
       tree tem;
       if (conv_code != ERROR_MARK
          && (!supportable_convert_operation (conv_code, type, conv_src_type,
@@ -2200,7 +2187,10 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
        return false;
 
       /* Now that we know the number of elements of the source build the
-        permute vector.  */
+        permute vector.
+        ???  When the second vector has constant values we can shuffle
+        it and its source indexes to make the permutation supported.
+        For now it mimics a blend.  */
       vec_perm_builder sel (refnelts, refnelts, 1);
       for (i = 0; i < elts.length (); ++i)
        sel.quick_push (elts[i].second + elts[i].first * refnelts);
@@ -2219,8 +2209,8 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
          || maybe_ne (GET_MODE_SIZE (TYPE_MODE (mask_type)),
                       GET_MODE_SIZE (TYPE_MODE (perm_type))))
        return false;
-      op2 = vec_perm_indices_to_tree (mask_type, indices);
-      bool convert_orig0 = false;
+      tree op2 = vec_perm_indices_to_tree (mask_type, indices);
+      bool converted_orig1 = false;
       gimple_seq stmts = NULL;
       if (!orig[1])
        orig[1] = orig[0];
@@ -2228,12 +2218,14 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
               && one_nonconstant)
        {
          orig[1] = gimple_build_vector_from_val (&stmts, UNKNOWN_LOCATION,
-                                                 perm_type, one_nonconstant);
-         convert_orig0 = conv_code != ERROR_MARK;
+                                                 type, one_nonconstant);
+         /* ???  We can see if we can safely convert to the original
+            element type.  */
+         converted_orig1 = conv_code != ERROR_MARK;
        }
       else if (orig[1] == error_mark_node)
        {
-         tree_vector_builder vec (perm_type, nelts, 1);
+         tree_vector_builder vec (type, nelts, 1);
          for (unsigned i = 0; i < nelts; ++i)
            if (constants[i])
              vec.quick_push (constants[i]);
@@ -2241,27 +2233,43 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
              /* ??? Push a don't-care value.  */
              vec.quick_push (one_constant);
          orig[1] = vec.build ();
-         convert_orig0 = conv_code != ERROR_MARK;
+         /* ???  See if we can convert the vector to the original type.  */
+         converted_orig1 = conv_code != ERROR_MARK;
        }
-      tree res;
-      if (convert_orig0)
+      tree blend_op2 = NULL_TREE;
+      if (converted_orig1)
        {
-         gcc_assert (nelts == refnelts);
-         res = gimple_build (&stmts, conv_code, type, orig[0]);
-         res = gimple_build (&stmts, VEC_PERM_EXPR, perm_type,
-                             res, orig[1], op2);
-       }
-      else
-       {
-         res = gimple_build (&stmts, VEC_PERM_EXPR, perm_type,
-                             orig[0], orig[1], op2);
-         if (nelts != refnelts)
-           res = gimple_build (&stmts, BIT_FIELD_REF,
-                               conv_code != ERROR_MARK ? conv_src_type : type,
-                               res, TYPE_SIZE (type), bitsize_zero_node);
-         if (conv_code != ERROR_MARK)
-           res = gimple_build (&stmts, conv_code, type, res);
+         /* Make sure we can do a blend in the target type.  */
+         vec_perm_builder sel (nelts, nelts, 1);
+         for (i = 0; i < elts.length (); ++i)
+           sel.quick_push (elts[i].first
+                           ? elts[i].second + nelts : i);
+         vec_perm_indices indices (sel, 2, nelts);
+         if (!can_vec_perm_const_p (TYPE_MODE (type), indices))
+           return false;
+         mask_type
+           = build_vector_type (build_nonstandard_integer_type (elem_size, 1),
+                                nelts);
+         if (GET_MODE_CLASS (TYPE_MODE (mask_type)) != MODE_VECTOR_INT
+             || maybe_ne (GET_MODE_SIZE (TYPE_MODE (mask_type)),
+                          GET_MODE_SIZE (TYPE_MODE (type))))
+           return false;
+         blend_op2 = vec_perm_indices_to_tree (mask_type, indices);
        }
+      tree orig1_for_perm
+       = converted_orig1 ? build_zero_cst (perm_type) : orig[1];
+      tree res = gimple_build (&stmts, VEC_PERM_EXPR, perm_type,
+                              orig[0], orig1_for_perm, op2);
+      if (nelts != refnelts)
+       res = gimple_build (&stmts, BIT_FIELD_REF,
+                           conv_code != ERROR_MARK ? conv_src_type : type,
+                           res, TYPE_SIZE (type), bitsize_zero_node);
+      if (conv_code != ERROR_MARK)
+       res = gimple_build (&stmts, conv_code, type, res);
+      /* Blend in the actual constant.  */
+      if (converted_orig1)
+       res = gimple_build (&stmts, VEC_PERM_EXPR, type,
+                           res, orig[1], blend_op2);
       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
       gimple_assign_set_rhs_with_ops (gsi, SSA_NAME, res);
     }