diff options
author | Richard Biener <rguenther@suse.de> | 2020-02-25 10:31:16 +0100 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2020-02-25 10:33:29 +0100 |
commit | 81c833b311b16cfd87a947374d5ffbbd48facd03 (patch) | |
tree | 31b6c240eeb1696e9c9baaa385713cf810f95779 /gcc/tree-vect-slp.c | |
parent | 2473c81cb2d4627f2d72310f4eca951c6084b596 (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.c | 50 |
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 © = 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); |