summaryrefslogtreecommitdiff
path: root/gcc/tree-vect-slp.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2020-02-25 10:31:16 +0100
committerRichard Biener <rguenther@suse.de>2020-02-25 10:33:29 +0100
commit81c833b311b16cfd87a947374d5ffbbd48facd03 (patch)
tree31b6c240eeb1696e9c9baaa385713cf810f95779 /gcc/tree-vect-slp.c
parent2473c81cb2d4627f2d72310f4eca951c6084b596 (diff)
tree-optimization/93868 copy SLP tree before re-arranging stmts
This avoids altering possibly shared SLP subtrees when attempting to get rid of permutations in SLP reductions by copying the SLP subtree before re-arranging stmts in it. 2020-02-25 Richard Biener <rguenther@suse.de> PR tree-optimization/93868 * tree-vect-slp.c (slp_copy_subtree): New function. (vect_attempt_slp_rearrange_stmts): Copy the SLP tree before re-arranging stmts in it. * gcc.dg/torture/pr93868.c: New testcase.
Diffstat (limited to 'gcc/tree-vect-slp.c')
-rw-r--r--gcc/tree-vect-slp.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 71a24b78cf4..077c7946fee 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1749,6 +1749,44 @@ vect_mark_slp_stmts_relevant (slp_tree node)
vect_mark_slp_stmts_relevant (node, visited);
}
+/* Copy the SLP subtree rooted at NODE. */
+
+static slp_tree
+slp_copy_subtree (slp_tree node, hash_map<slp_tree, slp_tree> &map)
+{
+ unsigned i;
+
+ bool existed_p;
+ slp_tree &copy = map.get_or_insert (node, &existed_p);
+ if (existed_p)
+ return copy;
+
+ copy = XNEW (_slp_tree);
+ memcpy (copy, node, sizeof (_slp_tree));
+ if (SLP_TREE_SCALAR_STMTS (node).exists ())
+ {
+ SLP_TREE_SCALAR_STMTS (copy) = SLP_TREE_SCALAR_STMTS (node).copy ();
+ stmt_vec_info stmt_info;
+ FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info)
+ STMT_VINFO_NUM_SLP_USES (stmt_info)++;
+ }
+ if (SLP_TREE_SCALAR_OPS (node).exists ())
+ SLP_TREE_SCALAR_OPS (copy) = SLP_TREE_SCALAR_OPS (node).copy ();
+ if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
+ SLP_TREE_LOAD_PERMUTATION (copy) = SLP_TREE_LOAD_PERMUTATION (node).copy ();
+ if (SLP_TREE_CHILDREN (node).exists ())
+ SLP_TREE_CHILDREN (copy) = SLP_TREE_CHILDREN (node).copy ();
+ gcc_assert (!SLP_TREE_VEC_STMTS (node).exists ());
+ copy->refcnt = 0;
+
+ slp_tree child;
+ FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (copy), i, child)
+ {
+ SLP_TREE_CHILDREN (copy)[i] = slp_copy_subtree (child, map);
+ SLP_TREE_CHILDREN (copy)[i]->refcnt++;
+ }
+ return copy;
+}
/* Rearrange the statements of NODE according to PERMUTATION. */
@@ -1840,6 +1878,18 @@ vect_attempt_slp_rearrange_stmts (slp_instance slp_instn)
statements in the nodes is not important unless they are memory
accesses, we can rearrange the statements in all the nodes
according to the order of the loads. */
+
+ /* We have to unshare the SLP tree we modify. */
+ hash_map<slp_tree, slp_tree> map;
+ slp_tree unshared = slp_copy_subtree (SLP_INSTANCE_TREE (slp_instn), map);
+ vect_free_slp_tree (SLP_INSTANCE_TREE (slp_instn), false);
+ unshared->refcnt++;
+ SLP_INSTANCE_TREE (slp_instn) = unshared;
+ FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
+ SLP_INSTANCE_LOADS (slp_instn)[i] = *map.get (node);
+ node = SLP_INSTANCE_LOADS (slp_instn)[0];
+
+ /* Do the actual re-arrangement. */
hash_set<slp_tree> visited;
vect_slp_rearrange_stmts (SLP_INSTANCE_TREE (slp_instn), group_size,
node->load_permutation, visited);