aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-05-03 10:39:56 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-05-03 10:39:56 +0000
commita7eb97ad269b6509bd7b31ca373daea98e4d7e85 (patch)
treea29da7cddfeb73ebddf097156d20dfb4b360880c
parente7a89a659afeaae763761dab0a7fd3f2f7ddcbe2 (diff)
downloadgcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.zip
gcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.tar.gz
gcc-a7eb97ad269b6509bd7b31ca373daea98e4d7e85.tar.bz2
re PR middle-end/88963 (gcc generates terrible code for vectors of 64+ length which are not natively supported)
2019-05-03 Richard Biener <rguenther@suse.de> PR tree-optimization/88963 * tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite vector loads feeding only BIT_FIELD_REFs to component loads. Rewrite stores fed by CONSTRUCTORs to component stores. * gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop. * gcc.target/i386/pr88963-1.c: New testcase. * gcc.target/i386/pr88963-2.c: Likewise. From-SVN: r270844
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88963-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88963-2.c14
-rw-r--r--gcc/tree-ssa-forwprop.c125
6 files changed, 168 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 346cb5f..80c34be 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2019-05-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/88963
+ * tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite
+ vector loads feeding only BIT_FIELD_REFs to component
+ loads. Rewrite stores fed by CONSTRUCTORs to component
+ stores.
+
2019-05-03 Jakub Jelinek <jakub@redhat.com>
* opts.h (finish_options): Remove lang_mask argument.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2bb5609..57a07d1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2019-05-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/88963
+ * gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop.
+ * gcc.target/i386/pr88963-1.c: New testcase.
+ * gcc.target/i386/pr88963-2.c: Likewise.
+
2019-05-03 Dominique d'Humieres <dominiq@gcc.gnu.org>
PR target/88809
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
index 6402c81..3d429ab 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details -fno-tree-forwprop" } */
/* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
typedef double d128 __attribute__((vector_size(16)));
diff --git a/gcc/testsuite/gcc.target/i386/pr88963-1.c b/gcc/testsuite/gcc.target/i386/pr88963-1.c
new file mode 100644
index 0000000..e6f1525
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88963-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mavx2 -fdump-tree-optimized" } */
+
+typedef int VInt __attribute__((vector_size(64)));
+
+void test(VInt*__restrict a, VInt*__restrict b,
+ VInt*__restrict c)
+{
+ *a = *b + *c;
+}
+
+/* Vector loads and stores should be split. */
+/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr88963-2.c b/gcc/testsuite/gcc.target/i386/pr88963-2.c
new file mode 100644
index 0000000..114f1f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88963-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -msse2 -fdump-tree-optimized" } */
+
+typedef int VInt __attribute__((vector_size(64)));
+
+void test(VInt*__restrict a, VInt*__restrict b,
+ VInt*__restrict c)
+{
+ *a = *b + *c;
+}
+
+/* Vector loads and stores should be split. */
+/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "vector\\(8\\)" "optimized" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index bbfa1bc..1553c9e 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2400,6 +2400,72 @@ pass_forwprop::execute (function *fun)
else
gsi_next (&gsi);
}
+ else if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE
+ && TYPE_MODE (TREE_TYPE (lhs)) == BLKmode
+ && gimple_assign_load_p (stmt)
+ && !gimple_has_volatile_ops (stmt)
+ && (TREE_CODE (gimple_assign_rhs1 (stmt))
+ != TARGET_MEM_REF)
+ && !stmt_can_throw_internal (cfun, stmt))
+ {
+ /* Rewrite loads used only in BIT_FIELD_REF extractions to
+ component-wise loads. */
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ bool rewrite = true;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (!is_gimple_assign (use_stmt)
+ || gimple_assign_rhs_code (use_stmt) != BIT_FIELD_REF)
+ {
+ rewrite = false;
+ break;
+ }
+ }
+ if (rewrite)
+ {
+ gimple *use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+ {
+ if (is_gimple_debug (use_stmt))
+ {
+ if (gimple_debug_bind_p (use_stmt))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ continue;
+ }
+
+ tree bfr = gimple_assign_rhs1 (use_stmt);
+ tree new_rhs = fold_build3 (BIT_FIELD_REF,
+ TREE_TYPE (bfr),
+ unshare_expr (rhs),
+ TREE_OPERAND (bfr, 1),
+ TREE_OPERAND (bfr, 2));
+ gimple *new_stmt
+ = gimple_build_assign (gimple_assign_lhs (use_stmt),
+ new_rhs);
+
+ location_t loc = gimple_location (use_stmt);
+ gimple_set_location (new_stmt, loc);
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+ unlink_stmt_vdef (use_stmt);
+ gsi_remove (&gsi2, true);
+
+ gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+ }
+
+ release_defs (stmt);
+ gsi_remove (&gsi, true);
+ }
+ else
+ gsi_next (&gsi);
+ }
+
else if (code == COMPLEX_EXPR)
{
/* Rewrite stores of a single-use complex build expression
@@ -2440,6 +2506,65 @@ pass_forwprop::execute (function *fun)
else
gsi_next (&gsi);
}
+ else if (code == CONSTRUCTOR
+ && VECTOR_TYPE_P (TREE_TYPE (rhs))
+ && TYPE_MODE (TREE_TYPE (rhs)) == BLKmode
+ && CONSTRUCTOR_NELTS (rhs) > 0
+ && (!VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
+ || (TYPE_MODE (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
+ != BLKmode)))
+ {
+ /* Rewrite stores of a single-use vector constructors
+ to component-wise stores if the mode isn't supported. */
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (single_imm_use (lhs, &use_p, &use_stmt)
+ && gimple_store_p (use_stmt)
+ && !gimple_has_volatile_ops (use_stmt)
+ && is_gimple_assign (use_stmt)
+ && (TREE_CODE (gimple_assign_lhs (use_stmt))
+ != TARGET_MEM_REF))
+ {
+ tree elt_t = TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value);
+ unsigned HOST_WIDE_INT elt_w
+ = tree_to_uhwi (TYPE_SIZE (elt_t));
+ unsigned HOST_WIDE_INT n
+ = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
+ for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w)
+ {
+ unsigned HOST_WIDE_INT ci = bi / elt_w;
+ tree new_rhs;
+ if (ci < CONSTRUCTOR_NELTS (rhs))
+ new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value;
+ else
+ new_rhs = build_zero_cst (elt_t);
+ tree use_lhs = gimple_assign_lhs (use_stmt);
+ tree new_lhs = build3 (BIT_FIELD_REF,
+ elt_t,
+ unshare_expr (use_lhs),
+ bitsize_int (elt_w),
+ bitsize_int (bi));
+ gimple *new_stmt = gimple_build_assign (new_lhs, new_rhs);
+ location_t loc = gimple_location (use_stmt);
+ gimple_set_location (new_stmt, loc);
+ gimple_set_vuse (new_stmt, gimple_vuse (use_stmt));
+ gimple_set_vdef (new_stmt,
+ make_ssa_name (gimple_vop (cfun)));
+ SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
+ gimple_set_vuse (use_stmt, gimple_vdef (new_stmt));
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+ gsi_insert_before (&gsi2, new_stmt, GSI_SAME_STMT);
+ }
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+ unlink_stmt_vdef (use_stmt);
+ release_defs (use_stmt);
+ gsi_remove (&gsi2, true);
+ release_defs (stmt);
+ gsi_remove (&gsi, true);
+ }
+ else
+ gsi_next (&gsi);
+ }
else
gsi_next (&gsi);
}