Hi All, This moves the code that checks for load/store lanes further in the pipeline and places it after slp_optimize. This would allow us to perform optimizations on the SLP tree and only bail out if we really have a permute.
With this change it allows us to handle permutes such as {1,1,1,1} which should be handled by a load and replicate. This change however makes it all or nothing. Either all instances can be handled or none at all. This is why some of the test cases have been adjusted. Bootstrapped Regtested on aarch64-none-linux-gnu, -x86_64-pc-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/ChangeLog: * tree-vect-slp.c (vect_analyze_slp_instance): Moved load/store lanes check to ... * tree-vect-loop.c (vect_analyze_loop_2): ..Here gcc/testsuite/ChangeLog: * gcc.dg/vect/slp-11b.c: Update output scan. * gcc.dg/vect/slp-perm-6.c: Likewise. --
diff --git a/gcc/testsuite/gcc.dg/vect/slp-11b.c b/gcc/testsuite/gcc.dg/vect/slp-11b.c index 0cc23770badf0e00ef98769a2dd14a92dca32cca..fe5bb0c3ce7682c7cef1313e342d95aba3fe11b2 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-11b.c +++ b/gcc/testsuite/gcc.dg/vect/slp-11b.c @@ -45,4 +45,4 @@ int main (void) /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided4 && vect_int_mult } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided4 && vect_int_mult } } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */ +/* { dg-final { scan-tree-dump-times "re-trying with SLP disabled" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c index 38489291a2659c989121d44c9e9e7bdfaa12f868..07bf8916de7ce88bbb1d65437f8bf6d8ab17efe6 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c @@ -106,7 +106,7 @@ int main (int argc, const char* argv[]) /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && {! vect_partial_vectors_usage_1 } } } } } } */ /* The epilogues are vectorized using partial vectors. */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_perm3_int && { {! vect_load_lanes } && vect_partial_vectors_usage_1 } } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_load_lanes } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "Built SLP cancelled: can use load/store-lanes" "vect" { target { vect_perm3_int && vect_load_lanes } } } } */ /* { dg-final { scan-tree-dump "LOAD_LANES" "vect" { target vect_load_lanes } } } */ /* { dg-final { scan-tree-dump "STORE_LANES" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 991fd4572298448c5d074f87a4ed318f0a3c9db6..c1350a8008850ea5e21a27cacd7e340d0da9bc9c 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2342,6 +2342,60 @@ start_over: "unsupported SLP instances\n"); goto again; } + + /* Check whether any load is possibly permuted. */ + slp_tree load_node, slp_root; + unsigned i, x; + slp_instance instance; + FOR_EACH_VEC_ELT (LOOP_VINFO_SLP_INSTANCES (loop_vinfo), x, instance) + { + bool loads_permuted = false; + slp_root = SLP_INSTANCE_TREE (instance); + int group_size = SLP_TREE_LANES (slp_root); + tree vectype = SLP_TREE_VECTYPE (slp_root); + + FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, load_node) + { + if (!SLP_TREE_LOAD_PERMUTATION (load_node).exists ()) + continue; + unsigned j; + stmt_vec_info load_info; + FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load_info) + if (SLP_TREE_LOAD_PERMUTATION (load_node)[j] != j) + { + loads_permuted = true; + break; + } + } + + /* If the loads and stores can be handled with load/store-lane + instructions do not generate this SLP instance. */ + if (loads_permuted + && vect_store_lanes_supported (vectype, group_size, false)) + { + FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, load_node) + { + stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT + (SLP_TREE_SCALAR_STMTS (load_node)[0]); + /* Use SLP for strided accesses (or if we can't + load-lanes). */ + if (STMT_VINFO_STRIDED_P (stmt_vinfo) + || ! vect_load_lanes_supported + (STMT_VINFO_VECTYPE (stmt_vinfo), + DR_GROUP_SIZE (stmt_vinfo), false)) + break; + } + + if (i == SLP_INSTANCE_LOADS (instance).length ()) + { + ok = opt_result::failure_at (vect_location, + "Built SLP cancelled: can use" + " load/store-lanes\n"); + goto again; + } + } + } + } /* Dissolve SLP-only groups. */ diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index c3e6d67067cbf8ca77be54df8a1b954a347e0eb0..88487cc2909a6b31f7d9bf6348ba249247e4150c 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2183,52 +2183,6 @@ vect_analyze_slp_instance (vec_info *vinfo, "SLP size %u vs. limit %u.\n", tree_size, max_tree_size); - /* Check whether any load is possibly permuted. */ - slp_tree load_node; - bool loads_permuted = false; - FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (new_instance), i, load_node) - { - if (!SLP_TREE_LOAD_PERMUTATION (load_node).exists ()) - continue; - unsigned j; - stmt_vec_info load_info; - FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (load_node), j, load_info) - if (SLP_TREE_LOAD_PERMUTATION (load_node)[j] != j) - { - loads_permuted = true; - break; - } - } - - /* If the loads and stores can be handled with load/store-lane - instructions do not generate this SLP instance. */ - if (is_a <loop_vec_info> (vinfo) - && loads_permuted - && dr && vect_store_lanes_supported (vectype, group_size, false)) - { - slp_tree load_node; - FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (new_instance), i, load_node) - { - stmt_vec_info stmt_vinfo = DR_GROUP_FIRST_ELEMENT - (SLP_TREE_SCALAR_STMTS (load_node)[0]); - /* Use SLP for strided accesses (or if we can't load-lanes). */ - if (STMT_VINFO_STRIDED_P (stmt_vinfo) - || ! vect_load_lanes_supported - (STMT_VINFO_VECTYPE (stmt_vinfo), - DR_GROUP_SIZE (stmt_vinfo), false)) - break; - } - if (i == SLP_INSTANCE_LOADS (new_instance).length ()) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "Built SLP cancelled: can use " - "load/store-lanes\n"); - vect_free_slp_instance (new_instance); - return false; - } - } - /* If this is a reduction chain with a conversion in front amend the SLP tree with a node for that. */ if (!dr