aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr59822.C14
-rw-r--r--gcc/tree-vect-stmts.c56
4 files changed, 81 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f993e48..7ddff75 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59822
+ * tree-vect-stmts.c (hoist_defs_of_uses): New function.
+ (vectorizable_load): Use it to hoist defs of uses of invariant
+ loads out of the loop.
+
2014-01-15 Matthew Gretton-Dann <matthew.gretton-dann@linaro.org>
Kugan Vivekanandarajah <kuganv@linaro.org>
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dde7878..1df5c3a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/59822
+ * g++.dg/torture/pr59822.C: New testcase.
+
2014-01-15 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/59808
diff --git a/gcc/testsuite/g++.dg/torture/pr59822.C b/gcc/testsuite/g++.dg/torture/pr59822.C
new file mode 100644
index 0000000..7357b6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr59822.C
@@ -0,0 +1,14 @@
+// { dg-do compile }
+
+typedef struct rtvec_def *rtvec;
+enum machine_mode { VOIDmode };
+struct rtvec_def { void *elem[1]; };
+extern void *const_tiny_rtx[2];
+void
+ix86_build_const_vector (enum machine_mode mode, bool vect,
+ void *value, rtvec v, int n_elt)
+{
+ int i;
+ for (i = 1; i < n_elt; ++i)
+ ((v)->elem[i]) = vect ? value : (const_tiny_rtx[(int) (mode)]);
+}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index acdaa2d..820df7e 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -5480,6 +5480,59 @@ permute_vec_elements (tree x, tree y, tree mask_vec, gimple stmt,
return data_ref;
}
+/* Hoist the definitions of all SSA uses on STMT out of the loop LOOP,
+ inserting them on the loops preheader edge. Returns true if we
+ were successful in doing so (and thus STMT can be moved then),
+ otherwise returns false. */
+
+static bool
+hoist_defs_of_uses (gimple stmt, struct loop *loop)
+{
+ ssa_op_iter i;
+ tree op;
+ bool any = false;
+
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (op);
+ if (!gimple_nop_p (def_stmt)
+ && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
+ {
+ /* Make sure we don't need to recurse. While we could do
+ so in simple cases when there are more complex use webs
+ we don't have an easy way to preserve stmt order to fulfil
+ dependencies within them. */
+ tree op2;
+ ssa_op_iter i2;
+ FOR_EACH_SSA_TREE_OPERAND (op2, def_stmt, i2, SSA_OP_USE)
+ {
+ gimple def_stmt2 = SSA_NAME_DEF_STMT (op2);
+ if (!gimple_nop_p (def_stmt2)
+ && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt2)))
+ return false;
+ }
+ any = true;
+ }
+ }
+
+ if (!any)
+ return true;
+
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (op);
+ if (!gimple_nop_p (def_stmt)
+ && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt);
+ gsi_remove (&gsi, false);
+ gsi_insert_on_edge_immediate (loop_preheader_edge (loop), def_stmt);
+ }
+ }
+
+ return true;
+}
+
/* vectorizable_load.
Check if STMT reads a non scalar data-ref (array/pointer/structure) that
@@ -6384,7 +6437,8 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
/* If we have versioned for aliasing then we are sure
this is a loop invariant load and thus we can insert
it on the preheader edge. */
- if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo)
+ && hoist_defs_of_uses (stmt, loop))
{
if (dump_enabled_p ())
{