This fixes more of PR68306. Digging into the details reveals that we only need to check a single (but the correct one) DR and that cost modeling also gets this wrong.
Thus fixed. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2015-11-13 Richard Biener <rguent...@suse.de> PR tree-optimization/68306 * tree-vect-data-refs.c (verify_data_ref_alignment): Move loop related checks ... (vect_verify_datarefs_alignment): ... here. (vect_slp_analyze_and_verify_node_alignment): Compute and verify alignment of the single DR that it matters. * tree-vect-stmts.c (vectorizable_store): Add an assert. (vectorizable_load): Add a comment. * tree-vect-slp.c (vect_analyze_slp_cost_1): Fix DR used for determining load cost. * gcc.dg/pr68306.c: Adjust. * gcc.dg/pr68306-2.c: New testcase. * gcc.dg/pr68306-3.c: Likewise. Index: gcc/tree-vect-data-refs.c =================================================================== *** gcc/tree-vect-data-refs.c (revision 230293) --- gcc/tree-vect-data-refs.c (working copy) *************** verify_data_ref_alignment (data_referenc *** 920,936 **** gimple *stmt = DR_STMT (dr); stmt_vec_info stmt_info = vinfo_for_stmt (stmt); - /* For interleaving, only the alignment of the first access matters. */ - if (STMT_VINFO_GROUPED_ACCESS (stmt_info) - && GROUP_FIRST_ELEMENT (stmt_info) != stmt) - return true; - - /* Strided accesses perform only component accesses, alignment is - irrelevant for them. */ - if (STMT_VINFO_STRIDED_P (stmt_info) - && !STMT_VINFO_GROUPED_ACCESS (stmt_info)) - return true; - supportable_dr_alignment = vect_supportable_dr_alignment (dr, false); if (!supportable_dr_alignment) { --- 920,925 ---- *************** vect_verify_datarefs_alignment (loop_vec *** 977,982 **** --- 966,983 ---- if (!STMT_VINFO_RELEVANT_P (stmt_info)) continue; + + /* For interleaving, only the alignment of the first access matters. */ + if (STMT_VINFO_GROUPED_ACCESS (stmt_info) + && GROUP_FIRST_ELEMENT (stmt_info) != stmt) + return true; + + /* Strided accesses perform only component accesses, alignment is + irrelevant for them. */ + if (STMT_VINFO_STRIDED_P (stmt_info) + && !STMT_VINFO_GROUPED_ACCESS (stmt_info)) + return true; + if (! verify_data_ref_alignment (dr)) return false; } *************** vect_analyze_data_refs_alignment (loop_v *** 2100,2127 **** static bool vect_slp_analyze_and_verify_node_alignment (slp_tree node) { ! unsigned i; ! gimple *stmt; ! FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt) { ! stmt_vec_info stmt_info = vinfo_for_stmt (stmt); ! ! /* Strided accesses perform only component accesses, misalignment ! information is irrelevant for them. */ ! if (STMT_VINFO_STRIDED_P (stmt_info) ! && !STMT_VINFO_GROUPED_ACCESS (stmt_info)) ! continue; ! ! data_reference_p dr = STMT_VINFO_DATA_REF (stmt_info); ! if (! vect_compute_data_ref_alignment (dr) ! || ! verify_data_ref_alignment (dr)) ! { ! if (dump_enabled_p ()) ! dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, ! "not vectorized: bad data alignment in basic " ! "block.\n"); ! return false; ! } } return true; --- 2101,2122 ---- static bool vect_slp_analyze_and_verify_node_alignment (slp_tree node) { ! /* We vectorize from the first scalar stmt in the node unless ! the node is permuted in which case we start from the first ! element in the group. */ ! gimple *first_stmt = SLP_TREE_SCALAR_STMTS (node)[0]; ! if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) ! first_stmt = GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt)); ! ! data_reference_p dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)); ! if (! vect_compute_data_ref_alignment (dr) ! || ! verify_data_ref_alignment (dr)) { ! if (dump_enabled_p ()) ! dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, ! "not vectorized: bad data alignment in basic " ! "block.\n"); ! return false; } return true; Index: gcc/tree-vect-stmts.c =================================================================== *** gcc/tree-vect-stmts.c (revision 230293) --- gcc/tree-vect-stmts.c (working copy) *************** vectorizable_store (gimple *stmt, gimple *** 5464,5469 **** --- 5464,5470 ---- group. */ vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0]; + gcc_assert (GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt)) == first_stmt); first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)); op = gimple_assign_rhs1 (first_stmt); } *************** vectorizable_load (gimple *stmt, gimple_ *** 6658,6666 **** if (grouped_load) { first_stmt = GROUP_FIRST_ELEMENT (stmt_info); ! if (slp ! && !SLP_TREE_LOAD_PERMUTATION (slp_node).exists () ! && first_stmt != SLP_TREE_SCALAR_STMTS (slp_node)[0]) first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0]; /* Check if the chain of loads is already vectorized. */ --- 6659,6667 ---- if (grouped_load) { first_stmt = GROUP_FIRST_ELEMENT (stmt_info); ! /* For BB vectorization we directly vectorize a subchain ! without permutation. */ ! if (slp && ! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ()) first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0]; /* Check if the chain of loads is already vectorized. */ Index: gcc/tree-vect-slp.c =================================================================== *** gcc/tree-vect-slp.c (revision 230293) --- gcc/tree-vect-slp.c (working copy) *************** vect_analyze_slp_cost_1 (slp_instance in *** 1429,1434 **** --- 1429,1441 ---- { int i; gcc_checking_assert (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info))); + /* If the load is permuted then the alignment is determined by + the first group element not by the first scalar stmt DR. */ + if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) + { + stmt = GROUP_FIRST_ELEMENT (stmt_info); + stmt_info = vinfo_for_stmt (stmt); + } vect_model_load_cost (stmt_info, ncopies_for_cost, false, node, prologue_cost_vec, body_cost_vec); /* If the load is permuted record the cost for the permutation. Index: gcc/testsuite/gcc.dg/pr68306.c =================================================================== *** gcc/testsuite/gcc.dg/pr68306.c (revision 230293) --- gcc/testsuite/gcc.dg/pr68306.c (working copy) *************** *** 1,5 **** --- 1,6 ---- /* { dg-do compile } */ /* { dg-options "-O3" } */ + /* { dg-additional-options "-mno-sse -mno-mmx" { target x86_64-*-* } } */ enum powerpc_pmc_type { PPC_PMC_IBM }; struct { Index: gcc/testsuite/gcc.dg/pr68306-2.c =================================================================== *** gcc/testsuite/gcc.dg/pr68306-2.c (revision 0) --- gcc/testsuite/gcc.dg/pr68306-2.c (revision 0) *************** *** 0 **** --- 1,12 ---- + /* { dg-do compile } */ + /* { dg-options "-O3" } */ + /* { dg-additional-options "-mno-sse -mno-mmx" { target x86_64-*-* } } */ + + struct { + int tz_minuteswest; + int tz_dsttime; + } a, b; + void fn1() { + b.tz_minuteswest = a.tz_minuteswest; + b.tz_dsttime = a.tz_dsttime; + } Index: gcc/testsuite/gcc.dg/pr68306-3.c =================================================================== *** gcc/testsuite/gcc.dg/pr68306-3.c (revision 0) --- gcc/testsuite/gcc.dg/pr68306-3.c (revision 0) *************** *** 0 **** --- 1,21 ---- + /* { dg-do compile } */ + /* { dg-options "-O3" } */ + /* { dg-additional-options "-mno-sse -mno-mmx" { target x86_64-*-* } } */ + /* { dg-additional-options "-mno-altivec -mno-vsx" { target powerpc*-*-* } } */ + + extern void fn2(); + struct { + unsigned qp_num; + unsigned starting_psn; + void *private_data; + } a; + struct { + unsigned id; + unsigned qpn; + unsigned psn; + } b; + void fn1() { + a.qp_num = b.qpn; + a.starting_psn = b.psn; + fn2(b.id); + }