This patch fixes PR52678 - re-computing the evolution of a loop PHI node after updating it during prologue loop peeling is fragile (and I remember several cases in the past where we ICEd here and adjusted the code). So, instead of re-computing the evolution this patch saves the evolution part at analysis time and re-uses it at this place.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-03-23 Richard Guenther <rguent...@suse.de> PR tree-optimization/52678 * tree-vectorizer.h (struct _stmt_vec_info): Add loop_phi_evolution_part member. (STMT_VINFO_LOOP_PHI_EVOLUTION_PART): New define. * tree-vect-loop.c (vect_analyze_scalar_cycles_1): Initialize STMT_VINFO_LOOP_PHI_EVOLUTION_PART. * tree-vect-loop-manip.c (vect_update_ivs_after_vectorizer): Use the cached evolution part and the PHI nodes value from the loop preheader edge instead of re-analyzing the evolution. * gfortran.dg/pr52678.f: New testcase. Index: gcc/tree-vectorizer.h =================================================================== *** gcc/tree-vectorizer.h (revision 185724) --- gcc/tree-vectorizer.h (working copy) *************** typedef struct _stmt_vec_info { *** 476,481 **** --- 476,488 ---- tree dr_step; tree dr_aligned_to; + /* For loop PHI nodes, the evolution part of it. This makes sure + this information is still available in vect_update_ivs_after_vectorizer + where we may not be able to re-analyze the PHI nodes evolution as + peeling for the prologue loop can make it unanalyzable. The evolution + part is still correct though. */ + tree loop_phi_evolution_part; + /* Used for various bookkeeping purposes, generally holding a pointer to some other stmt S that is in some way "related" to this stmt. Current use of this field is: *************** typedef struct _stmt_vec_info { *** 572,577 **** --- 579,585 ---- #define STMT_VINFO_GROUP_SAME_DR_STMT(S) (S)->same_dr_stmt #define STMT_VINFO_GROUP_READ_WRITE_DEPENDENCE(S) (S)->read_write_dep #define STMT_VINFO_STRIDED_ACCESS(S) ((S)->first_element != NULL && (S)->data_ref_info) + #define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part #define GROUP_FIRST_ELEMENT(S) (S)->first_element #define GROUP_NEXT_ELEMENT(S) (S)->next_element Index: gcc/tree-vect-loop.c =================================================================== *** gcc/tree-vect-loop.c (revision 185724) --- gcc/tree-vect-loop.c (working copy) *************** vect_analyze_scalar_cycles_1 (loop_vec_i *** 579,584 **** --- 579,588 ---- continue; } + STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo) + = evolution_part_in_loop_num (access_fn, loop->num); + gcc_assert (STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_vinfo) != NULL_TREE); + if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "Detected induction."); STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def; Index: gcc/tree-vect-loop-manip.c =================================================================== *** gcc/tree-vect-loop-manip.c (revision 185724) --- gcc/tree-vect-loop-manip.c (working copy) *************** vect_update_ivs_after_vectorizer (loop_v *** 1797,1809 **** !gsi_end_p (gsi) && !gsi_end_p (gsi1); gsi_next (&gsi), gsi_next (&gsi1)) { - tree access_fn = NULL; - tree evolution_part; tree init_expr; tree step_expr, off; tree type; tree var, ni, ni_name; gimple_stmt_iterator last_gsi; phi = gsi_stmt (gsi); phi1 = gsi_stmt (gsi1); --- 1797,1808 ---- !gsi_end_p (gsi) && !gsi_end_p (gsi1); gsi_next (&gsi), gsi_next (&gsi1)) { tree init_expr; tree step_expr, off; tree type; tree var, ni, ni_name; gimple_stmt_iterator last_gsi; + stmt_vec_info stmt_info; phi = gsi_stmt (gsi); phi1 = gsi_stmt (gsi1); *************** vect_update_ivs_after_vectorizer (loop_v *** 1822,1866 **** } /* Skip reduction phis. */ ! if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (phi)) == vect_reduction_def) { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "reduc phi. skip."); continue; } ! access_fn = analyze_scalar_evolution (loop, PHI_RESULT (phi)); ! gcc_assert (access_fn); ! /* We can end up with an access_fn like ! (short int) {(short unsigned int) i_49, +, 1}_1 ! for further analysis we need to strip the outer cast but we ! need to preserve the original type. */ ! type = TREE_TYPE (access_fn); ! STRIP_NOPS (access_fn); ! evolution_part = ! unshare_expr (evolution_part_in_loop_num (access_fn, loop->num)); ! gcc_assert (evolution_part != NULL_TREE); /* FORNOW: We do not support IVs whose evolution function is a polynomial of degree >= 2 or exponential. */ ! gcc_assert (!tree_is_chrec (evolution_part)); ! step_expr = evolution_part; ! init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, ! loop->num)); ! init_expr = fold_convert (type, init_expr); off = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr), fold_convert (TREE_TYPE (step_expr), niters), step_expr); ! if (POINTER_TYPE_P (TREE_TYPE (init_expr))) ni = fold_build_pointer_plus (init_expr, off); else ! ni = fold_build2 (PLUS_EXPR, TREE_TYPE (init_expr), ! init_expr, ! fold_convert (TREE_TYPE (init_expr), off)); ! var = create_tmp_var (TREE_TYPE (init_expr), "tmp"); add_referenced_var (var); last_gsi = gsi_last_bb (exit_bb); --- 1821,1854 ---- } /* Skip reduction phis. */ ! stmt_info = vinfo_for_stmt (phi); ! if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def) { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "reduc phi. skip."); continue; } ! type = TREE_TYPE (gimple_phi_result (phi)); ! step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_info); ! step_expr = unshare_expr (step_expr); /* FORNOW: We do not support IVs whose evolution function is a polynomial of degree >= 2 or exponential. */ ! gcc_assert (!tree_is_chrec (step_expr)); ! init_expr = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop)); off = fold_build2 (MULT_EXPR, TREE_TYPE (step_expr), fold_convert (TREE_TYPE (step_expr), niters), step_expr); ! if (POINTER_TYPE_P (type)) ni = fold_build_pointer_plus (init_expr, off); else ! ni = fold_build2 (PLUS_EXPR, type, ! init_expr, fold_convert (type, off)); ! var = create_tmp_var (type, "tmp"); add_referenced_var (var); last_gsi = gsi_last_bb (exit_bb); Index: gcc/testsuite/gfortran.dg/pr52678.f =================================================================== *** gcc/testsuite/gfortran.dg/pr52678.f (revision 0) --- gcc/testsuite/gfortran.dg/pr52678.f (revision 0) *************** *** 0 **** --- 1,18 ---- + ! { dg-do compile } + ! { dg-options "-O -ftree-vectorize" } + SUBROUTINE OpenAD_set_ref_state(DRF, RHOFACF, RHOFACC) + real(8) DRF(1 : 15) + real(8) RHOFACF(1 : 16) + real(8) RHOFACC(1 : 15) + integer, dimension(:), allocatable :: oad_it + integer :: oad_it_ptr + INTEGER(8) OpenAD_Symbol_188 + INTEGER(4) K + OpenAD_Symbol_188 = 0 + DO K = 2, 15, 1 + RHOFACF(INT(K)) = ((RHOFACC(K) * DRF(K + (-1)) + RHOFACC(K + + + (-1)) * DRF(K)) /(DRF(K) + DRF(K + (-1)))) + OpenAD_Symbol_188 = (INT(OpenAD_Symbol_188) + INT(1)) + END DO + oad_it(oad_it_ptr) = OpenAD_Symbol_188 + end subroutine OpenAD_set_ref_state