diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index c03fc2fbecad1a2219504ac9daae75495e691775..48f615e1952707de4827f0e69e443c0a7db27d81 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -290,6 +290,27 @@ vect_slp_tree_uniform_p (slp_tree node) return true; } +/* Return true when the node is a permute node and the permutation the node + contains is a no-op. */ + +static bool +vect_slp_tree_permute_noop_p (slp_tree node) +{ + gcc_assert (SLP_TREE_CODE (node) == VEC_PERM_EXPR); + + if (!SLP_TREE_LANE_PERMUTATION (node).exists ()) + return true; + + unsigned x, seed; + lane_permutation_t perms = SLP_TREE_LANE_PERMUTATION (node); + seed = perms[0].second; + for (x = 1; x < perms.length (); x++) + if (perms[x].first != perms[0].first || perms[x].second != ++seed) + return false; + + return true; +} + /* Find the place of the data-ref in STMT_INFO in the interleaving chain that starts from FIRST_STMT_INFO. Return -1 if the data-ref is not a part of the chain. */ @@ -3150,6 +3171,41 @@ vect_optimize_slp (vec_info *vinfo) /* For loads simply drop the permutation, the load permutation already performs the desired permutation. */ ; + else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) + { + /* If the node if already a permute node we just need to apply + the permutation to the permute node itself. */ + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "simplifying permute node %p\n", + node); + + vect_slp_permute (perms[perm], SLP_TREE_LANE_PERMUTATION (node), + true); + + /* If the remaining permute is a no-op then we can just drop the + node instead of materializing it. */ + if (vect_slp_tree_permute_noop_p (node)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "removing unneeded permute node %p\n", + node); + + unsigned idx = SLP_TREE_LANE_PERMUTATION (node)[0].first; + slp_tree value = SLP_TREE_CHILDREN (node)[idx]; + unsigned src = slpg->vertices[node->vertex].pred->src; + slp_tree prev = vertices[src]; + unsigned dest; + slp_tree tmp; + FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (prev), dest, tmp) + if (tmp == node) + { + SLP_TREE_CHILDREN (prev)[dest] = value; + break; + } + } + } else { if (dump_enabled_p ()) @@ -5361,7 +5417,7 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "permutation requires at " - "least three vectors"); + "least three vectors\n"); gcc_assert (!gsi); return false; }