The following fixes PR68379. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard. 2015-11-30 Richard Biener <rguent...@suse.de> PR tree-optimization/68379 * tree-vect-stmts.c (vectorizable_load): For BB vectorization always base loads on the first used DR of a group. * tree-vect-data-refs.c (vect_slp_analyze_and_verify_node_alignment): Compute alignment of the first scalar element unconditionally. * gcc.dg/torture/pr68379.c: New testcase. * gfortran.dg/pr68379-1.f90: Likewise. * gfortran.dg/pr68379-2.f: Likewise. Index: gcc/tree-vect-stmts.c =================================================================== --- gcc/tree-vect-stmts.c (revision 231065) +++ gcc/tree-vect-stmts.c (working copy) @@ -6130,6 +6133,7 @@ vectorizable_load (gimple *stmt, gimple_ bool grouped_load = false; bool load_lanes_p = false; gimple *first_stmt; + gimple *first_stmt_for_drptr = NULL; bool inv_p; bool negative = false; bool compute_in_loop = false; @@ -6733,10 +6737,14 @@ vectorizable_load (gimple *stmt, gimple_ if (grouped_load) { first_stmt = GROUP_FIRST_ELEMENT (stmt_info); - /* For BB vectorization we directly vectorize a subchain + /* For SLP 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]; + first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0]; + /* For BB vectorization always use the first stmt to base + the data ref pointer on. */ + if (bb_vinfo) + first_stmt_for_drptr = SLP_TREE_SCALAR_STMTS (slp_node)[0]; /* Check if the chain of loads is already vectorized. */ if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)) @@ -6948,6 +6956,24 @@ vectorizable_load (gimple *stmt, gimple_ (DR_REF (first_dr)), 0); inv_p = false; } + else if (first_stmt_for_drptr + && first_stmt != first_stmt_for_drptr) + { + dataref_ptr + = vect_create_data_ref_ptr (first_stmt_for_drptr, aggr_type, + at_loop, offset, &dummy, gsi, + &ptr_incr, simd_lane_access_p, + &inv_p, byte_offset); + /* Adjust the pointer by the difference to first_stmt. */ + data_reference_p ptrdr + = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt_for_drptr)); + tree diff = fold_convert (sizetype, + size_binop (MINUS_EXPR, + DR_INIT (first_dr), + DR_INIT (ptrdr))); + dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, + stmt, diff); + } else dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, at_loop, Index: gcc/testsuite/gcc.dg/torture/pr68379.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr68379.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr68379.c (working copy) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +int a, b[3], c[3][5]; + +void +fn1 () +{ + int e; + for (a = 2; a >= 0; a--) + for (e = 0; e < 4; e++) + c[a][e] = b[a]; +} Index: gcc/testsuite/gfortran.dg/pr68379-1.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr68379-1.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/pr68379-1.f90 (working copy) @@ -0,0 +1,35 @@ +! { dg-do compile } +! { dg-options "-O3" } +MODULE qs_efield_berry + TYPE cp_error_type + END TYPE + INTEGER, PARAMETER :: dp=8 + TYPE qs_energy_type + REAL(KIND=dp), POINTER :: efield + END TYPE + TYPE qs_environment_type + END TYPE + INTERFACE + SUBROUTINE foo(qs_env,energy,error) + IMPORT + TYPE(qs_environment_type), POINTER :: qs_env + TYPE(cp_error_type) :: error + TYPE(qs_energy_type), POINTER :: energy + END SUBROUTINE + END INTERFACE +CONTAINS + SUBROUTINE qs_efield_mo_derivatives() + TYPE(qs_environment_type), POINTER :: qs_env + TYPE(cp_error_type) :: error + COMPLEX(dp) :: zi(3), zphase(3) + REAL(dp) :: ci(3) + TYPE(qs_energy_type), POINTER :: energy + CALL foo(qs_env, energy, error) + zi = zi * zphase + ci = AIMAG(LOG(zi)) + DO idir=1,3 + ener_field=ener_field+ci(idir)*fieldfac(idir) + END DO + energy%efield=ener_field + END SUBROUTINE qs_efield_mo_derivatives +END MODULE qs_efield_berry Index: gcc/testsuite/gfortran.dg/pr68379-2.f =================================================================== --- gcc/testsuite/gfortran.dg/pr68379-2.f (revision 0) +++ gcc/testsuite/gfortran.dg/pr68379-2.f (working copy) @@ -0,0 +1,24 @@ +! { dg-do compile } +! { dg-additional-options "-Ofast" } +! { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } } + + SUBROUTINE PASSB4 (IDO,L1,CC,CH,WA1,WA2,WA3) + IMPLICIT REAL(4) (A-H, O-Z) + DIMENSION CC(IDO,4,L1), CH(IDO,L1,4), WA1(*), WA2(*), WA3(*) + 102 DO 104 K=1,L1 + DO 103 I=2,IDO,2 + TI1 = CC(I,1,K)-CC(I,3,K) + TI2 = CC(I,1,K)+CC(I,3,K) + TI3 = CC(I,2,K)+CC(I,4,K) + TR2 = CC(I-1,1,K)+CC(I-1,3,K) + TI4 = CC(I-1,2,K)-CC(I-1,4,K) + TR3 = CC(I-1,2,K)+CC(I-1,4,K) + CH(I-1,K,1) = TR2+TR3 + CH(I,K,1) = TI2+TI3 + CI4 = TI1-TI4 + CH(I-1,K,4) = CI4 + CH(I,K,4) = CI4 + 103 CONTINUE + 104 CONTINUE + RETURN + END Index: gcc/tree-vect-data-refs.c =================================================================== --- gcc/tree-vect-data-refs.c (revision 231101) +++ gcc/tree-vect-data-refs.c (working copy) @@ -2102,11 +2102,16 @@ vect_slp_analyze_and_verify_node_alignme 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]; + data_reference_p first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)); 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) + /* For creating the data-ref pointer we need alignment of the + first element anyway. */ + || (dr != first_dr + && ! vect_compute_data_ref_alignment (first_dr)) || ! verify_data_ref_alignment (dr)) { if (dump_enabled_p ())