On Fri, 8 Jan 2016, Alan Lawrence wrote: > Here's an alternative patch, using the hunk from > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68707#c16, which 'improves' (heh, > we think) on the previous by allowing SLP to proceed where the loads are > strided, for example, slp-perm-11.c. Also I fix the testsuite failures > (looking > for SLP where we've now decided to do load/store-lanes instead). I used simple > scan-tree-dump (rather than -times) because load_lanes typically appears many > times in the log for each instance output, and it felt fragile to look for a > specific number. > > Note, this doesn't fix PR67323 - that's an example where unpermuted SLP is > still (a bit) worse than load-lanes, as it needs unrolling * 2. The > previously-posted patch doesn't fix this either, however > (https://gcc.gnu.org/ml/gcc-patches/2015-12/msg01620.html). > > Bootstrapped + check-gcc + check-g++ on x86_64 (no changes), arm and aarch64 > (various new scan-tree-dump tests all passing, and PASS->FAIL for > O3-pr36098.c).
Looks good to me. Ok if arm maintainers agree. Thanks, Richard. > gcc/ChangeLog: > > 2016-01-XX Alan Lawrence <alan.lawre...@arm.com> > Richard Biener <rguent...@suse.de> > > * tree-vect-slp.c (vect_analyze_slp_instance): Cancel permuted SLP > instances that can be handled via vect_load_lanes. > > gcc/testsuite/ChangeLog: > > * lib/target-supports.exp (check_effective_target_vect_load_lanes): New. > * gcc.dg/vect/slp-perm-1.c: Look for vect_load_lanes instead of SLP > on platforms supporting it. > * gcc.dg/vect/slp-perm-2.c: Likewise. > * gcc.dg/vect/slp-perm-3.c: Likewise. > * gcc.dg/vect/slp-perm-5.c: Likewise. > * gcc.dg/vect/slp-perm-7.c: Likewise. > * gcc.dg/vect/slp-perm-8.c: Likewise. > * gcc.dg/vect/slp-perm-6.c: Look for vect_load_lanes in addition to SLP > on platforms supporting it. > --- > gcc/testsuite/gcc.dg/vect/slp-perm-1.c | 6 +++++- > gcc/testsuite/gcc.dg/vect/slp-perm-2.c | 7 +++++-- > gcc/testsuite/gcc.dg/vect/slp-perm-3.c | 7 +++++-- > gcc/testsuite/gcc.dg/vect/slp-perm-5.c | 7 +++++-- > gcc/testsuite/gcc.dg/vect/slp-perm-6.c | 7 +++++-- > gcc/testsuite/gcc.dg/vect/slp-perm-7.c | 8 +++++--- > gcc/testsuite/gcc.dg/vect/slp-perm-8.c | 7 +++++-- > gcc/testsuite/lib/target-supports.exp | 19 +++++++++++++++++++ > gcc/tree-vect-slp.c | 30 ++++++++++++++++++++++++++++++ > 9 files changed, 84 insertions(+), 14 deletions(-) > > diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c > index 2b6c134..6d0d66f 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-1.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-1.c > @@ -58,5 +58,9 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_perm } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-2.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-2.c > index da50e16..34b413d 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-2.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-2.c > @@ -54,5 +54,8 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_perm } } } */ > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-3.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-3.c > index 1d33f9b..ec13e0f 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-3.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-3.c > @@ -67,6 +67,9 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_perm } } } */ > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-5.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c > index 9ed4d724..f44f44f 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-5.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-5.c > @@ -73,6 +73,9 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" > { target vect_perm } } } */ > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-6.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c > index 392d36f..551734a 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-6.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-6.c > @@ -72,5 +72,8 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" > { target vect_perm } } } */ > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-7.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c > index 4352334..8b66142 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-7.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-7.c > @@ -71,6 +71,8 @@ int main (int argc, const char* argv[]) > } > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target > vect_perm } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_perm } } } */ > - > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target { vect_perm && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm && 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/testsuite/gcc.dg/vect/slp-perm-8.c > b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c > index 3bdd150..b1e9a10 100644 > --- a/gcc/testsuite/gcc.dg/vect/slp-perm-8.c > +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c > @@ -54,5 +54,8 @@ int main (int argc, const char* argv[]) > > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target > { vect_perm_byte && vect_char_mult } } } } */ > /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target > { vect_perm_byte && {! vect_char_mult } } } } } */ > -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target vect_perm_byte } } } */ > - > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" > { target { vect_perm_byte && {! vect_load_lanes } } } } } */ > +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" > { target vect_load_lanes } } } */ > +/* { dg-final { scan-tree-dump "note: Built SLP cancelled: can use > load/store-lanes" { target { vect_perm_byte && 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/testsuite/lib/target-supports.exp > b/gcc/testsuite/lib/target-supports.exp > index 4e349e9..0e6d2b6 100644 > --- a/gcc/testsuite/lib/target-supports.exp > +++ b/gcc/testsuite/lib/target-supports.exp > @@ -4823,6 +4823,25 @@ proc check_effective_target_vect_element_align { } { > return $et_vect_element_align > } > > +# Return 1 if the target supports vector LOAD_LANES operations, 0 otherwise. > + > +proc check_effective_target_vect_load_lanes { } { > + global et_vect_load_lanes > + > + if [info exists et_vect_load_lanes] { > + verbose "check_effective_target_vect_load_lanes: using cached result" 2 > + } else { > + set et_vect_load_lanes 0 > + if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) > + || [istarget aarch64*-*-*] } { > + set et_vect_load_lanes 1 > + } > + } > + > + verbose "check_effective_target_vect_load_lanes: returning > $et_vect_load_lanes" 2 > + return $et_vect_load_lanes > +} > + > # Return 1 if the target supports vector conditional operations, 0 otherwise. > > proc check_effective_target_vect_condition { } { > diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c > index b893682..b53767f 100644 > --- a/gcc/tree-vect-slp.c > +++ b/gcc/tree-vect-slp.c > @@ -1793,6 +1793,36 @@ vect_analyze_slp_instance (vec_info *vinfo, > } > } > > + /* 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)) > + { > + slp_tree load_node; > + FOR_EACH_VEC_ELT (loads, i, load_node) > + { > + gimple *first_stmt = GROUP_FIRST_ELEMENT > + (vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (load_node)[0])); > + stmt_vec_info stmt_vinfo = vinfo_for_stmt (first_stmt); > + /* 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), > + GROUP_SIZE (stmt_vinfo))) > + break; > + } > + if (i == loads.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; > + } > + } > + > vinfo->slp_instances.safe_push (new_instance); > > if (dump_enabled_p ()) > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)