aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-11-27 12:16:54 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-11-27 12:16:54 +0000
commit88feafba3cb5b186d53080c4958474065c4bd5d2 (patch)
tree7298af26e95c1f2a3f422cd75c35c6b583284c5e
parentb7b848f5d7984a9984e0a518b75ff91a0de0cb32 (diff)
downloadgcc-88feafba3cb5b186d53080c4958474065c4bd5d2.zip
gcc-88feafba3cb5b186d53080c4958474065c4bd5d2.tar.gz
gcc-88feafba3cb5b186d53080c4958474065c4bd5d2.tar.bz2
re PR tree-optimization/92690 (vector CTOR optimization performs invalid conversion)
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr92690.c38
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c3
-rw-r--r--gcc/tree-ssa-forwprop.c92
5 files changed, 102 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d46ba4c..b0385da 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 92d6855..2fd0ae7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..b49f184
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr92690.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
index d55197b..24e6338 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
@@ -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-*-* } } } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 7202d4a..e1bdb49 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -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);
}