https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59354
--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, we SLP the first block node stmt 0 b[_17] = _24; stmt 1 b[_3] = _50; stmt 2 b[_93] = _99; stmt 3 b[_104] = _110; node stmt 0 _24 = (unsigned char) _23; stmt 1 _50 = (unsigned char) _63; stmt 2 _99 = (unsigned char) _98; stmt 3 _110 = (unsigned char) _109; node stmt 0 _23 = a[_21]; stmt 1 _63 = a[_64]; stmt 2 _98 = a[_97]; stmt 3 _109 = a[_108]; and for all other instances claim the load permutation is not supported. For the stmts visble above the load permutation _is_ 1:1, but as we need to gobble up more loads due to the truncation the effective SLP group we deal with has gaps (bah, the gaps code...) Thus the underlying issue is that we have t.c:13:3: note: Detected interleaving of size 16 t.c:13:3: note: Detected interleaving of size 4 t.c:13:3: note: Detected interleaving of size 4 t.c:13:3: note: Detected interleaving of size 4 t.c:13:3: note: Detected interleaving of size 4 with the group-size of the stores (4) determining the SLP group size but the analysis code being confused by the non-matching group size of the loads. In the end we should probably split up the groups if a single group ends up being refered to in different SLP instances (thus also postpone most of the dependence-kind tests until after SLP discovery). Let's see if a simple workaround doesn't regress anything. Index: gcc/tree-vect-slp.c =================================================================== --- gcc/tree-vect-slp.c (revision 219581) +++ gcc/tree-vect-slp.c (working copy) @@ -729,8 +729,11 @@ vect_build_slp_tree_1 (loop_vec_info loo ??? We should enhance this to only disallow gaps inside vectors. */ if ((unrolling_factor > 1 - && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt - && GROUP_GAP (vinfo_for_stmt (stmt)) != 0) + && ((GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt + && GROUP_GAP (vinfo_for_stmt (stmt)) != 0) + /* If the group is split up then GROUP_GAP + isn't correct here, nor is GROUP_FIRST_ELEMENT. */ + || GROUP_SIZE (vinfo_for_stmt (stmt)) > group_size)) || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt && GROUP_GAP (vinfo_for_stmt (stmt)) != 1)) {